summaryrefslogtreecommitdiff
path: root/Source/cmNinjaTargetGenerator.cxx
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 15:39:57 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 15:39:57 -0700
commit035c7fabc3b82cbc9a346c11abe2e9462b4c0379 (patch)
tree7e40f5a790eae329a8c5d3e59f046451767956ff /Source/cmNinjaTargetGenerator.cxx
downloadcmake-035c7fabc3b82cbc9a346c11abe2e9462b4c0379.tar.gz
cmake-035c7fabc3b82cbc9a346c11abe2e9462b4c0379.tar.bz2
cmake-035c7fabc3b82cbc9a346c11abe2e9462b4c0379.zip
Imported Upstream version 2.8.9upstream/2.8.9
Diffstat (limited to 'Source/cmNinjaTargetGenerator.cxx')
-rw-r--r--Source/cmNinjaTargetGenerator.cxx689
1 files changed, 689 insertions, 0 deletions
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
new file mode 100644
index 000000000..3532c8ba4
--- /dev/null
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -0,0 +1,689 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmNinjaTargetGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmNinjaNormalTargetGenerator.h"
+#include "cmNinjaUtilityTargetGenerator.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+#include "cmComputeLinkInformation.h"
+#include "cmSourceFile.h"
+#include "cmCustomCommandGenerator.h"
+
+#include <algorithm>
+
+cmNinjaTargetGenerator *
+cmNinjaTargetGenerator::New(cmTarget* target)
+{
+ switch (target->GetType())
+ {
+ case cmTarget::EXECUTABLE:
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
+ return new cmNinjaNormalTargetGenerator(target);
+
+ case cmTarget::UTILITY:
+ return new cmNinjaUtilityTargetGenerator(target);;
+
+ case cmTarget::GLOBAL_TARGET: {
+ // We only want to process global targets that live in the home
+ // (i.e. top-level) directory. CMake creates copies of these targets
+ // in every directory, which we don't need.
+ cmMakefile *mf = target->GetMakefile();
+ if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0)
+ return new cmNinjaUtilityTargetGenerator(target);
+ // else fallthrough
+ }
+
+ default:
+ return 0;
+ }
+}
+
+cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
+ :
+ MacOSXContentGenerator(0),
+ OSXBundleGenerator(0),
+ MacContentFolders(),
+ Target(target),
+ Makefile(target->GetMakefile()),
+ LocalGenerator(
+ static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
+ Objects()
+{
+ this->GeneratorTarget =
+ this->GetGlobalGenerator()->GetGeneratorTarget(target);
+ MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
+}
+
+cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
+{
+ delete this->MacOSXContentGenerator;
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
+{
+ return *this->GetGlobalGenerator()->GetBuildFileStream();
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const
+{
+ return *this->GetGlobalGenerator()->GetRulesFileStream();
+}
+
+cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
+{
+ return this->LocalGenerator->GetGlobalNinjaGenerator();
+}
+
+const char* cmNinjaTargetGenerator::GetConfigName() const
+{
+ return this->LocalGenerator->GetConfigName();
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+const char* cmNinjaTargetGenerator::GetFeature(const char* feature)
+{
+ return this->Target->GetFeature(feature, this->GetConfigName());
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature)
+{
+ return cmSystemTools::IsOn(this->GetFeature(feature));
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags,
+ const char* lang)
+{
+ // Add language-specific flags.
+ this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName());
+
+ if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
+ {
+ this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+ }
+}
+
+// TODO: Most of the code is picked up from
+// void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink),
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
+// Refactor it.
+std::string
+cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
+ const std::string& language)
+{
+ std::string flags;
+
+ this->AddFeatureFlags(flags, language.c_str());
+
+ this->GetLocalGenerator()->AddArchitectureFlags(flags,
+ this->GetTarget(),
+ language.c_str(),
+ this->GetConfigName());
+
+ // TODO: Fortran support.
+ // // Fortran-specific flags computed for this target.
+ // if(*l == "Fortran")
+ // {
+ // this->AddFortranFlags(flags);
+ // }
+
+ // Add shared-library flags if needed.
+ this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
+ language.c_str());
+
+ // Add include directory flags.
+ {
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target,
+ language.c_str());
+ std::string includeFlags =
+ this->LocalGenerator->GetIncludeFlags(includes, language.c_str(),
+ language == "RC" ? true : false); // full include paths for RC
+ // needed by cmcldeps
+ if(cmGlobalNinjaGenerator::IsMinGW())
+ cmSystemTools::ReplaceString(includeFlags, "\\", "/");
+
+ this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
+ }
+
+ // Append old-style preprocessor definition flags.
+ this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
+
+ // Add target-specific and source-specific flags.
+ this->LocalGenerator->AppendFlags(flags,
+ this->Target->GetProperty("COMPILE_FLAGS"));
+ this->LocalGenerator->AppendFlags(flags,
+ source->GetProperty("COMPILE_FLAGS"));
+
+ // TODO: Handle Apple frameworks.
+
+ return flags;
+}
+
+// TODO: Refactor with
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
+std::string
+cmNinjaTargetGenerator::
+ComputeDefines(cmSourceFile *source, const std::string& language)
+{
+ std::string defines;
+
+ // Add the export symbol definition for shared library objects.
+ if(const char* exportMacro = this->Target->GetExportMacro())
+ {
+ this->LocalGenerator->AppendDefines(defines, exportMacro,
+ language.c_str());
+ }
+
+ // Add preprocessor definitions for this target and configuration.
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Makefile->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Target->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ source->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ {
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(this->GetConfigName());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Makefile->GetProperty(defPropName.c_str()),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Target->GetProperty(defPropName.c_str()),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ source->GetProperty(defPropName.c_str()),
+ language.c_str());
+ }
+
+ return defines;
+}
+
+cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
+{
+ // Static libraries never depend on other targets for linking.
+ if (this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
+ this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
+ return cmNinjaDeps();
+
+ cmComputeLinkInformation* cli =
+ this->Target->GetLinkInformation(this->GetConfigName());
+ if(!cli)
+ return cmNinjaDeps();
+
+ const std::vector<std::string> &deps = cli->GetDepends();
+ cmNinjaDeps result(deps.size());
+ std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+
+ // Add a dependency on the link definitions file, if any.
+ if(!this->ModuleDefinitionFile.empty())
+ {
+ result.push_back(this->ModuleDefinitionFile);
+ }
+
+ return result;
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetSourceFilePath(cmSourceFile* source) const
+{
+ return ConvertToNinjaPath(source->GetFullPath().c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetObjectFilePath(cmSourceFile* source) const
+{
+ std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+ if(!path.empty())
+ path += "/";
+ std::string const& objectName = this->GeneratorTarget->Objects[source];
+ path += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ path += "/";
+ path += objectName;
+ return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
+{
+ std::string dir = this->Target->GetDirectory(this->GetConfigName());
+ return ConvertToNinjaPath(dir.c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetTargetFilePath(const std::string& name) const
+{
+ std::string path = this->GetTargetOutputDir();
+ if (path.empty() || path == ".")
+ return name;
+ path += "/";
+ path += name;
+ return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetName() const
+{
+ return this->Target->GetName();
+}
+
+std::string cmNinjaTargetGenerator::GetTargetPDB() const
+{
+ std::string targetFullPathPDB;
+ if(this->Target->GetType() == cmTarget::EXECUTABLE ||
+ this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
+ this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->Target->GetType() == cmTarget::MODULE_LIBRARY)
+ {
+ targetFullPathPDB = this->Target->GetDirectory(this->GetConfigName());
+ targetFullPathPDB += "/";
+ targetFullPathPDB += this->Target->GetPDBName(this->GetConfigName());
+ }
+
+ return targetFullPathPDB.c_str();
+}
+
+
+void
+cmNinjaTargetGenerator
+::WriteLanguageRules(const std::string& language)
+{
+#ifdef NINJA_GEN_VERBOSE_FILES
+ this->GetRulesFileStream()
+ << "# Rules for language " << language << "\n\n";
+#endif
+ this->WriteCompileRule(language);
+}
+
+void
+cmNinjaTargetGenerator
+::WriteCompileRule(const std::string& language)
+{
+ cmLocalGenerator::RuleVariables vars;
+ vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
+ vars.CMTarget = this->GetTarget();
+ std::string lang = language;
+ vars.Language = lang.c_str();
+ vars.Source = "$in";
+ vars.Object = "$out";
+ std::string flags = "$FLAGS";
+ vars.Defines = "$DEFINES";
+ vars.TargetPDB = "$TARGET_PDB";
+
+
+ cmMakefile* mf = this->GetMakefile();
+
+ bool useClDeps = false;
+ std::string clDepsBinary;
+ std::string clShowPrefix;
+ if (lang == "C" || lang == "CXX" || lang == "RC")
+ {
+ const char* depsPtr = mf->GetDefinition("CMAKE_CMCLDEPS_EXECUTABLE");
+ const char* showPtr = mf->GetDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX");
+ if (depsPtr && showPtr)
+ {
+ // don't wrap for try_compile,
+ // TODO but why doesn't it work with cmcldeps?
+ const std::string projectName = mf->GetProjectName() ?
+ mf->GetProjectName() : "";
+ if (projectName != "CMAKE_TRY_COMPILE")
+ {
+ useClDeps = true;
+ std::string qu = "\"";
+ clDepsBinary = qu + depsPtr + qu;
+ clShowPrefix = qu + showPtr + qu;
+ vars.DependencyFile = "$DEP_FILE";
+ }
+ }
+ }
+
+
+ std::string depfile;
+ std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
+ const char *depfileFlags = mf->GetDefinition(depfileFlagsName.c_str());
+ if (depfileFlags || useClDeps) {
+ std::string depFlagsStr = depfileFlags ? depfileFlags : "";
+ depfile = "$DEP_FILE";
+ cmSystemTools::ReplaceString(depFlagsStr, "<DEPFILE>", "\"$DEP_FILE\"");
+ cmSystemTools::ReplaceString(depFlagsStr, "<OBJECT>", "$out");
+ cmSystemTools::ReplaceString(depFlagsStr, "<CMAKE_C_COMPILER>",
+ mf->GetDefinition("CMAKE_C_COMPILER"));
+ flags += " " + depFlagsStr;
+ }
+ vars.Flags = flags.c_str();
+
+
+ // Rule for compiling object file.
+ std::string compileCmdVar = "CMAKE_";
+ compileCmdVar += language;
+ compileCmdVar += "_COMPILE_OBJECT";
+ std::string compileCmd = mf->GetRequiredDefinition(compileCmdVar.c_str());
+ std::vector<std::string> compileCmds;
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+
+ for (std::vector<std::string>::iterator i = compileCmds.begin();
+ i != compileCmds.end(); ++i)
+ this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+
+ std::string cmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+
+ if(useClDeps)
+ {
+ std::string cl = mf->GetDefinition("CMAKE_C_COMPILER");
+ cl = "\"" + cl + "\" ";
+ cmdLine = clDepsBinary + " " + lang + " $in \"$DEP_FILE\" $out "
+ + clShowPrefix + " " + cl + cmdLine;
+ }
+
+ // Write the rule for compiling file of the given language.
+ cmOStringStream comment;
+ comment << "Rule for compiling " << language << " files.";
+ cmOStringStream description;
+ description << "Building " << language << " object $out";
+ this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
+ cmdLine,
+ description.str(),
+ comment.str(),
+ depfile);
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatements()
+{
+ // Write comments.
+ cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+ this->GetBuildFileStream()
+ << "# Object build statements for "
+ << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+ << " target "
+ << this->GetTargetName()
+ << "\n\n";
+
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
+ {
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+ }
+ this->OSXBundleGenerator->GenerateMacOSXContentStatements(
+ this->GeneratorTarget->HeaderSources,
+ this->MacOSXContentGenerator);
+ this->OSXBundleGenerator->GenerateMacOSXContentStatements(
+ this->GeneratorTarget->ExtraSources,
+ this->MacOSXContentGenerator);
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ this->Objects.push_back(this->GetSourceFilePath(*si));
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
+ {
+ this->WriteObjectBuildStatement(*si);
+ }
+ if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
+ {
+ this->ModuleDefinitionFile = this->ConvertToNinjaPath(
+ this->GeneratorTarget->ModuleDefinitionFile.c_str());
+ }
+
+ {
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ for(std::vector<std::string>::iterator oi = objs.begin();
+ oi != objs.end(); ++oi)
+ {
+ this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
+ }
+ }
+
+ this->GetBuildFileStream() << "\n";
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatement(cmSourceFile* source)
+{
+ cmNinjaDeps emptyDeps;
+
+ std::string comment;
+ const std::string language = source->GetLanguage();
+ std::string rule = this->LanguageCompilerRule(language);
+
+ cmNinjaDeps outputs;
+ std::string objectFileName = this->GetObjectFilePath(source);
+ outputs.push_back(objectFileName);
+ // Add this object to the list of object files.
+ this->Objects.push_back(objectFileName);
+
+ cmNinjaDeps explicitDeps;
+ std::string sourceFileName;
+ if (language == "RC")
+ sourceFileName = source->GetFullPath();
+ else
+ sourceFileName = this->GetSourceFilePath(source);
+ explicitDeps.push_back(sourceFileName);
+
+ // Ensure that the target dependencies are built before any source file in
+ // the target, using order-only dependencies.
+ cmNinjaDeps orderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
+
+ if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
+ std::vector<std::string> depList;
+ cmSystemTools::ExpandListArgument(objectDeps, depList);
+ std::transform(depList.begin(), depList.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ }
+
+ // Add order-only dependencies on custom command outputs.
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
+ {
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ const std::vector<std::string>& ccoutputs = cc->GetOutputs();
+ std::transform(ccoutputs.begin(), ccoutputs.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ }
+
+ // If the source file is GENERATED and does not have a custom command
+ // (either attached to this source file or another one), assume that one of
+ // the target dependencies, OBJECT_DEPENDS or header file custom commands
+ // will rebuild the file.
+ if (source->GetPropertyAsBool("GENERATED") && !source->GetCustomCommand() &&
+ !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
+ this->GetGlobalGenerator()->AddAssumedSourceDependencies(sourceFileName,
+ orderOnlyDeps);
+ }
+
+ cmNinjaVars vars;
+ vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
+ vars["DEFINES"] = this->ComputeDefines(source, language);
+ vars["DEP_FILE"] = objectFileName + ".d";;
+ EnsureParentDirectoryExists(objectFileName);
+
+ // TODO move to GetTargetPDB
+ cmMakefile* mf = this->GetMakefile();
+ if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
+ mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
+ {
+ vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ ConvertToNinjaPath(GetTargetPDB().c_str()).c_str(),
+ cmLocalGenerator::SHELL);
+ }
+
+ if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS"))
+ {
+ cmLocalGenerator::RuleVariables compileObjectVars;
+ std::string lang = language;
+ compileObjectVars.Language = lang.c_str();
+
+ std::string escapedSourceFileName = sourceFileName;
+
+ if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str()))
+ {
+ escapedSourceFileName = cmSystemTools::CollapseFullPath(
+ escapedSourceFileName.c_str(),
+ this->GetGlobalGenerator()->GetCMakeInstance()->
+ GetHomeOutputDirectory());
+ }
+
+ escapedSourceFileName =
+ this->LocalGenerator->ConvertToOutputFormat(
+ escapedSourceFileName.c_str(), cmLocalGenerator::SHELL);
+
+ compileObjectVars.Source = escapedSourceFileName.c_str();
+ compileObjectVars.Object = objectFileName.c_str();
+ compileObjectVars.Flags = vars["FLAGS"].c_str();
+ compileObjectVars.Defines = vars["DEFINES"].c_str();
+
+ // Rule for compiling object file.
+ std::string compileCmdVar = "CMAKE_";
+ compileCmdVar += language;
+ compileCmdVar += "_COMPILE_OBJECT";
+ std::string compileCmd =
+ this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
+ std::vector<std::string> compileCmds;
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+
+ for (std::vector<std::string>::iterator i = compileCmds.begin();
+ i != compileCmds.end(); ++i)
+ this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars);
+
+ std::string cmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+
+ this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine,
+ sourceFileName);
+ }
+
+ cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ comment,
+ rule,
+ outputs,
+ explicitDeps,
+ emptyDeps,
+ orderOnlyDeps,
+ vars);
+
+ if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
+ std::vector<std::string> outputList;
+ cmSystemTools::ExpandListArgument(objectOutputs, outputList);
+ std::transform(outputList.begin(), outputList.end(), outputList.begin(),
+ MapToNinjaPath());
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Additional output files.",
+ outputList,
+ outputs);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmNinjaTargetGenerator
+::AddModuleDefinitionFlag(std::string& flags)
+{
+ if(this->ModuleDefinitionFile.empty())
+ {
+ return;
+ }
+
+ // TODO: Create a per-language flag variable.
+ const char* defFileFlag =
+ this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ if(!defFileFlag)
+ {
+ return;
+ }
+
+ // Append the flag and value. Use ConvertToLinkReference to help
+ // vs6's "cl -link" pass it to the linker.
+ std::string flag = defFileFlag;
+ flag += (this->LocalGenerator->ConvertToLinkReference(
+ this->ModuleDefinitionFile.c_str()));
+ this->LocalGenerator->AppendFlags(flags, flag.c_str());
+}
+
+void
+cmNinjaTargetGenerator
+::EnsureDirectoryExists(const std::string& dir)
+{
+ cmSystemTools::MakeDirectory(dir.c_str());
+}
+
+void
+cmNinjaTargetGenerator
+::EnsureParentDirectoryExists(const std::string& path)
+{
+ EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path.c_str()));
+}
+
+
+//----------------------------------------------------------------------------
+void
+cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
+ cmSourceFile& source, const char* pkgloc)
+{
+ // Skip OS X content when not building a Framework or Bundle.
+ if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty())
+ {
+ return;
+ }
+
+ std::string macdir =
+ this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
+
+ // Get the input file location.
+ std::string input = source.GetFullPath();
+ input =
+ this->Generator->GetLocalGenerator()->ConvertToNinjaPath(input.c_str());
+
+ // Get the output file location.
+ std::string output = macdir;
+ output += "/";
+ output += cmSystemTools::GetFilenameName(input);
+ output =
+ this->Generator->GetLocalGenerator()->ConvertToNinjaPath(output.c_str());
+
+ // Write a build statement to copy the content into the bundle.
+ this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input,
+ output);
+
+ // Add as a dependency of all target so that it gets called.
+ this->Generator->GetGlobalGenerator()->AddDependencyToAll(output);
+}