Răsfoiți Sursa

ENH: unify make process on unix

Bill Hoffman 24 ani în urmă
părinte
comite
1cd9ce6f6e

+ 21 - 7
CMakeSystemConfig.cmake.in

@@ -2,10 +2,24 @@
 # CMakeLocal.make.in should be in the directory where you run configure
 # in, which need not be the source directory
 #
-SET (CMAKE_WORDS_BIGENDIAN @CMAKE_WORDS_BIGENDIAN@)
-SET (CMAKE_USE_SPROC       @CMAKE_USE_SPROC@)
-SET (CMAKE_USE_PTHREADS    @CMAKE_USE_PTHREADS@)
-SET (CMAKE_HP_PTHREADS     @CMAKE_HP_PTHREADS@)
-SET (CXX                   @CXX@)
-SET (CMAKE_THREAD_LIBS     @CMAKE_THREAD_LIBS@)
-SET (CMAKE_DL_LIBS         @CMAKE_DL_LIBS@)
+SET (CMAKE_WORDS_BIGENDIAN    @CMAKE_WORDS_BIGENDIAN@ )
+SET (CMAKE_USE_SPROC          @CMAKE_USE_SPROC@ CACHE BOOL)
+SET (CMAKE_USE_PTHREADS       @CMAKE_USE_PTHREADS@ CACHE BOOL)
+SET (CMAKE_HP_PTHREADS        @CMAKE_HP_PTHREADS@ CACHE BOOL)
+SET (CMAKE_CXX                @CXX@ CACHE FILEPATH)
+SET (CMAKE_CC                 @CC@ CACHE FILEPATH)
+SET (CMAKE_RANLIB             @RANLIB@ CACHE STRING)
+SET (CMAKE_AR                 @CMAKE_AR@ CACHE STRING)
+SET (CMAKE_THREAD_LIBS        @CMAKE_THREAD_LIBS@ CACHE STRING)
+SET (CMAKE_DL_LIBS            @CMAKE_DL_LIBS@ CACHE STRING)
+SET (CMAKE_CXX_FLAGS          "@CXXFLAGS@" CACHE STRING)
+SET (CMAKE_CC_FLAGS           "@CFLAGS@" CACHE STRING)
+SET (CMAKE_SHLIB_CFLAGS       @CMAKE_SHLIB_CFLAGS@ CACHE STRING)
+SET (CMAKE_SHLIB_BUILD_FLAGS  @CMAKE_SHLIB_BUILD_FLAGS@ CACHE STRING)
+SET (CMAKE_SHLIB_LD_LIBS      @CMAKE_SHLIB_LD_LIBS@ CACHE STRING)
+SET (CMAKE_SHLIB_SUFFIX       @CMAKE_SHLIB_SUFFIX@ CACHE STRING)
+SET (CMAKE_CPP_FLAGS          @CPPFLAGS@ CACHE STRING)
+SET (CMAKE_TEMPLATE_FLAGS     @CMAKE_TEMPLATE_FLAGS@ CACHE STRING)
+SET (CMAKE_C_COMPILER         @CC@ CACHE FILEPATH)
+SET (CMAKE_SHLIB_LINK_FLAGS   @CMAKE_SHLIB_LINK_FLAGS@ CACHE STRING)
+SET (CMAKE_LIB_EXT            @CMAKE_LIB_EXT@ CACHE STRING)

+ 10 - 1
Source/MFCDialog/CMakeSetupDialog.cpp

@@ -353,7 +353,16 @@ void CMakeSetupDialog::OnBuildProjects()
   makefile.MakeStartDirectoriesCurrent();
   CString makefileIn = m_WhereSource;
   makefileIn += "/CMakeLists.txt";
-  makefile.ReadListFile(makefileIn);
+  makefile.ReadListFile(makefileIn); 
+  if(!cmCacheManager::GetInstance()->GetCacheValue("CMAKE_CXX"))
+    {
+    if(!makefile.GetDefinition("CMAKE_CXX"))
+      {
+      makefile.AddDefinition("CMAKE_CXX", "VC60");
+      }
+    cmCacheManager::GetInstance()->AddCacheEntry("CMAKE_CXX", "VC60",
+                                                 "Compiler used", cmCacheManager::STRING);
+    }
   // Generate the project files
   makefile.GenerateMakefile();
   // Save the cache

+ 8 - 8
Source/Makefile.in

@@ -1,15 +1,15 @@
-
 srcdir        = @srcdir@
 VPATH         = @srcdir@
 
