summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Martin <ken.martin@kitware.com>2006-02-14 15:36:04 (GMT)
committerKen Martin <ken.martin@kitware.com>2006-02-14 15:36:04 (GMT)
commit7740ccd1a41e837b89cd5bb7b87d9654b7b745a2 (patch)
tree126259e7c3b07471a47f0e596f1d6f63bf001a51
parent3bce601c41b8487a18417e32b75c0e22f0750bbc (diff)
downloadCMake-7740ccd1a41e837b89cd5bb7b87d9654b7b745a2.zip
CMake-7740ccd1a41e837b89cd5bb7b87d9654b7b745a2.tar.gz
CMake-7740ccd1a41e837b89cd5bb7b87d9654b7b745a2.tar.bz2
ENH: some cleanup of the makefile generator
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx334
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.h34
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx394
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h37
-rw-r--r--Source/cmMakefileTargetGenerator.cxx794
-rw-r--r--Source/cmMakefileTargetGenerator.h152
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx90
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.h34
8 files changed, 1869 insertions, 0 deletions
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
new file mode 100644
index 0000000..03acb8c
--- /dev/null
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -0,0 +1,334 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmMakefileExecutableTargetGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+//----------------------------------------------------------------------------
+void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
+{
+ // create the build.make file and directory, put in the common blocks
+ this->CreateRuleFile();
+
+ // Add in any rules for custom commands
+ this->WriteCustomCommandsForTarget();
+
+ // write in rules for object files
+ this->WriteCommonCodeRules();
+
+ // write the link rules
+ this->WriteExecutableRule();
+
+ // Write the requires target.
+ this->WriteTargetRequiresRules();
+
+ // Write clean target
+ this->WriteTargetCleanRules();
+
+ // close the streams
+ this->CloseFileStreams();
+}
+
+
+
+//----------------------------------------------------------------------------
+void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
+{
+ // Write the dependency generation rule.
+ this->WriteTargetDependRules();
+
+ std::vector<std::string> commands;
+
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string objTarget;
+
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
+ obj != this->Objects.end(); ++obj)
+ {
+ objTarget = relPath;
+ objTarget += *obj;
+ depends.push_back(objTarget);
+ }
+
+ // Add dependencies on targets that must be built first.
+ this->AppendTargetDepends(depends);
+
+ // Add a dependency on the rule file itself.
+ this->LocalGenerator->AppendRuleDepend(depends,
+ this->BuildFileNameFull.c_str());
+
+ for(std::vector<std::string>::const_iterator obj =
+ this->ExternalObjects.begin();
+ obj != this->ExternalObjects.end(); ++obj)
+ {
+ depends.push_back(*obj);
+ }
+
+ // from here up is the same for exe or lib
+
+ // Get the name of the executable to generate.
+ std::string targetName;
+ std::string targetNameReal;
+ this->Target->GetExecutableNames(targetName, targetNameReal,
+ this->LocalGenerator->m_ConfigurationName.c_str());
+
+ // Construct the full path version of the names.
+ std::string outpath = this->LocalGenerator->m_ExecutableOutputPath;
+ if(outpath.length() == 0)
+ {
+ outpath = this->Makefile->GetStartOutputDirectory();
+ outpath += "/";
+ }
+#ifdef __APPLE__
+ if(this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
+ {
+ // Make bundle directories
+ outpath += this->Target->GetName();
+ outpath += ".app/Contents/MacOS/";
+ std::string f1 =
+ this->Makefile->GetModulesFile("MacOSXBundleInfo.plist.in");
+ if ( f1.size() == 0 )
+ {
+ cmSystemTools::Error("could not find Mac OSX bundle template file.");
+ }
+ std::string macdir =
+ this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ if ( macdir.size() == 0 )
+ {
+ macdir = this->Makefile->GetCurrentOutputDirectory();
+ }
+ if(macdir.size() && macdir[macdir.size()-1] != '/')
+ {
+ macdir += "/";
+ }
+ macdir += this->Target->GetName();
+ macdir += ".app/Contents/";
+ std::string f2 = macdir + "Info.plist";
+ macdir += "MacOS";
+ cmSystemTools::MakeDirectory(macdir.c_str());
+ this->Makefile->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", this->Target->GetName());
+ this->Makefile->ConfigureFile(f1.c_str(), f2.c_str(),
+ false, false, false);
+ }
+#endif
+ std::string targetFullPath = outpath + targetName;
+ std::string targetFullPathReal = outpath + targetNameReal;
+
+ // Convert to the output path to use in constructing commands.
+ std::string targetOutPath =
+ this->Convert(targetFullPath.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ std::string targetOutPathReal =
+ this->Convert(targetFullPathReal.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+
+ // Get the language to use for linking this executable.
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+
+ // Make sure we have a link language.
+ if(!linkLanguage)
+ {
+ cmSystemTools::Error("Cannot determine link language for target \"",
+ this->Target->GetName(), "\".");
+ return;
+ }
+
+ // Add the link message.
+ std::string buildEcho = "Linking ";
+ buildEcho += linkLanguage;
+ buildEcho += " executable ";
+ buildEcho += targetOutPath;
+ this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
+
+ // Build a list of compiler flags and linker flags.
+ std::string flags;
+ std::string linkFlags;
+
+ // Add flags to deal with shared libraries. Any library being
+ // linked in might be shared, so always use shared flags for an
+ // executable.
+ this->LocalGenerator->AddSharedFlags(linkFlags, linkLanguage, true);
+
+ // Add flags to create an executable.
+ this->LocalGenerator->
+ AddConfigVariableFlags(linkFlags, "CMAKE_EXE_LINKER_FLAGS");
+
+
+ if(this->Target->GetPropertyAsBool("WIN32_EXECUTABLE"))
+ {
+ this->LocalGenerator->AppendFlags(linkFlags,
+ this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
+ }
+ else
+ {
+ this->LocalGenerator->AppendFlags(linkFlags,
+ this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
+ }
+
+ // Add language-specific flags.
+ this->LocalGenerator->AddLanguageFlags(flags, linkLanguage);
+
+ // Add target-specific linker flags.
+ this->LocalGenerator->AppendFlags(linkFlags, this->Target->GetProperty("LINK_FLAGS"));
+
+ // Construct a list of files associated with this executable that
+ // may need to be cleaned.
+ std::vector<std::string> exeCleanFiles;
+ {
+ std::string cleanName;
+ std::string cleanRealName;
+ this->Target->GetExecutableCleanNames(cleanName, cleanRealName,
+ this->LocalGenerator->m_ConfigurationName.c_str());
+ std::string cleanFullName = outpath + cleanName;
+ std::string cleanFullRealName = outpath + cleanRealName;
+ exeCleanFiles.push_back(this->Convert(cleanFullName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ if(cleanRealName != cleanName)
+ {
+ exeCleanFiles.push_back(this->Convert(cleanFullRealName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ }
+ }
+
+ // Add a command to remove any existing files for this executable.
+ std::vector<std::string> commands1;
+ this->LocalGenerator->AppendCleanCommand(commands1, exeCleanFiles);
+ this->LocalGenerator->CreateCDCommand(commands1,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ commands1.clear();
+ // Add the pre-build and pre-link rules.
+ this->LocalGenerator->
+ AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
+ this->LocalGenerator->
+ AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
+
+ // Construct the main link rule.
+ std::string linkRuleVar = "CMAKE_";
+ linkRuleVar += linkLanguage;
+ linkRuleVar += "_LINK_EXECUTABLE";
+ std::string linkRule =
+ this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
+ cmSystemTools::ExpandListArgument(linkRule, commands1);
+ this->LocalGenerator->CreateCDCommand
+ (commands1,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+
+ // Add a rule to create necessary symlinks for the library.
+ if(targetOutPath != targetOutPathReal)
+ {
+ std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
+ symlink += targetOutPathReal;
+ symlink += " ";
+ symlink += targetOutPath;
+ commands.push_back(symlink);
+ }
+
+ // Add the post-build rules.
+ this->LocalGenerator->AppendCustomCommands
+ (commands, this->Target->GetPostBuildCommands());
+
+ // Collect up flags to link in needed libraries.
+ cmOStringStream linklibs;
+ this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string variableName;
+ std::string variableNameExternal;
+ this->WriteObjectsVariable(variableName, variableNameExternal);
+ std::string buildObjs = "$(";
+ buildObjs += variableName;
+ buildObjs += ") $(";
+ buildObjs += variableNameExternal;
+ buildObjs += ")";
+ std::string cleanObjs = "$(";
+ cleanObjs += variableName;
+ cleanObjs += ")";
+
+ // Expand placeholders in the commands.
+ for(std::vector<std::string>::iterator i = commands.begin();
+ i != commands.end(); ++i)
+ {
+ this->LocalGenerator->ExpandRuleVariables(*i,
+ linkLanguage,
+ buildObjs.c_str(),
+ targetOutPathReal.c_str(),
+ linklibs.str().c_str(),
+ 0,
+ 0,
+ flags.c_str(),
+ 0,
+ 0,
+ linkFlags.c_str());
+ }
+
+ // Write the build rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
+ 0,
+ targetFullPathReal.c_str(),
+ depends, commands);
+
+ // The symlink name for the target should depend on the real target
+ // so if the target version changes it rebuilds and recreates the
+ // symlink.
+ if(targetFullPath != targetFullPathReal)
+ {
+ depends.clear();
+ commands.clear();
+ depends.push_back(targetFullPathReal.c_str());
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ targetFullPath.c_str(),
+ depends, commands);
+ }
+
+ // Write convenience targets.
+ std::string dir = this->Makefile->GetStartOutputDirectory();
+ dir += "/";
+ dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ std::string buildTargetRuleName = dir;
+ buildTargetRuleName += "/build";
+ buildTargetRuleName =
+ this->Convert(buildTargetRuleName.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
+ targetFullPath.c_str(),
+ buildTargetRuleName.c_str());
+
+ // Clean all the possible executable names and symlinks and object files.
+ this->CleanFiles.insert(this->CleanFiles.end(),
+ exeCleanFiles.begin(),
+ exeCleanFiles.end());
+ this->CleanFiles.push_back(cleanObjs);
+}
+
diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h
new file mode 100644
index 0000000..a02286c
--- /dev/null
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -0,0 +1,34 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmMakefileExecutableTargetGenerator_h
+#define cmMakefileExecutableTargetGenerator_h
+
+#include "cmMakefileTargetGenerator.h"
+
+class cmMakefileExecutableTargetGenerator: public cmMakefileTargetGenerator
+{
+public:
+ /* the main entry point for this class. Writes the Makefiles associated
+ with this target */
+ virtual void WriteRuleFiles();
+
+protected:
+ virtual void WriteExecutableRule();
+
+};
+
+#endif
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
new file mode 100644
index 0000000..89057f6
--- /dev/null
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -0,0 +1,394 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmMakefileLibraryTargetGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
+{
+ // create the build.make file and directory, put in the common blocks
+ this->CreateRuleFile();
+
+ // Add in any rules for custom commands
+ this->WriteCustomCommandsForTarget();
+
+ // write in rules for object files
+ this->WriteCommonCodeRules();
+
+ // write the link rules
+ // Write the rule for this target type.
+ switch(this->Target->GetType())
+ {
+ case cmTarget::STATIC_LIBRARY:
+ this->WriteStaticLibraryRules();
+ break;
+ case cmTarget::SHARED_LIBRARY:
+ this->WriteSharedLibraryRules();
+ break;
+ case cmTarget::MODULE_LIBRARY:
+ this->WriteModuleLibraryRules();
+ break;
+ default:
+ // If language is not known, this is an error.
+ cmSystemTools::Error("Unknown Library Type");
+ break;
+ }
+
+ // Write the requires target.
+ this->WriteTargetRequiresRules();
+
+ // Write clean target
+ this->WriteTargetCleanRules();
+
+ // close the streams
+ this->CloseFileStreams();
+}
+
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
+{
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+ std::string linkRuleVar = "CMAKE_";
+ if (linkLanguage)
+ {
+ linkRuleVar += linkLanguage;
+ }
+ linkRuleVar += "_CREATE_STATIC_LIBRARY";
+
+ std::string extraFlags;
+ this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules()
+{
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+ std::string linkRuleVar = "CMAKE_";
+ if (linkLanguage)
+ {
+ linkRuleVar += linkLanguage;
+ }
+ linkRuleVar += "_CREATE_SHARED_LIBRARY";
+
+ std::string extraFlags;
+ this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
+ this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_SHARED_LINKER_FLAGS");
+ if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
+ {
+ const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
+ i != sources.end(); ++i)
+ {
+ if((*i)->GetSourceExtension() == "def")
+ {
+ extraFlags += " ";
+ extraFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ extraFlags +=
+ this->Convert((*i)->GetFullPath().c_str(),cmLocalGenerator::START_OUTPUT,cmLocalGenerator::MAKEFILE);
+ }
+ }
+ }
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules()
+{
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+ std::string linkRuleVar = "CMAKE_";
+ if (linkLanguage)
+ {
+ linkRuleVar += linkLanguage;
+ }
+ linkRuleVar += "_CREATE_SHARED_MODULE";
+
+ std::string extraFlags;
+ this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
+ this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS");
+ // TODO: .def files should be supported here also.
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteLibraryRules
+(const char* linkRuleVar, const char* extraFlags)
+{
+ // Write the dependency generation rule.
+ this->WriteTargetDependRules();
+
+ // TODO: Merge the methods that call this method to avoid
+ // code duplication.
+ std::vector<std::string> commands;
+
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string objTarget;
+
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
+ obj != this->Objects.end(); ++obj)
+ {
+ objTarget = relPath;
+ objTarget += *obj;
+ depends.push_back(objTarget);
+ }
+
+ // Add dependencies on targets that must be built first.
+ this->AppendTargetDepends(depends);
+
+ // Add a dependency on the rule file itself.
+ this->LocalGenerator->AppendRuleDepend(depends,
+ this->BuildFileNameFull.c_str());
+
+ for(std::vector<std::string>::const_iterator obj
+ = this->ExternalObjects.begin();
+ obj != this->ExternalObjects.end(); ++obj)
+ {
+ depends.push_back(*obj);
+ }
+
+ // Get the language to use for linking this library.
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+
+ // Make sure we have a link language.
+ if(!linkLanguage)
+ {
+ cmSystemTools::Error("Cannot determine link language for target \"",
+ this->Target->GetName(), "\".");
+ return;
+ }
+
+ // Create set of linking flags.
+ std::string linkFlags;
+ this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+
+ // Construct the name of the library.
+ std::string targetName;
+ std::string targetNameSO;
+ std::string targetNameReal;
+ this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
+ this->LocalGenerator->m_ConfigurationName.c_str());
+
+ // Construct the full path version of the names.
+ std::string outpath = this->LocalGenerator->m_LibraryOutputPath;
+ if(outpath.length() == 0)
+ {
+ outpath = this->Makefile->GetStartOutputDirectory();
+ outpath += "/";
+ }
+ std::string targetFullPath = outpath + targetName;
+ std::string targetFullPathSO = outpath + targetNameSO;
+ std::string targetFullPathReal = outpath + targetNameReal;
+
+ // Construct the output path version of the names for use in command
+ // arguments.
+ std::string targetOutPath =
+ this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ std::string targetOutPathSO =
+ this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ std::string targetOutPathReal =
+ this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+
+ // Add the link message.
+ std::string buildEcho = "Linking ";
+ buildEcho += linkLanguage;
+ switch(this->Target->GetType())
+ {
+ case cmTarget::STATIC_LIBRARY:
+ buildEcho += " static library "; break;
+ case cmTarget::SHARED_LIBRARY:
+ buildEcho += " shared library "; break;
+ case cmTarget::MODULE_LIBRARY:
+ buildEcho += " shared module "; break;
+ default:
+ buildEcho += " library "; break;
+ }
+ buildEcho += targetOutPath.c_str();
+ this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
+
+ // Construct a list of files associated with this library that may
+ // need to be cleaned.
+ std::vector<std::string> libCleanFiles;
+ {
+ std::string cleanStaticName;
+ std::string cleanSharedName;
+ std::string cleanSharedSOName;
+ std::string cleanSharedRealName;
+ this->Target->GetLibraryCleanNames(cleanStaticName,
+ cleanSharedName,
+ cleanSharedSOName,
+ cleanSharedRealName,
+ this->LocalGenerator->m_ConfigurationName.c_str());
+ std::string cleanFullStaticName = outpath + cleanStaticName;
+ std::string cleanFullSharedName = outpath + cleanSharedName;
+ std::string cleanFullSharedSOName = outpath + cleanSharedSOName;
+ std::string cleanFullSharedRealName = outpath + cleanSharedRealName;
+ libCleanFiles.push_back
+ (this->Convert(cleanFullStaticName.c_str(),cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ if(cleanSharedRealName != cleanStaticName)
+ {
+ libCleanFiles.push_back(this->Convert(cleanFullSharedRealName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ }
+ if(cleanSharedSOName != cleanStaticName &&
+ cleanSharedSOName != cleanSharedRealName)
+ {
+ libCleanFiles.push_back(this->Convert(cleanFullSharedSOName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ }
+ if(cleanSharedName != cleanStaticName &&
+ cleanSharedName != cleanSharedSOName &&
+ cleanSharedName != cleanSharedRealName)
+ {
+ libCleanFiles.push_back(this->Convert(cleanFullSharedName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE));
+ }
+ }
+ // Add a command to remove any existing files for this library.
+ std::vector<std::string> commands1;
+ this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles);
+ this->LocalGenerator->CreateCDCommand(commands1,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ commands1.clear();
+ // Add the pre-build and pre-link rules.
+ this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
+ this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
+
+ // Construct the main link rule.
+ std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
+ cmSystemTools::ExpandListArgument(linkRule, commands1);
+ this->LocalGenerator->CreateCDCommand(commands1,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+
+ // Add a rule to create necessary symlinks for the library.
+ if(targetOutPath != targetOutPathReal)
+ {
+ std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
+ symlink += targetOutPathReal;
+ symlink += " ";
+ symlink += targetOutPathSO;
+ symlink += " ";
+ symlink += targetOutPath;
+ commands1.clear();
+ commands1.push_back(symlink);
+ this->LocalGenerator->CreateCDCommand(commands1,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+ commands.insert(commands.end(), commands1.begin(), commands1.end());
+ }
+
+ // Add the post-build rules.
+ this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
+
+ // Collect up flags to link in needed libraries.
+ cmOStringStream linklibs;
+ this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
+
+ // Construct object file lists that may be needed to expand the
+ // rule.
+ std::string variableName;
+ std::string variableNameExternal;
+ this->WriteObjectsVariable(variableName, variableNameExternal);
+ std::string buildObjs = "$(";
+ buildObjs += variableName;
+ buildObjs += ") $(";
+ buildObjs += variableNameExternal;
+ buildObjs += ")";
+ std::string cleanObjs = "$(";
+ cleanObjs += variableName;
+ cleanObjs += ")";
+
+ // Expand placeholders in the commands.
+ for(std::vector<std::string>::iterator i = commands.begin();
+ i != commands.end(); ++i)
+ {
+ this->LocalGenerator->ExpandRuleVariables(*i,
+ linkLanguage,
+ buildObjs.c_str(),
+ targetOutPathReal.c_str(),
+ linklibs.str().c_str(),
+ 0, 0, 0, buildObjs.c_str(),
+ targetNameSO.c_str(),
+ linkFlags.c_str());
+ }
+
+ // Write the build rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ targetFullPathReal.c_str(), depends, commands);
+
+ // The symlink names for the target should depend on the real target
+ // so if the target version changes it rebuilds and recreates the
+ // symlinks.
+ if(targetFullPathSO != targetFullPathReal)
+ {
+ depends.clear();
+ commands.clear();
+ depends.push_back(targetFullPathReal.c_str());
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ targetFullPathSO.c_str(), depends, commands);
+ }
+ if(targetFullPath != targetFullPathSO)
+ {
+ depends.clear();
+ commands.clear();
+ depends.push_back(targetFullPathSO.c_str());
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ targetFullPath.c_str(), depends, commands);
+ }
+
+ // Write convenience targets.
+ std::string dir = this->Makefile->GetStartOutputDirectory();
+ dir += "/";
+ dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ std::string buildTargetRuleName = dir;
+ buildTargetRuleName += "/build";
+ buildTargetRuleName =
+ this->Convert(buildTargetRuleName.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
+ this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
+ targetFullPath.c_str(),
+ buildTargetRuleName.c_str());
+
+ // Clean all the possible library names and symlinks and object files.
+ this->CleanFiles.insert(this->CleanFiles.end(),
+ libCleanFiles.begin(),libCleanFiles.end());
+ this->CleanFiles.push_back(cleanObjs);
+}
+
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
new file mode 100644
index 0000000..7c7c43d
--- /dev/null
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -0,0 +1,37 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmMakefileLibraryTargetGenerator_h
+#define cmMakefileLibraryTargetGenerator_h
+
+#include "cmMakefileTargetGenerator.h"
+
+class cmMakefileLibraryTargetGenerator:
+ public cmMakefileTargetGenerator
+{
+public:
+ /* the main entry point for this class. Writes the Makefiles associated
+ with this target */
+ virtual void WriteRuleFiles();
+
+protected:
+ void WriteStaticLibraryRules();
+ void WriteSharedLibraryRules();
+ void WriteModuleLibraryRules();
+ void WriteLibraryRules(const char *linkRule, const char *extraFlags);
+};
+
+#endif
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
new file mode 100644
index 0000000..87bef28
--- /dev/null
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -0,0 +1,794 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmMakefileTargetGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+#include "cmMakefileExecutableTargetGenerator.h"
+#include "cmMakefileLibraryTargetGenerator.h"
+#include "cmMakefileUtilityTargetGenerator.h"
+
+
+cmMakefileTargetGenerator::cmMakefileTargetGenerator()
+{
+ this->BuildFileStream = 0;
+ this->InfoFileStream = 0;
+ this->FlagFileStream = 0;
+}
+
+cmMakefileTargetGenerator *
+cmMakefileTargetGenerator::New(cmLocalUnixMakefileGenerator3 *lg,
+ cmStdString tgtName, cmTarget *tgt)
+{
+ cmMakefileTargetGenerator *result = 0;
+
+ switch (tgt->GetType())
+ {
+ case cmTarget::EXECUTABLE:
+ result = new cmMakefileExecutableTargetGenerator;
+ break;
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ result = new cmMakefileLibraryTargetGenerator;
+ break;
+ case cmTarget::UTILITY:
+ result = new cmMakefileUtilityTargetGenerator;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ result->TargetName = tgtName;
+ result->Target = tgt;
+ result->LocalGenerator = lg;
+ result->GlobalGenerator = lg->GetGlobalGenerator();
+ result->Makefile = lg->GetMakefile();
+ return result;
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::CreateRuleFile()
+{
+ // Create a directory for this target.
+ this->TargetBuildDirectory =
+ this->LocalGenerator->GetTargetDirectory(*this->Target);
+ this->TargetBuildDirectoryFull =
+ this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
+ cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
+
+ // Construct the rule file name.
+ this->BuildFileName = this->TargetBuildDirectory;
+ this->BuildFileName += "/build.make";
+ this->BuildFileNameFull = this->TargetBuildDirectoryFull;
+ this->BuildFileNameFull += "/build.make";
+
+ // Open the rule file. This should be copy-if-different because the
+ // rules may depend on this file itself.
+ this->BuildFileStream =
+ new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
+ this->BuildFileStream->SetCopyIfDifferent(true);
+ if(!this->BuildFileStream)
+ {
+ return;
+ }
+ this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
+ this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
+ this->LocalGenerator->WriteMakeVariables(*this->BuildFileStream);
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteCustomCommandsForTarget()
+{
+ // write the custom commands for this target
+ // Look for files registered for cleaning in this directory.
+ if(const char* additional_clean_files =
+ this->Makefile->GetProperty
+ ("ADDITIONAL_MAKE_CLEAN_FILES"))
+ {
+ cmSystemTools::ExpandListArgument(additional_clean_files,
+ this->CleanFiles);
+ }
+ this->WriteCustomCommands();
+}
+
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteCommonCodeRules()
+{
+ // Include the dependencies for the target.
+ std::string dependFileNameFull = this->TargetBuildDirectoryFull;
+ dependFileNameFull += "/depend.make";
+ *this->BuildFileStream
+ << "# Include any dependencies generated for this target.\n"
+ << this->LocalGenerator->m_IncludeDirective << " "
+ << this->Convert(dependFileNameFull.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE)
+ << "\n\n";
+
+ // make sure the depend file exists
+ if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
+ {
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
+ depFileStream
+ << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built." << std::endl;
+ }
+
+ // Open the flags file. This should be copy-if-different because the
+ // rules may depend on this file itself.
+ this->FlagFileNameFull = this->TargetBuildDirectoryFull;
+ this->FlagFileNameFull += "/flags.make";
+ this->FlagFileStream =
+ new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
+ this->FlagFileStream->SetCopyIfDifferent(true);
+ if(!this->FlagFileStream)
+ {
+ return;
+ }
+ this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
+
+ // Include the flags for the target.
+ *this->BuildFileStream
+ << "# Include the compile flags for this target's objects.\n"
+ << this->LocalGenerator->m_IncludeDirective << " "
+ << this->Convert(this->FlagFileNameFull.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE)
+ << "\n\n";
+
+ // First generate the object rule files. Save a list of all object
+ // files for this target.
+ const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
+ source != sources.end(); ++source)
+ {
+ if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !(*source)->GetCustomCommand())
+ {
+ if(!this->GlobalGenerator->IgnoreFile
+ ((*source)->GetSourceExtension().c_str()))
+ {
+ // Generate this object file's rule file.
+ this->WriteObjectRuleFiles(*(*source));
+ }
+ else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
+ {
+ // This is an external object file. Just add it.
+ this->ExternalObjects.push_back((*source)->GetFullPath());
+ }
+ else
+ {
+ // We only get here if a source file is not an external object
+ // and has an extension that is listed as an ignored file type
+ // for this language. No message or diagnosis should be
+ // given.
+ }
+ }
+ }
+
+ // write language flags for target
+ std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
+ checkSet =
+ this->LocalGenerator->GetIntegrityCheckSet()[this->Target->GetName()];
+ for(std::map<cmStdString,
+ cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
+ l = checkSet.begin(); l != checkSet.end(); ++l)
+ {
+ const char *lang = l->first.c_str();
+ std::string flags;
+ // Add the export symbol definition for shared library objects.
+ bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
+ (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
+ if(shared)
+ {
+ flags += "-D";
+ if(const char* custom_export_name =
+ this->Target->GetProperty("DEFINE_SYMBOL"))
+ {
+ flags += custom_export_name;
+ }
+ else
+ {
+ std::string in = this->Target->GetName();
+ in += "_EXPORTS";
+ flags += cmSystemTools::MakeCindentifier(in.c_str());
+ }
+ }
+
+ // Add language-specific flags.
+ this->LocalGenerator->AddLanguageFlags(flags, lang);
+
+ // Add shared-library flags if needed.
+ this->LocalGenerator->AddSharedFlags(flags, lang, shared);
+
+ // Add include directory flags.
+ this->LocalGenerator->
+ AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
+ // Add include directory flags.
+ this->LocalGenerator->
+ AppendFlags(flags,this->GetFrameworkFlags().c_str());
+
+ *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
+ }
+}
+
+
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
+{
+ // Identify the language of the source file.
+ const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
+ if(!lang)
+ {
+ // If language is not known, this is an error.
+ cmSystemTools::Error("Source file \"", source.GetFullPath().c_str(),
+ "\" has unknown type.");
+ return;
+ }
+
+ // Get the full path name of the object file.
+ std::string objNoTargetDir;
+ std::string obj =
+ this->LocalGenerator->GetObjectFileName(*this->Target, source, &objNoTargetDir);
+
+ // Avoid generating duplicate rules.
+ if(m_ObjectFiles.find(obj) == m_ObjectFiles.end())
+ {
+ m_ObjectFiles.insert(obj);
+ }
+ else
+ {
+ cmOStringStream err;
+ err << "Warning: Source file \""
+ << source.GetSourceName().c_str() << "."
+ << source.GetSourceExtension().c_str()
+ << "\" is listed multiple times for target \""
+ << this->Target->GetName()
+ << "\".";
+ cmSystemTools::Message(err.str().c_str(), "Warning");
+ return;
+ }
+
+ // Create the directory containing the object file. This may be a
+ // subdirectory under the target's directory.
+ std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
+ cmSystemTools::MakeDirectory
+ (this->LocalGenerator->ConvertToFullPath(dir).c_str());
+
+ // Save this in the target's list of object files.
+ this->Objects.push_back(obj);
+ std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
+ relativeObj += obj;
+ // we compute some depends when writing the depend.make that we will also
+ // use in the build.make, same with depMakeFile
+ std::vector<std::string> depends;
+ std::string depMakeFile;
+
+ // generate the build rule file
+ this->WriteObjectBuildFile(obj, lang, source, depends);
+
+ // The object file should be checked for dependency integrity.
+ this->LocalGenerator->m_CheckDependFiles[this->Target->GetName()][lang].insert(&source);
+ // add this to the list of objects for this local generator
+ if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
+ {
+ objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
+ }
+ this->LocalGenerator->m_LocalObjectFiles[objNoTargetDir].push_back(this->Target);
+}
+
+//----------------------------------------------------------------------------
+void
+cmMakefileTargetGenerator
+::WriteObjectBuildFile(std::string &obj,
+ const char *lang,
+ cmSourceFile& source,
+ std::vector<std::string>& depends)
+{
+ this->LocalGenerator->AppendRuleDepend(depends, this->FlagFileNameFull.c_str());
+
+ // generate the depend scanning rule
+ this->WriteObjectDependRules(source, depends);
+
+ std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
+ relativeObj += obj;
+ if(this->Makefile->GetDefinition("CMAKE_WINDOWS_OBJECT_PATH"))
+ {
+ relativeObj = cmSystemTools::ConvertToOutputPath(relativeObj.c_str());
+ }
+ // Write the build rule.
+ // Build the set of compiler flags.
+ std::string flags;
+ if(this->Target->GetProperty("COMPILE_FLAGS"))
+ {
+ this->LocalGenerator->AppendFlags(flags, this->Target->GetProperty("COMPILE_FLAGS"));
+ }
+
+ // Add flags from source file properties.
+ if (source.GetProperty("COMPILE_FLAGS"))
+ {
+ this->LocalGenerator->AppendFlags(flags, source.GetProperty("COMPILE_FLAGS"));
+ *this->FlagFileStream << "# Custom flags: "
+ << relativeObj << "_FLAGS = "
+ << source.GetProperty("COMPILE_FLAGS")
+ << "\n"
+ << "\n";
+ }
+
+ // Add language-specific flags.
+ std::string langFlags = "$(";
+ langFlags += lang;
+ langFlags += "_FLAGS)";
+ this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
+
+ // Get the output paths for source and object files.
+ std::string sourceFile = source.GetFullPath();
+ if(this->LocalGenerator->m_UseRelativePaths)
+ {
+ sourceFile = this->Convert(sourceFile.c_str(),
+ cmLocalGenerator::HOME_OUTPUT);
+ }
+ sourceFile = this->Convert(sourceFile.c_str(),
+ cmLocalGenerator::NONE,
+ cmLocalGenerator::SHELL);
+ std::string objectFile =
+ this->Convert(obj.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+
+ // Construct the build message.
+ std::vector<std::string> no_commands;
+ std::vector<std::string> commands;
+ std::string buildEcho = "Building ";
+ buildEcho += lang;
+ buildEcho += " object ";
+ buildEcho += relativeObj;
+ this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
+
+ // Construct the compile rules.
+ std::string compileRuleVar = "CMAKE_";
+ compileRuleVar += lang;
+ compileRuleVar += "_COMPILE_OBJECT";
+ std::string compileRule =
+ this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
+ cmSystemTools::ExpandListArgument(compileRule, commands);
+
+ // Expand placeholders in the commands.
+ for(std::vector<std::string>::iterator i = commands.begin();
+ i != commands.end(); ++i)
+ {
+ this->LocalGenerator->ExpandRuleVariables(*i,
+ lang,
+ 0, // no objects
+ 0, // no target
+ 0, // no link libs
+ sourceFile.c_str(),
+ relativeObj.c_str(),
+ flags.c_str());
+ }
+
+ // Make the target dependency scanning rule include cmake-time-known
+ // dependencies. The others are handled by the check-build-system
+ // path.
+ std::string depMark =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ depMark += "/depend.make.mark";
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depMark.c_str(), depends, no_commands);
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ relativeObj.c_str(), depends, commands);
+
+ // If the language needs provides-requires mode, create the
+ // corresponding targets.
+ std::string objectRequires = relativeObj;
+ objectRequires += ".requires";
+ std::vector<std::string> p_depends;
+ // always provide an empty requires target
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ objectRequires.c_str(), p_depends,
+ no_commands);
+
+ // write a build rule to recursively build what this obj provides
+ std::string objectProvides = relativeObj;
+ objectProvides += ".provides";
+ std::string temp = relativeObj;
+ temp += ".provides.build";
+ std::vector<std::string> r_commands;
+ std::string tgtMakefileName =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ tgtMakefileName += "/build.make";
+ r_commands.push_back
+ (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),temp.c_str()));
+ p_depends.clear();
+ p_depends.push_back(objectRequires);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ objectProvides.c_str(), p_depends,
+ r_commands);
+
+ // write the provides.build rule dependency on the obj file
+ p_depends.clear();
+ p_depends.push_back(relativeObj);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ temp.c_str(), p_depends, no_commands);
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteTargetRequiresRules()
+{
+ std::vector<std::string> depends;
+ std::vector<std::string> no_commands;
+
+ // Construct the name of the dependency generation target.
+ std::string depTarget =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ depTarget += "/requires";
+
+ // This target drives dependency generation for all object files.
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string objTarget;
+ for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
+ obj != this->Objects.end(); ++obj)
+ {
+ objTarget = relPath;
+ objTarget += *obj;
+ objTarget += ".requires";
+ depends.push_back(objTarget);
+ }
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(), depends, no_commands);
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteTargetCleanRules()
+{
+ std::vector<std::string> depends;
+ const char* sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE");
+ if(sym)
+ {
+ depends.push_back(sym);
+ }
+ std::vector<std::string> commands;
+
+ // Construct the clean target name.
+ std::string cleanTarget =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ cleanTarget += "/clean";
+
+ // Construct the clean command.
+ this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles);
+ this->LocalGenerator->CreateCDCommand(commands,
+ this->Makefile->GetStartOutputDirectory(),
+ this->Makefile->GetHomeOutputDirectory());
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ cleanTarget.c_str(), depends, commands);
+}
+
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteTargetDependRules()
+{
+ // must write the targets depend info file
+ std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ this->InfoFileNameFull = dir;
+ this->InfoFileNameFull += "/DependInfo.cmake";
+ this->InfoFileNameFull =
+ this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
+ this->InfoFileStream =
+ new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
+ this->InfoFileStream->SetCopyIfDifferent(true);
+ if(!*this->InfoFileStream)
+ {
+ return;
+ }
+ this->LocalGenerator->
+ WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
+
+ // and now write the rule to use it
+ std::vector<std::string> depends;
+ std::vector<std::string> commands;
+
+ // Construct the name of the dependency generation target.
+ std::string depTarget =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ depTarget += "/depend";
+
+ std::string depMark = depTarget;
+ depMark += ".make.mark";
+ depends.push_back(depMark);
+
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(), depends, commands);
+ depends.clear();
+
+ // Write the dependency generation rule.
+ std::string depEcho = "Scanning dependencies of target ";
+ depEcho += this->Target->GetName();
+ this->LocalGenerator->AppendEcho(commands, depEcho.c_str());
+
+ // Add a command to call CMake to scan dependencies. CMake will
+ // touch the corresponding depends file after scanning dependencies.
+ cmOStringStream depCmd;
+ // TODO: Account for source file properties and directory-level
+ // definitions when scanning for dependencies.
+ depCmd << "$(CMAKE_COMMAND) -E cmake_depends "
+ << " \""
+ << this->GlobalGenerator->GetName() << "\" "
+ << this->LocalGenerator->Convert
+ (this->Makefile->GetHomeOutputDirectory(),
+ cmLocalGenerator::FULL,cmLocalGenerator::SHELL)
+ << " "
+ << this->LocalGenerator->Convert
+ (this->Makefile->GetStartOutputDirectory(),
+ cmLocalGenerator::FULL,cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->InfoFileNameFull.c_str(),
+ cmLocalGenerator::FULL,
+ cmLocalGenerator::SHELL);
+ commands.push_back(depCmd.str());
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depMark.c_str(), depends, commands);
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::WriteObjectDependRules(cmSourceFile& source,
+ std::vector<std::string>& depends)
+{
+ // Create the list of dependencies known at cmake time. These are
+ // shared between the object file and dependency scanning rule.
+ depends.push_back(source.GetFullPath());
+ if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
+ {
+ std::vector<std::string> deps;
+ cmSystemTools::ExpandListArgument(objectDeps, deps);
+ for(std::vector<std::string>::iterator i = deps.begin();
+ i != deps.end(); ++i)
+ {
+ depends.push_back(i->c_str());
+ }
+ }
+}
+
+void cmMakefileTargetGenerator::WriteCustomCommands()
+{
+ // add custom commands to the clean rules?
+ const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
+ bool clean = cmSystemTools::IsOff(clean_no_custom);
+
+ // Generate the rule files for each custom command.
+ const std::vector<cmSourceFile*> &classes = this->Makefile->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+ i != classes.end(); i++)
+ {
+ if(cmCustomCommand* cc = (*i)->GetCustomCommand())
+ {
+ this->GenerateCustomRuleFile(*cc);
+ if (clean)
+ {
+ this->CleanFiles.push_back
+ (this->Convert(cc->GetOutput(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL));
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::GenerateCustomRuleFile(const cmCustomCommand& cc)
+{
+ // Convert the output name to a relative path if possible.
+ std::string output = this->Convert(cc.GetOutput(),
+ cmLocalGenerator::START_OUTPUT);
+
+ // Collect the commands.
+ std::vector<std::string> commands;
+ std::string preEcho = "Generating ";
+ preEcho += output;
+ this->LocalGenerator->AppendEcho(commands, preEcho.c_str());
+ this->LocalGenerator->AppendCustomCommand(commands, cc);
+
+ // Collect the dependencies.
+ std::vector<std::string> depends;
+ this->LocalGenerator->AppendCustomDepend(depends, cc);
+
+ // Write the rule.
+ const char* comment = 0;
+ if(cc.GetComment() && *cc.GetComment())
+ {
+ comment = cc.GetComment();
+ }
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
+ cc.GetOutput(), depends, commands);
+}
+
+//----------------------------------------------------------------------------
+void
+cmMakefileTargetGenerator
+::WriteObjectsVariable(std::string& variableName,
+ std::string& variableNameExternal)
+{
+ // Write a make variable assignment that lists all objects for the
+ // target.
+ variableName =
+ this->LocalGenerator->CreateMakeVariable(this->Target->GetName(), "_OBJECTS");
+ *this->BuildFileStream
+ << "# Object files for target " << this->Target->GetName() << "\n"
+ << variableName.c_str() << " =";
+ std::string object;
+ const char* objName =
+ this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
+ const char* lineContinue =
+ this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
+ if(!lineContinue)
+ {
+ lineContinue = "\\";
+ }
+ for(std::vector<std::string>::const_iterator i = this->Objects.begin();
+ i != this->Objects.end(); ++i)
+ {
+ *this->BuildFileStream << " " << lineContinue << "\n";
+ if(objName)
+ {
+ *this->BuildFileStream <<
+ this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ }
+ else
+ {
+ *this->BuildFileStream <<
+ this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
+ }
+ }
+ *this->BuildFileStream << "\n";
+
+ // Write a make variable assignment that lists all external objects
+ // for the target.
+ variableNameExternal =
+ this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),"_EXTERNAL_OBJECTS");
+ *this->BuildFileStream
+ << "\n"
+ << "# External object files for target " << this->Target->GetName() << "\n"
+ << variableNameExternal.c_str() << " =";
+ for(std::vector<std::string>::const_iterator i =
+ this->ExternalObjects.begin();
+ i != this->ExternalObjects.end(); ++i)
+ {
+ object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
+ *this->BuildFileStream
+ << " " << lineContinue << "\n"
+ << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
+ if(objName)
+ {
+ *this->BuildFileStream << this->Convert(i->c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ }
+ else
+ {
+ *this->BuildFileStream <<
+ this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
+ }
+ }
+ *this->BuildFileStream << "\n" << "\n";
+}
+
+
+//----------------------------------------------------------------------------
+std::string cmMakefileTargetGenerator::GetFrameworkFlags()
+{
+#ifndef __APPLE__
+ return std::string();
+#else
+ std::set<cmStdString> emitted;
+ std::vector<std::string> includes;
+ this->GetIncludeDirectories(includes);
+ std::vector<std::string>::iterator i;
+ // check all include directories for frameworks as this
+ // will already have added a -F for the framework
+ for(i = includes.begin(); i != includes.end(); ++i)
+ {
+ if(cmSystemTools::IsPathToFramework(i->c_str()))
+ {
+ std::string frameworkDir = *i;
+ frameworkDir += "/../";
+ frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
+ emitted.insert(frameworkDir);
+ }
+ }
+
+ std::string flags;
+ std::vector<std::string>& frameworks = this->Target->GetFrameworks();
+ for(i = frameworks.begin();
+ i != frameworks.end(); ++i)
+ {
+ if(emitted.insert(*i).second)
+ {
+ flags += "-F";
+ flags += this->LocalGenerator->ConvertToOutputForExisting(i->c_str());
+ flags += " ";
+ }
+ }
+ return flags;
+#endif
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::AppendTargetDepends(std::vector<std::string>& depends)
+{
+ // Static libraries never depend on anything for linking.
+ if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ return;
+ }
+
+ // Keep track of dependencies already listed.
+ std::set<cmStdString> emitted;
+
+ // A target should not depend on itself.
+ emitted.insert(this->Target->GetName());
+
+ // Loop over all library dependencies.
+ const cmTarget::LinkLibraries& tlibs = this->Target->GetLinkLibraries();
+ for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
+ lib != tlibs.end(); ++lib)
+ {
+ // Don't emit the same library twice for this target.
+ if(emitted.insert(lib->first).second)
+ {
+ // Depend only on other CMake targets.
+ if(cmTarget* tgt =
+ this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
+ {
+ if(const char* location =
+ tgt->GetLocation(this->LocalGenerator->m_ConfigurationName.c_str()))
+ {
+ depends.push_back(location);
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::CloseFileStreams()
+{
+ delete this->BuildFileStream;
+ delete this->InfoFileStream;
+ delete this->FlagFileStream;
+}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
new file mode 100644
index 0000000..eaf8f86
--- /dev/null
+++ b/Source/cmMakefileTargetGenerator.h
@@ -0,0 +1,152 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmMakefileTargetGenerator_h
+#define cmMakefileTargetGenerator_h
+
+#include "cmLocalUnixMakefileGenerator3.h"
+
+class cmCustomCommand;
+class cmDependInformation;
+class cmDepends;
+class cmGeneratedFileStream;
+class cmGlobalGenerator;
+class cmLocalUnixMakefileGenerator3;
+class cmMakeDepend;
+class cmMakefile;
+class cmTarget;
+class cmSourceFile;
+
+/** \class cmMakefileTargetGenerator
+ * \brief Support Routines for writing makefiles
+ *
+ */
+class cmMakefileTargetGenerator
+{
+public:
+ // construct using this factory call
+ static cmMakefileTargetGenerator *New(cmLocalUnixMakefileGenerator3 *lg,
+ cmStdString tgtName,
+ cmTarget *tgt);
+
+ /* the main entry point for this class. Writes the Makefiles associated
+ with this target */
+ virtual void WriteRuleFiles() = 0;
+
+protected:
+
+ // create the file and directory etc
+ void CreateRuleFile();
+
+ // outputs the rules for any custom commands used by this target
+ void WriteCustomCommandsForTarget();
+
+ // write some common code at the top of build.make
+ void WriteCommonCodeRules();
+
+ // write the provide require rules for this target
+ void WriteTargetRequiresRules();
+
+ // write the clean rules for this target
+ void WriteTargetCleanRules();
+
+ // write the depend rules for this target
+ void WriteTargetDependRules();
+
+ // write the rules for an object
+ void WriteObjectRuleFiles(cmSourceFile& source);
+
+ // write the build rule for an object
+ void WriteObjectBuildFile(std::string &obj,
+ const char *lang,
+ cmSourceFile& source,
+ std::vector<std::string>& depends);
+
+ // write the depend.make file for an object
+ void WriteObjectDependRules(cmSourceFile& source,
+ std::vector<std::string>& depends);
+
+ // this is responsible for writing all of the rules for all this
+ // directories custom commands (but not utility targets)
+ void WriteCustomCommands();
+ void GenerateCustomRuleFile(const cmCustomCommand& cc);
+
+ // write out the variable that lists the objects for this target
+ void WriteObjectsVariable(std::string& variableName,
+ std::string& variableNameExternal);
+
+ // Return the a string with -F flags on apple
+ std::string GetFrameworkFlags();
+
+ // append intertarget dependencies
+ void AppendTargetDepends(std::vector<std::string>& depends);
+
+ virtual void CloseFileStreams();
+
+ cmStdString TargetName;
+ cmTarget *Target;
+ cmLocalUnixMakefileGenerator3 *LocalGenerator;
+ cmGlobalGenerator *GlobalGenerator;
+ cmMakefile *Makefile;
+
+ // the full path to the build file
+ std::string BuildFileName;
+ std::string BuildFileNameFull;
+
+ // the path to the directory the build file is in
+ std::string TargetBuildDirectory;
+ std::string TargetBuildDirectoryFull;
+
+ // the stream for the build file
+ cmGeneratedFileStream *BuildFileStream;
+
+ // the stream for the flag file
+ std::string FlagFileNameFull;
+ cmGeneratedFileStream *FlagFileStream;
+
+ // the stream for the info file
+ std::string InfoFileNameFull;
+ cmGeneratedFileStream *InfoFileStream;
+
+ // files to clean
+ std::vector<std::string> CleanFiles;
+
+ // objects used by this target
+ std::vector<std::string> Objects;
+ std::vector<std::string> ExternalObjects;
+
+ // Set of object file names that will be built in this directory.
+ std::set<cmStdString> m_ObjectFiles;
+
+
+ //==================================================================
+ // Convenience routines that do nothing more than forward to
+ // implementaitons
+ std::string Convert(const char* source,
+ cmLocalGenerator::RelativeRoot relative,
+ cmLocalGenerator::OutputFormat output =
+ cmLocalGenerator::UNCHANGED,
+ bool optional = false)
+ {
+ return this->LocalGenerator->Convert(source, relative, output, optional);
+ }
+
+ // constructor to set the ivarscmMakefileTargetGenerator
+ cmMakefileTargetGenerator();
+
+};
+
+#endif
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
new file mode 100644
index 0000000..9843a06
--- /dev/null
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -0,0 +1,90 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmMakefileUtilityTargetGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+
+//----------------------------------------------------------------------------
+void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
+{
+ this->CreateRuleFile();
+
+ *this->BuildFileStream
+ << "# Utility rule file for " << this->Target->GetName() << ".\n\n";
+
+ // write the custom commands for this target
+ this->WriteCustomCommandsForTarget();
+
+ // Collect the commands and dependencies.
+ std::vector<std::string> commands;
+ std::vector<std::string> depends;
+ const char* sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE");
+ if(sym)
+ {
+ depends.push_back(sym);
+ }
+
+ // Utility targets store their rules in pre- and post-build commands.
+ this->LocalGenerator->AppendCustomDepends
+ (depends, this->Target->GetPreBuildCommands());
+ this->LocalGenerator->AppendCustomDepends
+ (depends, this->Target->GetPostBuildCommands());
+ this->LocalGenerator->AppendCustomCommands
+ (commands, this->Target->GetPreBuildCommands());
+ this->LocalGenerator->AppendCustomCommands
+ (commands, this->Target->GetPostBuildCommands());
+
+ // Add dependencies on targets that must be built first.
+ this->AppendTargetDepends(depends);
+
+ // Add a dependency on the rule file itself.
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string objTarget = relPath;
+ objTarget += this->BuildFileName;
+ this->LocalGenerator->AppendRuleDepend(depends, objTarget.c_str());
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ this->Target->GetName(), depends, commands);
+
+ // Write convenience targets.
+ std::string dir = this->Makefile->GetStartOutputDirectory();
+ dir += "/";
+ dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ std::string buildTargetRuleName = dir;
+ buildTargetRuleName += "/build";
+ buildTargetRuleName =
+ this->LocalGenerator->Convert(buildTargetRuleName.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
+ this->Target->GetName(),
+ buildTargetRuleName.c_str());
+
+ // Write clean target
+ this->WriteTargetCleanRules();
+
+ // close the streams
+ this->CloseFileStreams();
+}
+
diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h
new file mode 100644
index 0000000..c8642a6
--- /dev/null
+++ b/Source/cmMakefileUtilityTargetGenerator.h
@@ -0,0 +1,34 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmMakefileUtilityTargetGenerator_h
+#define cmMakefileUtilityTargetGenerator_h
+
+#include "cmMakefileTargetGenerator.h"
+
+class cmMakefileUtilityTargetGenerator:
+ public cmMakefileTargetGenerator
+{
+public:
+ /* the main entry point for this class. Writes the Makefiles associated
+ with this target */
+ virtual void WriteRuleFiles();
+
+protected:
+
+};
+
+#endif