From e693d47253157c9372aeb7c2edbecef8d1fb6225 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 2 Jul 2001 15:38:02 -0400 Subject: [PATCH] ENH: Added support for selection of static/shared build on a per-library basis. --- Source/cmAddLibraryCommand.cxx | 31 ++++- Source/cmAddLibraryCommand.h | 6 +- Source/cmDSPWriter.cxx | 17 ++- Source/cmDSPWriter.h | 7 -- Source/cmDSWWriter.cxx | 3 +- Source/cmMakefile.cxx | 14 ++- Source/cmMakefile.h | 3 +- Source/cmTarget.h | 3 +- Source/cmUnixMakefileGenerator.cxx | 190 ++++++++++++++--------------- Source/cmUnixMakefileGenerator.h | 1 - 10 files changed, 148 insertions(+), 127 deletions(-) diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index c49a4f6078..f607df396b 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -50,10 +50,35 @@ bool cmAddLibraryCommand::InitialPass(std::vector& args) return false; } - std::vector::iterator s = args.begin(); - std::vector srclists(++s, args.end()); + // 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::iterator s = args.begin(); + ++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 srclists(s, args.end()); + + m_Makefile->AddLibrary(args[0].c_str(), shared, srclists); - m_Makefile->AddLibrary(args[0].c_str(),srclists); return true; } diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index 650ef198c2..44954b13e9 100644 --- a/Source/cmAddLibraryCommand.h +++ b/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); diff --git a/Source/cmDSPWriter.cxx b/Source/cmDSPWriter.cxx index 76dc2077ac..71973df49a 100644 --- a/Source/cmDSPWriter.cxx +++ b/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) diff --git a/Source/cmDSPWriter.h b/Source/cmDSPWriter.h index 7190785cb9..0182e1a53a 100644 --- a/Source/cmDSPWriter.h +++ b/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 m_Configurations; }; diff --git a/Source/cmDSWWriter.cxx b/Source/cmDSWWriter.cxx index a44dfda186..3662f28d9c 100644 --- a/Source/cmDSWWriter.cxx +++ b/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 diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ccc477eab5..773000cef8 100644 --- a/Source/cmMakefile.cxx +++ b/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 &srcs) +void cmMakefile::AddLibrary(const char* lname, bool shared, + const std::vector &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 &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, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 3e780ac63b..0b89422949 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -225,7 +225,8 @@ public: /** * Set the name of the library. */ - void AddLibrary(const char *libname, const std::vector &srcs); + void AddLibrary(const char *libname, bool shared, + const std::vector &srcs); /** * Add a class/source file to the build. diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 031a4144b9..4b8e612f17 100644 --- a/Source/cmTarget.h +++ b/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. diff --git a/Source/cmUnixMakefileGenerator.cxx b/Source/cmUnixMakefileGenerator.cxx index 3b39690730..d21acc181d 100644 --- a/Source/cmUnixMakefileGenerator.cxx +++ b/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 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 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 rules; + // Iterate over every target. std::map& targets = m_Makefile->GetTargets(); for(std::map::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& sources = target->second.GetSourceFiles(); for(std::vector::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"; + } + } } } } diff --git a/Source/cmUnixMakefileGenerator.h b/Source/cmUnixMakefileGenerator.h index ed0fd07c78..82230bc096 100644 --- a/Source/cmUnixMakefileGenerator.h +++ b/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);