-# DO NOT INCLUDE CMakeMaster.make here!
-# This will cause an infinite loop as it will add the
-# command for changing into this directory
+CMAKE_CONFIG_DIR = @CMAKE_CONFIG_DIR@
+CXX           = @CXX@
+CXXFLAGS      = @CXXFLAGS@ -DCMAKE_HAS_AUTOCONF -I${CMAKE_CONFIG_DIR}/CMake/Source
+
+.SUFFIXES: .cxx .java .class
+
+.cxx.o:
+	${CXX} ${CXXFLAGS} -c $< -o $@
 
-# let cmake know that this was done with autoconf
-KIT_FLAGS = -DCMAKE_HAS_AUTOCONF  -I${CMAKE_CONFIG_DIR}/CMake/Source 
-include @CMAKE_CONFIG_DIR@/CMake/CMakeVariables.make
-include @CMAKE_CONFIG_DIR@/CMake/CMakeSimpleRules.make
 
 OBJS = \
 CMakeBuildTargets.o  \

+ 2 - 3
Source/cmBuildNameCommand.cxx

@@ -55,7 +55,7 @@ bool cmBuildNameCommand::Invoke(std::vector<std::string>& args)
     m_Makefile->AddDefinition("BUILDNAME", cacheValue);
     return true;
     }
-  std::string buildname = "WinNT-VC60";
+  std::string buildname = "WinNT";
   if(m_Makefile->GetDefinition("UNIX"))
     {
     buildname = "";
@@ -70,10 +70,9 @@ bool cmBuildNameCommand::Invoke(std::vector<std::string>& args)
 	buildname = reg.match(1) + "-" + reg.match(2);
 	}
       }
-
     }
 
-  std::string compiler = "-${CXX}";
+  std::string compiler = "-${CMAKE_CXX}";
   m_Makefile->ExpandVariablesInString ( compiler );
   buildname += compiler;
   

+ 4 - 1
Source/cmBuildSharedLibrariesCommand.cxx

@@ -53,7 +53,10 @@ bool cmBuildSharedLibrariesCommand::Invoke(std::vector<std::string>& args)
       AddCacheEntry("BUILD_SHARED_LIBS",
                     false,
                     "If ON, the resulting project or makefiles will "
-                    "produce shared libraries.");
+                    "produce shared libraries.  WARNING! On some "
+                    "UNIX platforms, changing this setting will require"
+                    " removing all .o files, as they will have to be recompiled "
+                    " with -fpic or some other flag.");
     m_Makefile->AddDefinition("BUILD_SHARED_LIBS", false);
     }
   else

+ 1 - 0
Source/cmCacheManager.cxx

@@ -51,6 +51,7 @@ const char* cmCacheManagerTypes[] =
   "FILEPATH",
   "STRING",
   "INTERNAL",
+  "STATIC",
   0
 };
 

+ 1 - 1
Source/cmCacheManager.h

