Browse Source

ENH: Added support for selection of static/shared build on a per-library basis.

Brad King 24 years ago
parent
commit
e693d47253

+ 27 - 2
Source/cmAddLibraryCommand.cxx

@@ -50,10 +50,35 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string>& args)
     return false;
     }
   
+  // Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
+  // otherwise it defaults to static library.
+  bool shared = !cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS"));
+  
   std::vector<std::string>::iterator s = args.begin();
-  std::vector<std::string> srclists(++s, args.end());
+  ++s;
+  
+  // If the second argument is "SHARED" or "STATIC", then it controls
+  // the type of library.  Otherwise, it is treated as a source or
+  // source list name.
+  if(s != args.end())
+    {
+    std::string libType = *s;
+    m_Makefile->ExpandVariablesInString(libType);
+    if(libType == "STATIC")
+      {
+      ++s;
+      shared = false;
+      }
+    else if(libType == "SHARED")
+      {
+      ++s;
+      shared = true;
+      }
+    }
+  std::vector<std::string> srclists(s, args.end());  
+  
+  m_Makefile->AddLibrary(args[0].c_str(), shared, srclists);
   
-  m_Makefile->AddLibrary(args[0].c_str(),srclists);
   return true;
 }
 

+ 5 - 1
Source/cmAddLibraryCommand.h

@@ -86,7 +86,11 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "ADD_LIBRARY(libname srclist srclist srclist ...)";
+      "ADD_LIBRARY(libname [SHARED | STATIC] srclist srclist srclist ...)\n"
+      "Adds a library target.  If the keyword SHARED or STATIC appears, it\n"
+      "sets the library type.  If neither keyword appears as the second\n"
+      "argument, the type defaults to the current value of BUILD_SHARED_LIBS.\n"
+      "If this variable is not set, the type defaults to STATIC.";
     }
   
   cmTypeMacro(cmAddLibraryCommand, cmCommand);

+ 8 - 9
Source/cmDSPWriter.cxx

@@ -88,11 +88,6 @@ void cmDSPWriter::OutputDSPFile()
     }
   
   // Create the DSP or set of DSP's for libraries and executables
