summaryrefslogtreecommitdiffstats
path: root/Source/cmMakefileTargetGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmMakefileTargetGenerator.cxx')
-rw-r--r--Source/cmMakefileTargetGenerator.cxx794
1 files changed, 794 insertions, 0 deletions
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;
+}