@@ -53,7 +53,7 @@ class cmMakefile;
 class cmCacheManager
 {
 public:
-  enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL  };
+  enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC };
   struct CacheEntry
   {
     std::string m_Value;

+ 0 - 2
Source/cmDSPMakefile.cxx

@@ -163,8 +163,6 @@ void cmDSPMakefile::WriteDSPFile(std::ostream& fout,
                                  const char *libName,
                                  cmTarget &target)
 {
-  target.GenerateSourceFilesFromSourceLists(*m_Makefile);
-
   // Write the DSP file's header.
   this->WriteDSPHeader(fout, libName, target);
   

+ 0 - 2
Source/cmDSPWriter.cxx

@@ -163,8 +163,6 @@ void cmDSPMakefile::WriteDSPFile(std::ostream& fout,
                                  const char *libName,
                                  cmTarget &target)
 {
-  target.GenerateSourceFilesFromSourceLists(*m_Makefile);
-
   // Write the DSP file's header.
   this->WriteDSPHeader(fout, libName, target);
   

+ 0 - 1
Source/cmMakeDepend.cxx

@@ -85,7 +85,6 @@ void cmMakeDepend::SetMakefile(cmMakefile* makefile)
   for(cmTargets::iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
-    l->second.GenerateSourceFilesFromSourceLists(*m_Makefile);
     std::vector<cmSourceFile> &classes = l->second.GetSourceFiles();
     for(std::vector<cmSourceFile>::iterator i = classes.begin(); 
         i != classes.end(); ++i)

+ 1 - 0
Source/cmMakefile.cxx

@@ -359,6 +359,7 @@ void cmMakefile::GenerateMakefile()
   for (cmTargets::iterator l = m_Targets.begin();
        l != m_Targets.end(); l++)
     {
+    l->second.GenerateSourceFilesFromSourceLists(*this);
     l->second.MergeLibraries(m_LinkLibraries);
     }
   // now do the generation

+ 2 - 2
Source/cmProjectCommand.cxx

@@ -60,13 +60,13 @@ bool cmProjectCommand::Invoke(std::vector<std::string>& args)
   cmCacheManager::GetInstance()->
     AddCacheEntry(bindir.c_str(),
 		  m_Makefile->GetCurrentOutputDirectory(),
-		  "Value Computed by CMake", cmCacheManager::PATH);
+		  "Value Computed by CMake", cmCacheManager::STATIC);
   m_Makefile->AddDefinition(srcdir.c_str(),
 	  m_Makefile->GetCurrentDirectory());
   cmCacheManager::GetInstance()->
     AddCacheEntry(srcdir.c_str(),
 		  m_Makefile->GetCurrentDirectory(),
-		  "Value Computed by CMake", cmCacheManager::PATH);
+		  "Value Computed by CMake", cmCacheManager::STATIC);
   
   return true;
 }

+ 20 - 1
Source/cmSetCommand.cxx

@@ -52,6 +52,20 @@ bool cmSetCommand::Invoke(std::vector<std::string>& args)
     {
       return true;
     }
+  if(args[1] == "CACHE")
+    { 
+    const char* type = "STRING"; // default type is string
+    if(args.size() > 2)
+      {
+      type = args[2].c_str();
+      }
+    m_Makefile->AddDefinition(args[0].c_str(), "");
+    cmCacheManager::GetInstance()->AddCacheEntry(args[0].c_str(),
+                                                 "",
+						 "Value Computed by CMake",
+                                                 cmCacheManager::StringToType(type));
+    return true;
+    }
   
   // expand value
   m_Makefile->ExpandVariablesInString(args[1]);
@@ -60,10 +74,15 @@ bool cmSetCommand::Invoke(std::vector<std::string>& args)
   // should we store the result in the cache ?
   if (args.size() > 2 && args[2] == "CACHE")
     {
+    const char* type = "STRING"; // default type is string
+    if(args.size() > 3)
+      {
+      type = args[3].c_str();
+      }
     cmCacheManager::GetInstance()->AddCacheEntry(args[0].c_str(),
                                                  args[1].c_str(),
 						 "Value Computed by CMake",
-                                                 cmCacheManager::STRING);
+                                                 cmCacheManager::StringToType(type));
     }
   return true;
 }

+ 315 - 101
Source/cmUnixMakefileGenerator.cxx

@@ -72,7 +72,7 @@ void cmUnixMakefileGenerator::GenerateMakefile()
     md.SetMakefile(m_Makefile);
     md.DoDepends();
     // output the makefile fragment
-    this->OutputMakefile("CMakeTargets.make"); 
+    this->OutputMakefile("Makefile"); 
     }
 }
 
@@ -99,16 +99,63 @@ void cmUnixMakefileGenerator::OutputMakefile(const char* file)
     cmSystemTools::Error("Error can not open for write: ", file);
     return;
     }
+  fout << "# CMAKE generated Makefile, DO NOT EDIT!\n"
+       << "# Generated from the following files:\n# "
+       << m_Makefile->GetHomeOutputDirectory() << "/CMakeCache.txt\n";
+  std::vector<std::string> lfiles = m_Makefile->GetListFiles();
+  // sort the array
+  std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
+  // remove duplicates
+  std::vector<std::string>::iterator new_end = 
+    std::unique(lfiles.begin(), lfiles.end());
+  lfiles.erase(new_end, lfiles.end());
+
+  for(std::vector<std::string>::const_iterator i = lfiles.begin();
+      i !=  lfiles.end(); ++i)
+    {
+    fout << "# " << i->c_str() << "\n";
+    }
+  fout << "\n\n";
+  // create a make variable with all of the sources for this Makefile
+  // for depend purposes.
+  fout << "CMAKE_MAKEFILE_SOURCES = ";
+  for(std::vector<std::string>::const_iterator i = lfiles.begin();
+      i !=  lfiles.end(); ++i)
+    {
+    fout << " " << i->c_str();
+    }
+  // Add the cache to the list
+  fout << " " << m_Makefile->GetHomeOutputDirectory() << "/CMakeCache.txt\n";
+  fout << "\n\n";
+  this->OutputMakeVariables(fout);
   this->OutputMakeFlags(fout);
-  this->OutputVerbatim(fout);
   this->OutputTargetRules(fout);
   this->OutputDependencies(fout);
   this->OutputTargets(fout);
   this->OutputSubDirectoryRules(fout);