-  m_LibraryBuildType = STATIC_LIBRARY;
-  if(!cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
-    {
-    m_LibraryBuildType = DLL;
-    }
 
   // clear project names
   m_CreatedProjectNames.clear();
@@ -104,8 +99,11 @@ void cmDSPWriter::OutputDSPFile()
     {
     switch(l->second.GetType())
       {
-      case cmTarget::LIBRARY:
-        this->SetBuildType(m_LibraryBuildType, l->first.c_str());
+      case cmTarget::STATIC_LIBRARY:
+        this->SetBuildType(STATIC_LIBRARY, l->first.c_str());
+        break;
+      case cmTarget::SHARED_LIBRARY:
+        this->SetBuildType(DLL, l->first.c_str());
         break;
       case cmTarget::EXECUTABLE:
         this->SetBuildType(EXECUTABLE,l->first.c_str());
@@ -538,8 +536,9 @@ void cmDSPWriter::WriteDSPHeader(std::ostream& fout, const char *libName,
     {
     // add libraries to executables and dlls (but never include
     // a library in a library, bad recursion)
-    if (target.GetType() != cmTarget::LIBRARY || 
-        (m_LibraryBuildType == DLL && libName != j->first))
+    if ((target.GetType() != cmTarget::SHARED_LIBRARY
+         && target.GetType() != cmTarget::STATIC_LIBRARY) || 
+        (target.GetType() == cmTarget::SHARED_LIBRARY && libName != j->first))
       {
       std::string lib = j->first;
       if(j->first.find(".lib") == std::string::npos)

+ 0 - 7
Source/cmDSPWriter.h

@@ -64,12 +64,6 @@ public:
    */
   void SetBuildType(BuildType,const char *name);
 
-  BuildType GetLibraryBuildType()
-    {
-      return m_LibraryBuildType;
-    }
-  
-
   /**
    * Return array of created DSP names in a STL vector.
    * Each executable must have its own dsp.
@@ -113,7 +107,6 @@ private:
 
   std::string m_IncludeOptions;
   cmMakefile* m_Makefile;
-  BuildType m_LibraryBuildType;
   std::vector<std::string> m_Configurations;
 };
 

+ 1 - 2
Source/cmDSWWriter.cxx

@@ -215,8 +215,7 @@ void cmDSWWriter::WriteProject(std::ostream& fout,
     {
     if(j->first != dspname)
       {
-      if (!(target.GetType() == cmTarget::LIBRARY) || 
-          project->GetLibraryBuildType() == cmDSPWriter::DLL)
+      if (target.GetType() != cmTarget::STATIC_LIBRARY)
         {
         // is the library part of this DSW ? If so add dependency
         const char* cacheValue

+ 12 - 2
Source/cmMakefile.cxx

@@ -541,10 +541,11 @@ void cmMakefile::SetProjectName(const char* p)
   m_ProjectName = p;
 }
 
-void cmMakefile::AddLibrary(const char* lname, const std::vector<std::string> &srcs)
+void cmMakefile::AddLibrary(const char* lname, bool shared,
+                            const std::vector<std::string> &srcs)
 {
   cmTarget target;
-  target.SetType(cmTarget::LIBRARY);
+  target.SetType(shared? cmTarget::SHARED_LIBRARY : cmTarget::STATIC_LIBRARY);
   target.SetInAll(true);
   target.GetSourceLists() = srcs;
   m_Targets.insert(cmTargets::value_type(lname,target));
@@ -554,6 +555,15 @@ void cmMakefile::AddLibrary(const char* lname, const std::vector<std::string> &s
     AddCacheEntry(lname,
                   this->GetCurrentOutputDirectory(),
                   "Path to a library", cmCacheManager::INTERNAL);
+
+  // Add an entry into the cache
+  std::string ltname = lname;
+  ltname += "_LIBRARY_TYPE";
+  cmCacheManager::GetInstance()->
+    AddCacheEntry(ltname.c_str(),
+                  shared? "SHARED":"STATIC",
+                  "Whether a library is static or shared.",
+                  cmCacheManager::INTERNAL);
 }
 
 void cmMakefile::AddExecutable(const char *exeName, 

+ 2 - 1
Source/cmMakefile.h

@@ -225,7 +225,8 @@ public:
   /**
    * Set the name of the library.
    */
-  void AddLibrary(const char *libname, const std::vector<std::string> &srcs);
+  void AddLibrary(const char *libname, bool shared,
+                  const std::vector<std::string> &srcs);
 
   /**
    * Add a class/source file to the build.

+ 2 - 1
Source/cmTarget.h

@@ -54,7 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 class cmTarget
 {
 public:
-  enum TargetType { EXECUTABLE, WIN32_EXECUTABLE, LIBRARY, UTILITY, INSTALL };
+  enum TargetType { EXECUTABLE, WIN32_EXECUTABLE, STATIC_LIBRARY,
+                    SHARED_LIBRARY, UTILITY, INSTALL };
 
   /**
    * Return the type of target.

+ 90 - 100
Source/cmUnixMakefileGenerator.cxx

@@ -242,11 +242,6 @@ void cmUnixMakefileGenerator::OutputMakefile(const char* file)
 }
 
 
-bool cmUnixMakefileGenerator::BuildingSharedLibs() const
-{
-  return !cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS"));
-}
-
 
 // Output the rules for any targets
 void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
@@ -255,21 +250,20 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
   fout << "TARGETS = ";
   const cmTargets &tgts = m_Makefile->GetTargets();
   // list libraries first
-  bool dll = this->BuildingSharedLibs();
   for(cmTargets::const_iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
-    if (l->second.GetType() == cmTarget::LIBRARY &&
-	l->second.IsInAll())
+    if (l->second.IsInAll())
       {
-      fout << " \\\n" << m_LibraryOutputPath << "lib" << l->first.c_str();
-      if(dll)
+      if(l->second.GetType() == cmTarget::STATIC_LIBRARY)
         {
-        fout << m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
+        fout << " \\\n" << m_LibraryOutputPath << "lib" << l->first.c_str()
+             << ".a";
         }
-      else
+      else if(l->second.GetType() == cmTarget::SHARED_LIBRARY)
         {
-        fout << ".a";
+        fout << " \\\n" << m_LibraryOutputPath << "lib" << l->first.c_str()
+             << m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
         }
       }
     }
@@ -341,7 +335,7 @@ void cmUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
   std::set<std::string> emitted;
 
   // Embed runtime search paths if possible and if required.
-  bool outputRuntime = this->BuildingSharedLibs();
+  bool outputRuntime = true;
   std::string runtimeFlag;
   std::string runtimeSep;
   std::vector<std::string> runtimeDirs;
@@ -487,17 +481,15 @@ void cmUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
 
 void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
 {
-  bool dll = this->BuildingSharedLibs();
-  
   // for each target
   const cmTargets &tgts = m_Makefile->GetTargets();
   for(cmTargets::const_iterator l = tgts.begin(); 
       l != tgts.end(); l++)
     {
-    if (l->second.GetType() == cmTarget::LIBRARY)
+    if (l->second.GetType() == cmTarget::STATIC_LIBRARY)
       {
       fout << "#---------------------------------------------------------\n";
-      fout << "# rules for a library\n";
+      fout << "# rules for a static library\n";
       fout << "#\n";
       fout << m_LibraryOutputPath << "lib" << l->first << ".a: ${" << 
         l->first << "_SRC_OBJS} \n";
@@ -506,8 +498,13 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
         l->first << "_SRC_OBJS} \n";
       fout << "\t${CMAKE_RANLIB} "
            << m_LibraryOutputPath << "lib" << l->first << ".a\n";
-      fout << std::endl;
-
+      fout << "\n\n";
+      }
+    else if (l->second.GetType() == cmTarget::SHARED_LIBRARY)
+      {
+      fout << "#---------------------------------------------------------\n";
+      fout << "# rules for a shared library\n";
+      fout << "#\n";
       fout << m_LibraryOutputPath << "lib" << l->first << "$(SHLIB_SUFFIX):  ${" << 
         l->first << "_SRC_OBJS} \n";
       fout << "\trm -f lib" << l->first << "$(SHLIB_SUFFIX)\n";
@@ -524,12 +521,8 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
       {
       fout << m_ExecutableOutputPath << l->first << ": ${" << 
         l->first << "_SRC_OBJS} ${CMAKE_DEPEND_LIBS}\n";
-      fout << "\t${CMAKE_CXX_COMPILER} ";
-      if (dll)
-        {
-        fout << "${CMAKE_SHLIB_LINK_FLAGS} ";
-        }
-      fout << "${CMAKE_CXXFLAGS} ${" << l->first << "_SRC_OBJS} ";
+      fout << "\t${CMAKE_CXX_COMPILER} ${CMAKE_SHLIB_LINK_FLAGS} ${CMAKE_CXXFLAGS} "
+           << "${" << l->first << "_SRC_OBJS} ";
       this->OutputLinkLibraries(fout, NULL,l->second);
       fout << " -o " << m_ExecutableOutputPath << l->first << "\n\n";
       }
@@ -550,7 +543,6 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
   // Search the list of libraries that will be linked into
   // the executable
   emitted.clear();
-  bool dll = this->BuildingSharedLibs();
   for(lib2 = libs.begin(); lib2 != libs.end(); ++lib2)
     {
     if( ! emitted.insert(lib2->first).second ) continue;
@@ -586,7 +578,10 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
       // add the library name
       libpath += lib2->first;
       // add the correct extension
-      if(dll)
+      std::string ltname = lib2->first+"_LIBRARY_TYPE";
+      const char* libType
+        = cmCacheManager::GetInstance()->GetCacheValue(ltname.c_str());
+      if(libType && std::string(libType) == "SHARED")
         {
         libpath += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
         }
@@ -615,16 +610,19 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
       {
       std::string library = "lib";
       library += lib2->first; 
-      bool dll = this->BuildingSharedLibs();
-      if(dll)
+      std::string libpath = cacheValue;
+      // add the correct extension
+      std::string ltname = lib2->first+"_LIBRARY_TYPE";
+      const char* libType
+        = cmCacheManager::GetInstance()->GetCacheValue(ltname.c_str());
+      if(libType && std::string(libType) == "SHARED")
         {
-        library += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
+        libpath += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
         }
       else
         {
-        library += ".a";
+        libpath += ".a";
         }
-      std::string libpath = cacheValue;
       if(m_LibraryOutputPath.size())
         {
         libpath = m_LibraryOutputPath;
@@ -953,10 +951,11 @@ void cmUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
     "CMAKE_AR            = @CMAKE_AR@\n"
     "CMAKE_AR_ARGS       = @CMAKE_AR_ARGS@\n"
     "CMAKE_C_COMPILER    = @CMAKE_C_COMPILER@\n"
-    "CMAKE_CFLAGS        = @CMAKE_C_FLAGS@ @CMAKE_SHLIB_CFLAGS@ \n"
+    "CMAKE_CFLAGS        = @CMAKE_C_FLAGS@\n"
+    "CMAKE_SHLIB_CFLAGS  = @CMAKE_SHLIB_CFLAGS@\n"
     "\n"
     "CMAKE_CXX_COMPILER  = @CMAKE_CXX_COMPILER@\n"
-    "CMAKE_CXXFLAGS      = @CMAKE_CXX_FLAGS@ @CMAKE_SHLIB_CFLAGS@ @CMAKE_TEMPLATE_FLAGS@ \n"
+    "CMAKE_CXXFLAGS      = @CMAKE_CXX_FLAGS@ @CMAKE_TEMPLATE_FLAGS@\n"
     "\n"
     "CMAKE_SHLIB_BUILD_FLAGS = @CMAKE_SHLIB_BUILD_FLAGS@\n"
     "CMAKE_SHLIB_LINK_FLAGS = @CMAKE_SHLIB_LINK_FLAGS@\n"
@@ -971,12 +970,6 @@ void cmUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
     "\n"
     "\n";
   std::string replaceVars = variables;
-  bool dll = this->BuildingSharedLibs();
-  if(!dll)
-    {
-    // if not a dll then remove the shlib -fpic flag
-    m_Makefile->AddDefinition("CMAKE_SHLIB_CFLAGS", "");
-    }
   
   m_Makefile->ExpandVariablesInString(replaceVars);
   fout << replaceVars.c_str();
@@ -987,7 +980,6 @@ void cmUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
 
 void cmUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
 {
-  bool dll = this->BuildingSharedLibs();
   const char* root
     = cmCacheManager::GetInstance()->GetCacheValue("CMAKE_ROOT");
   fout << "INSTALL = " << root << "/Templates/install-sh -c\n";
@@ -1024,17 +1016,16 @@ void cmUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
       // now install the target
       switch (l->second.GetType())
 	{
-	case cmTarget::LIBRARY:
+	case cmTarget::STATIC_LIBRARY:
 	  fout << "\t$(INSTALL_DATA) " << m_LibraryOutputPath << "lib" 
                << l->first;
-	  if(dll)
-	    {
-	      fout << m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
-	    }
-	  else
-	    {
-	      fout << ".a";
-	    }
+          fout << ".a";
+	  fout << " " << prefix << l->second.GetInstallPath() << "\n";
+	  break;
+	case cmTarget::SHARED_LIBRARY:
+	  fout << "\t$(INSTALL_DATA) " << m_LibraryOutputPath << "lib" 
+               << l->first;
+          fout << m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
 	  fout << " " << prefix << l->second.GetInstallPath() << "\n";
 	  break;
 	case cmTarget::WIN32_EXECUTABLE:
@@ -1094,35 +1085,6 @@ void cmUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
 
 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_C_COMPILER} ${CMAKE_CFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");
-  this->OutputMakeRule(fout, 
-                       "# build cplusplus file",
-                       ".cxx.o", 
-                       0,
-                       "${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");  
-  this->OutputMakeRule(fout, 
-                       "# build cplusplus file",
-                       ".cpp.o", 
-                       0,
-                       "${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");  
-  this->OutputMakeRule(fout, 
-                       "# build cplusplus file",
-                       ".cc.o", 
-                       0,
-                       "${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");  
-  this->OutputMakeRule(fout, 
-                       "# build cplusplus file",
-                       ".C.o", 
-                       0,
-                       "${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@");  
-
   // only include the cmake.depends and not the Makefile, as
   // building one will cause the other to be built
   this->OutputMakeRule(fout, 
@@ -1178,38 +1140,66 @@ void cmUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
                        0);
   
 
-  // Write special rules for source files coming from other packages
-  // (not in the current build or source directories)
-
-  fout << "# Write special rules for source files coming from other packages\n";
-  fout << "# (not in the current build or source directories)\n";
+  fout << "# Rules to build .o files from their sources:\n";
 
+  std::set<std::string> rules;
+  
   // Iterate over every target.
   std::map<std::string, cmTarget>& targets = m_Makefile->GetTargets();
   for(std::map<std::string, cmTarget>::const_iterator target = targets.begin(); 
       target != targets.end(); ++target)
     {
+    bool shared = (target->second.GetType() == cmTarget::SHARED_LIBRARY);
     // Iterate over every source for this target.
     const std::vector<cmSourceFile>& sources = target->second.GetSourceFiles();
     for(std::vector<cmSourceFile>::const_iterator source = sources.begin(); 
         source != sources.end(); ++source)
       {
-      if(!source->IsAHeaderFileOnly() && 
-	 (cmSystemTools::GetFilenamePath(source->GetFullPath()) 
-	  != m_Makefile->GetCurrentOutputDirectory()) &&
-	 (cmSystemTools::GetFilenamePath(source->GetFullPath()) 
-	    != m_Makefile->GetCurrentDirectory()))
+     if(!source->IsAHeaderFileOnly())
         {
-	fout << cmSystemTools::GetFilenameName(source->GetSourceName()) << ".o : " << source->GetFullPath() << "\n";
-	std::string ext = source->GetSourceExtension();
-	if ( ext == "cxx" || ext == "cc" || ext == "cpp" || ext == "C" )
-	  {
-	  fout << "\t${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -c $< -o $@\n\n";
-	  }
-	else if ( ext == "c" )
- 	  {
-	  fout << "\t${CMAKE_C_COMPILER} ${CMAKE_CFLAGS} ${INCLUDE_FLAGS} -c $< -o $@\n\n";
-	  }
+        std::string shortName;
+        // If the full path to the source file includes this
+        // directory, we want to use the relative path for the
+        // filename of the object file.  Otherwise, we will use just
+        // the filename portion.
+        if((cmSystemTools::GetFilenamePath(source->GetFullPath()).find(m_Makefile->GetCurrentDirectory()) == 0)
+           || (cmSystemTools::GetFilenamePath(source->GetFullPath()).find(m_Makefile->GetCurrentOutputDirectory()) == 0))
+          {
+          shortName = source->GetSourceName();
+          
+          // The path may be relative.  See if a directory needs to be
+          // created for the output file.  This is a ugly, and perhaps
+          // should be moved elsewhere.
+          std::string relPath =
+            cmSystemTools::GetFilenamePath(source->GetSourceName());
+          if(relPath != "")
+            {
+            std::string outPath = m_Makefile->GetCurrentOutputDirectory();
+            outPath += "/"+relPath;
+            cmSystemTools::MakeDirectory(outPath.c_str());
+            }
+          }
+        else
+          {
+          shortName = cmSystemTools::GetFilenameName(source->GetSourceName());
+          }
+        // Only output a rule for each .o once.
+        if(rules.find(shortName) == rules.end())
+          {
+          rules.insert(shortName);
+          fout << shortName.c_str() << ".o : " << source->GetFullPath() << "\n";
+          std::string ext = source->GetSourceExtension();
+          if ( ext == "cxx" || ext == "cc" || ext == "cpp" || ext == "C" )
+            {
+            fout << "\t${CMAKE_CXX_COMPILER} ${CMAKE_CXXFLAGS} "
+                 << (shared? "${CMAKE_SHLIB_CFLAGS} ":"") << "${INCLUDE_FLAGS} -c $< -o $@\n\n";
+            }
+          else if ( ext == "c" )
+            {
+            fout << "\t${CMAKE_C_COMPILER} ${CMAKE_CFLAGS} "
+                 << (shared? "${CMAKE_SHLIB_CFLAGS} ":"") << "${INCLUDE_FLAGS} -c $< -o $@\n\n";
+            }
+          }
         }
       }
     }

+ 0 - 1
Source/cmUnixMakefileGenerator.h

@@ -94,7 +94,6 @@ private:
   void RecursiveGenerateCacheOnly();
   void ProcessDepends(const cmMakeDepend &md);
   void GenerateCacheOnly();
-  bool BuildingSharedLibs() const;
   void OutputMakefile(const char* file);
   void OutputMakeFlags(std::ostream&);
   void OutputTargetRules(std::ostream& fout);