-  this->OutputObjectDepends(fout);
+  std::string dependName;
+  if(!this->m_CacheOnly)
+    {
+    dependName = m_Makefile->GetStartOutputDirectory();
+    dependName += "/cmake.depends";
+    std::ofstream dependout(dependName.c_str());
+    if(!dependout)
+      {
+       cmSystemTools::Error("Error can not open for write: ", dependName.c_str());
+       return;
+      }
+    this->OutputObjectDepends(dependout);
+    }
   this->OutputCustomRules(fout);
+  this->OutputMakeRules(fout);
+  // only add the depend include if the depend file exists
+  if(cmSystemTools::FileExists(dependName.c_str()))
+    {
+    fout << "include cmake.depends\n";
+    }
 }
 
+
 // Output the rules for any targets
 void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
 {
@@ -116,13 +163,22 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
   fout << "TARGETS = ";
   const cmTargets &tgts = m_Makefile->GetTargets();
   // list libraries first
+  bool dll = cmCacheManager::GetInstance()->IsOn("BUILD_SHARED_LIBS");
   for(cmTargets::const_iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
     if (l->second.GetType() == cmTarget::LIBRARY &&
 	l->second.IsInAll())
       {
-      fout << " \\\nlib" << l->first.c_str() << "${CMAKE_LIB_EXT}";
+      fout << " \\\nlib" << l->first.c_str();
+      if(dll)
+        {
+        fout << m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
+        }
+      else
+        {
+        fout << ".a";
+        }
       }
     }
   // executables
@@ -147,7 +203,6 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
       }
     }
   fout << "\n\n";
-  
   // get the classes from the source lists then add them to the groups
   for(cmTargets::const_iterator l = tgts.begin(); 
       l != tgts.end(); l++)
@@ -164,6 +219,13 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
       }
     fout << "\n\n";
     }
+  fout << "CLEAN_OBJECT_FILES = ";
+  for(cmTargets::const_iterator l = tgts.begin(); 
+      l != tgts.end(); l++)
+    {
+    fout << "${" << l->first << "_SRC_OBJS} ";
+    }
+  fout << "\n";
 }
 
 
@@ -201,7 +263,10 @@ void cmUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
     if(targetLibrary && (lib->first == targetLibrary)) continue;
     // don't look at debug libraries
     if (lib->second == cmTarget::DEBUG) continue;
-    
+    // skip zero size library entries, this may happen
+    // if a variable expands to nothing.
+    if (lib->first.size() == 0) continue;
+    // if it is a full path break it into -L and -l
     if(lib->first.find('/') != std::string::npos)
       {
       std::string dir, file;
@@ -218,6 +283,7 @@ void cmUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
       librariesLinked += file;
       librariesLinked += " ";
       }
+    // not a full path, so add -l name
     else
       {
       std::string::size_type pos = lib->first.find("-l");
@@ -237,7 +303,6 @@ void cmUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
     // For executables, add these a second time so order does not matter
     linkLibs += librariesLinked;
     }
-  linkLibs += " ${LOCAL_LINK_FLAGS} ";
   fout << linkLibs;
 }
 
@@ -254,19 +319,19 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
       fout << "#---------------------------------------------------------\n";
       fout << "# rules for a library\n";
       fout << "#\n";
-      fout << "lib" << l->first << ".a: ${KIT_OBJ} ${" << 
+      fout << "lib" << l->first << ".a: ${" << 
         l->first << "_SRC_OBJS} \n";
-      fout << "\t${AR} cr lib" << l->first << ".a ${KIT_OBJ} ${" << 
+      fout << "\t${CMAKE_AR} cr lib" << l->first << ".a ${" << 
         l->first << "_SRC_OBJS} \n";
-      fout << "\t${RANLIB} lib" << l->first << ".a\n";
+      fout << "\t${CMAKE_RANLIB} lib" << l->first << ".a\n";
       fout << std::endl;
 
-      fout << "lib" << l->first << "$(SHLIB_SUFFIX): ${KIT_OBJ} ${" << 
+      fout << "lib" << l->first << "$(SHLIB_SUFFIX):  ${" << 
         l->first << "_SRC_OBJS} \n";
       fout << "\trm -f lib" << l->first << "$(SHLIB_SUFFIX)\n";
-      fout << "\t$(CXX) ${CXX_FLAGS} ${CMAKE_SHLIB_BUILD_FLAGS} -o \\\n";
+      fout << "\t$(CMAKE_CXX) ${CMAKE_SHLIB_LINK_FLAGS} ${CMAKE_CXX_FLAGS} ${CMAKE_SHLIB_BUILD_FLAGS} -o \\\n";
       fout << "\t  lib" << l->first << "$(SHLIB_SUFFIX) \\\n";
-      fout << "\t  ${KIT_OBJ} ${" << l->first << 
+      fout << "\t  ${" << l->first << 
         "_SRC_OBJS} ";
       this->OutputLinkLibraries(fout, l->first.c_str(), l->second);
       fout << "\n\n";
@@ -275,7 +340,7 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
       {
       fout << l->first << ": ${" << 
         l->first << "_SRC_OBJS} ${CMAKE_DEPEND_LIBS}\n";
-      fout << "\t${CXX}  ${CXX_FLAGS} ${" << 
+      fout << "\t${CMAKE_CXX}  ${CMAKE_CXXFLAGS} ${" << 
         l->first << "_SRC_OBJS} ";
       this->OutputLinkLibraries(fout, NULL,l->second);
       fout << " -o " << l->first << "\n\n";
@@ -304,11 +369,49 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
       {
       std::string libpath = cacheValue;
       libpath += "/lib";
-      libpath += lib2->first;
-      libpath += "${CMAKE_LIB_EXT}";
+      libpath += lib2->first; 
+      bool dll = cmCacheManager::GetInstance()->IsOn("BUILD_SHARED_LIBS");
+      if(dll)
+        {
+        libpath += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
+        }
+      else
+        {
+        libpath += ".a";
+        }
       fout << libpath << " ";
       }
     }
+  fout << "\n\n";
+  for(lib2 = libs.begin(); lib2 != libs.end(); ++lib2)
+    {
+    // loop over the list of directories that the libraries might
+    // be in, looking for an ADD_LIBRARY(lib...) line. This would
+    // be stored in the cache
+    const char* cacheValue
+      = cmCacheManager::GetInstance()->GetCacheValue(lib2->first.c_str());
+    if(cacheValue)
+      {
+      std::string library = "lib";
+      library += lib2->first; 
+      bool dll = cmCacheManager::GetInstance()->IsOn("BUILD_SHARED_LIBS");
+      if(dll)
+        {
+        library += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
+        }
+      else
+        {
+        library += ".a";
+        }
+      std::string libpath = cacheValue;
+      libpath += "/";
+      libpath += library;
+      // put out a rule to build the library if it does not exist
+      fout << libpath.c_str()
+           << ":\n\tcd " << cacheValue 
+           << "; make " << library.c_str() << "\n\n";
+      }
+    }
 
   std::vector<std::string>& utils = m_Makefile->GetUtilities();
   std::vector<std::string>& utildirs = m_Makefile->GetUtilityDirectories();
@@ -324,7 +427,7 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
       {
       std::string expression = "TARGETS =.*";
       expression += util->c_str();
-      if(cmSystemTools::Grep(dir->c_str(), "CMakeTargets.make",
+      if(cmSystemTools::Grep(dir->c_str(), "Makefile",
                              expression.c_str()))
         {
         fout << *util << " ";
@@ -350,25 +453,12 @@ void cmUnixMakefileGenerator::OutputMakeFlags(std::ostream& fout)
     fout << "-I" << cmSystemTools::EscapeSpaces(i->c_str()).c_str() << " ";
     }
   fout << m_Makefile->GetDefineFlags();
-  fout << " ${LOCAL_INCLUDE_FLAGS} ";
   fout << "\n\n";
   fout << "default_target: all\n\n";
   // see if there are files to compile in this makefile
   // These are used for both libraries and executables
 }
 
-// output verbatim section
-void cmUnixMakefileGenerator::OutputVerbatim(std::ostream& fout)
-{
-    std::vector<std::string>& MakeVerbatim = m_Makefile->GetMakeVerbatim();
-  // Ouput user make text embeded in the input file
-  for(unsigned int i =0; i < MakeVerbatim.size(); i++)
-    {
-    fout << MakeVerbatim[i] << "\n";
-    }
-  fout << "\n\n";
-  
-}
 
 // fix up names of directories so they can be used
 // as targets in makefiles.
@@ -391,24 +481,26 @@ inline std::string FixDirectoryName(const char* dir)
   return s;
 }
 
-
-// output rules for decending into sub directories
-void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
+void 
+cmUnixMakefileGenerator::
+OutputSubDirectoryVars(std::ostream& fout,
+                       const char* var,
+                       const char* target,
+                       const char* target1,
+                       const char* target2,
+                       const std::vector<std::string>& SubDirectories)
 {
-    // Output Sub directory build rules
-  const std::vector<std::string>& SubDirectories
-    = m_Makefile->GetSubDirectories();
-    
   if( SubDirectories.size() == 0)
     {
     return;
     }
-  fout << "SUBDIR_BUILD = \\\n";
+  fout << "# Variable for making " << target << " in subdirectories.\n";
+  fout << var << " = \\\n";
   unsigned int i;
   for(i =0; i < SubDirectories.size(); i++)
     { 
     std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
-    fout << "build_" << subdir.c_str();
+    fout << target << "_" << subdir.c_str();
     if(i == SubDirectories.size()-1)
       {
       fout << " \n\n";
@@ -418,37 +510,49 @@ void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
       fout << " \\\n";
       }
     }
-  fout << std::endl;
-  fout << "SUBDIR_CLEAN = \\\n";
-  for(i =0; i < SubDirectories.size(); i++)
-    { 
+  fout << "# Targets for making " << target << " in subdirectories.\n";
+  for(int i =0; i < SubDirectories.size(); i++)
+    {
     std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
-    fout << "clean_" << subdir.c_str();
-    if(i == SubDirectories.size()-1)
+    fout << target << "_" << subdir.c_str() << ":\n";
+    if(target1)
       {
-      fout << " \n\n";
+      fout << "\tcd " << SubDirectories[i].c_str()
+           << "; ${MAKE} -${MAKEFLAGS} " << target1 << "\n";
       }
-    else
+    if(target2)
       {
-      fout << " \\\n";
+      fout << "\tcd " << SubDirectories[i].c_str()
+           << "; ${MAKE} -${MAKEFLAGS} " << target2 << "\n";
       }
     }
-  fout << std::endl;
-  fout << "alldirs : ${SUBDIR_BUILD}\n\n";
+  fout << "\n\n";
+}
 
-  for(i =0; i < SubDirectories.size(); i++)
-    {
-    std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
-    fout << "build_" << subdir.c_str() << ":\n";
-    fout << "\tcd " << SubDirectories[i].c_str()
-         << "; ${MAKE} -${MAKEFLAGS} CMakeTargets.make\n";
-    fout << "\tcd " << SubDirectories[i].c_str()
-         << "; ${MAKE} -${MAKEFLAGS} all\n\n";
 
-    fout << "clean_" << subdir.c_str() << ": \n";
-    fout << "\tcd " << SubDirectories[i].c_str() 
-         << "; ${MAKE} -${MAKEFLAGS} clean\n\n";
+// output rules for decending into sub directories
+void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
+{
+    // Output Sub directory build rules
+  const std::vector<std::string>& SubDirectories
+    = m_Makefile->GetSubDirectories();
+    
+  if( SubDirectories.size() == 0)
+    {
+    return;
     }
+  this->OutputSubDirectoryVars(fout, "SUBDIR_BUILD", "build",
+                               "cmake.depends",
+                               "all",
+                               SubDirectories);
+  this->OutputSubDirectoryVars(fout, "SUBDIR_CLEAN", "clean",
+                               "clean",
+                               0,
+                               SubDirectories);
+  this->OutputSubDirectoryVars(fout, "SUBDIR_DEPEND", "depend",
+                               "depend",
+                               0,
+                               SubDirectories);
 }
 
 
@@ -585,49 +689,12 @@ void cmUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
 
 void cmUnixMakefileGenerator::GenerateCacheOnly()
 {
-  
-  std::string source = m_Makefile->GetHomeDirectory();
-  source += "/CMake/CMakeMakefileTemplate.in";
   cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory());
   std::string dest = m_Makefile->GetStartOutputDirectory();
   dest += "/Makefile";
-  std::ofstream fout(dest.c_str());
-  std::cout << "cmake: creating : " << dest.c_str() << "\n";
-  if(!fout)
-    {
-    cmSystemTools::Error("Failed to open file for write " , dest.c_str());
-    }
-  else
-    {
-    if(strcmp(m_Makefile->GetHomeDirectory(), 
-              m_Makefile->GetHomeOutputDirectory()) == 0)
-      {
-      fout << "srcdir        = .\n\n";
-      }
-    else
-      {
-      fout << "srcdir        = " <<  m_Makefile->GetStartDirectory() << "\n";
-      fout << "VPATH         = " <<  m_Makefile->GetStartDirectory() << "\n";
-      }
-    }
-  fout << "include "
-       << m_Makefile->GetHomeOutputDirectory() << "/CMake/CMakeMaster.make\n";
-  dest = m_Makefile->GetStartOutputDirectory();
-  dest += "/CMakeTargets.make";
-  // make sure there is a CMakeTargets.make file as some
-  // makes require it to exist
-  if(!cmSystemTools::FileExists(dest.c_str()))
-    {
-    std::cout << "cmake: creating : " << dest.c_str() << "\n";
-    std::ofstream fout(dest.c_str());
-    if(!fout)
-      { 
-      cmSystemTools::Error("Failed to open file for write " , dest.c_str());
-      }
-    fout << "#Initial CMakeTargets.make file created only to keep \n";
-    fout << "#certain makes happy that don't like to include makefiles\n";
-    fout << "#that do not exist\n";
-    }
+  std::cout << "cmake: creating : " << dest.c_str() << std::endl;
+  this->OutputMakefile(dest.c_str());
+  return;
 }
 
 void cmUnixMakefileGenerator::RecursiveGenerateCacheOnly()
@@ -654,3 +721,150 @@ void cmUnixMakefileGenerator::RecursiveGenerateCacheOnly()
       delete makefiles[i];
     }
 }
+
+void cmUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
+{
+  if(strcmp(m_Makefile->GetHomeDirectory(), 
+            m_Makefile->GetHomeOutputDirectory()) == 0)
+    {
+    fout << "srcdir        = .\n\n";
+    }
+  else
+    {
+    fout << "srcdir        = " <<  m_Makefile->GetStartDirectory() << "\n";
+    fout << "VPATH         = " <<  m_Makefile->GetStartDirectory() << "\n";
+    }
+  const char* variables = 
+    "# the standard shell for make\n"
+    "SHELL = /bin/sh\n"
+    "\n"
+    "CMAKE_LIB_EXT          = @CMAKE_LIB_EXT@\n"
+    "CMAKE_RANLIB        = @CMAKE_RANLIB@\n"
+    "CMAKE_AR        = @CMAKE_AR@\n"
+    "CMAKE_CC            = @CMAKE_CC@\n"
+    "CMAKE_CFLAGS        = @CMAKE_CC_FLAGS@ @CMAKE_SHLIB_CFLAGS@ \n"
+    "\n"
+    "CMAKE_CXX           = @CMAKE_CXX@\n"
+    "CMAKE_CXXFLAGS      = @CMAKE_CXX_FLAGS@ @CMAKE_SHLIB_CFLAGS@ @CMAKE_TEMPLATE_FLAGS@ \n"
+    "\n"
+    "CMAKE_SHLIB_BUILD_FLAGS = @CMAKE_SHLIB_BUILD_FLAGS@\n"
+    "CMAKE_SHLIB_LINK_FLAGS = @CMAKE_SHLIB_LINK_FLAGS@\n"
+    "DL_LIBS              = @CMAKE_DL_LIBS@\n"
+    "SHLIB_LD_LIBS        = @CMAKE_SHLIB_LD_LIBS@\n"
+    "SHLIB_SUFFIX         = @CMAKE_SHLIB_SUFFIX@\n"
+    "THREAD_LIBS          = @CMAKE_THREAD_LIBS@\n"
+    "\n"
+    "# set up the path to the rulesgen program\n"
+    "CMAKE = ${CMAKE_BINARY_DIR}/CMake/Source/CMakeBuildTargets\n"
+    "\n"
+    "\n"
+    "\n";
+  std::string replaceVars = variables;
+  m_Makefile->ExpandVariablesInString(replaceVars);
+  fout << replaceVars.c_str();
+  fout << "CMAKE_CURRENT_SOURCE = " << m_Makefile->GetStartDirectory() << "\n";
+  fout << "CMAKE_CURRENT_BINARY = " << m_Makefile->GetStartOutputDirectory() << "\n";
+}
+
+
+void cmUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
+{
+  this->OutputMakeRule(fout, 
+                       "# tell make about .cxx and .java",
+                       ".SUFFIXES", ".cxx .java .class", 0);
+  this->OutputMakeRule(fout, 
+                       "# build c file",
+                       ".c.o", 
+                       0,
+                       "${CMAKE_CC} ${CMAKE_CFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");
+  this->OutputMakeRule(fout, 
+                       "# build cplusplus file",
+                       ".cxx.o", 
+                       0,
+                       "${CMAKE_CXX} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");  this->OutputMakeRule(fout, 
+                       "Default build rule",
+                       "all",
+                       "Makefile cmake.depends ${TARGETS} ${SUBDIR_BUILD} ${CMAKE}",
+                       0);
+  this->OutputMakeRule(fout, 
+                       "rule to build cmake from source",
+                       "${CMAKE}", "${CMAKE_SOURCE_DIR}/CMake/Source/*.cxx "
+                       "${CMAKE_SOURCE_DIR}/CMake/Source/*.h",
+                       "cd ${CMAKE_BINARY_DIR}/CMake/Source; "
+                       "${MAKE} CMakeBuildTargets");
+  this->OutputMakeRule(fout, 
+                       "remove generated files",
+                       "clean",
+                       "${SUBDIR_CLEAN}",
+                       "rm -f ${CLEAN_OBJECT_FILES} ${EXECUTABLES} ${TARGETS}");
+  this->OutputMakeRule(fout, 
+                       "Rule to build the Makefile",
+                       "Makefile",
+                       "${CMAKE} ${CMAKE_MAKEFILE_SOURCES} ",
+                       "${CMAKE} ${CMAKE_CURRENT_SOURCE}/CMakeLists.txt "
+                       "-S${CMAKE_CURRENT_SOURCE} -O${CMAKE_CURRENT_BINARY} "
+                       "-H${CMAKE_SOURCE_DIR} -B${CMAKE_BINARY_DIR}");  
+  this->OutputMakeRule(fout, 
+                       "Rule to build the cmake.depends",
+                       "cmake.depends",
+                       "${CMAKE} ${CMAKE_MAKEFILE_SOURCES} ",
+                       "${CMAKE} ${CMAKE_CURRENT_SOURCE}/CMakeLists.txt "
+                       "-S${CMAKE_CURRENT_SOURCE} -O${CMAKE_CURRENT_BINARY} "
+                       "-H${CMAKE_SOURCE_DIR} -B${CMAKE_BINARY_DIR}");
+  this->OutputMakeRule(fout, 
+                       "Rule to force the build of cmake.depends",
+                       "depend",
+                       "${SUBDIR_DEPEND}",
+                       "${CMAKE} ${CMAKE_CURRENT_SOURCE}/CMakeLists.txt "
+                       "-S${CMAKE_CURRENT_SOURCE} -O${CMAKE_CURRENT_BINARY} "
+                       "-H${CMAKE_SOURCE_DIR} -B${CMAKE_BINARY_DIR}");  
+  this->OutputMakeRule(fout, 
+                       "Rebuild the cache",
+                       "rebuild_cache",
+                       "${CMAKE_BINARY_DIR}/CMakeCache.txt",
+                       "${CMAKE} ${CMAKE_SOURCE_DIR}/CMakeLists.txt "
+                       "-MakeCache -S${CMAKE_SOURCE_DIR} -O${CMAKE_BINARY_DIR} "
+                       "-H${CMAKE_SOURCE_DIR} -B${CMAKE_BINARY_DIR}");
+  
+}
+
+void cmUnixMakefileGenerator::OutputMakeRule(std::ostream& fout, 
+                                             const char* comment,
+                                             const char* target,
+                                             const char* depends, 
+                                             const char* command)
+{
+  if(!target)
+    {
+    cmSystemTools::Error("no target for OutputMakeRule");
+    return;
+    }
+  
+  std::string replace;
+  if(comment)
+    {
+    replace = comment;
+    m_Makefile->ExpandVariablesInString(replace);
+    fout << "# " << comment;
+    }
+  fout << "\n";
+  replace = target;
+  m_Makefile->ExpandVariablesInString(replace);
+  fout << replace.c_str() << ": ";
+  if(depends)
+    {
+    replace = depends;
+    m_Makefile->ExpandVariablesInString(replace);
+    fout << replace.c_str();
+    }
+  fout << "\n";
+  if(command)
+    {
+    replace = command;
+    m_Makefile->ExpandVariablesInString(replace);
+    fout << "\t" << replace.c_str() << "\n\n";
+    }
+  fout << "\n\n\n";
+
+}
+

+ 13 - 1
Source/cmUnixMakefileGenerator.h

@@ -86,7 +86,6 @@ private:
   void GenerateCacheOnly();
   void OutputMakefile(const char* file);
   void OutputMakeFlags(std::ostream&);
-  void OutputVerbatim(std::ostream&);
   void OutputTargetRules(std::ostream& fout);
   void OutputLinkLibraries(std::ostream&, const char*, const cmTarget &);
   void OutputTargets(std::ostream&);
@@ -94,6 +93,19 @@ private:
   void OutputDependInformation(std::ostream&);
   void OutputDependencies(std::ostream&);
   void OutputCustomRules(std::ostream&);
+  void OutputMakeVariables(std::ostream&);
+  void OutputMakeRules(std::ostream&);
+  void OutputSubDirectoryVars(std::ostream& fout,
+                              const char* var,
+                              const char* target,
+                              const char* target1,
+                              const char* target2,
+                              const std::vector<std::string>& SubDirectories);
+  void OutputMakeRule(std::ostream&, 
+                      const char* comment,
+                      const char* target,
+                      const char* depends, 
+                      const char* command);
 private:
   bool m_CacheOnly;
   bool m_Recurse;