1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
4 Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
6 Distributed under the OSI-approved BSD License (the "License");
7 see accompanying file Copyright.txt for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even the
10 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 See the License for more information.
12 ============================================================================*/
13 #include "cmNinjaTargetGenerator.h"
14 #include "cmGlobalNinjaGenerator.h"
15 #include "cmLocalNinjaGenerator.h"
16 #include "cmGeneratedFileStream.h"
17 #include "cmGeneratorTarget.h"
18 #include "cmNinjaNormalTargetGenerator.h"
19 #include "cmNinjaUtilityTargetGenerator.h"
20 #include "cmSystemTools.h"
21 #include "cmMakefile.h"
22 #include "cmComputeLinkInformation.h"
23 #include "cmSourceFile.h"
24 #include "cmCustomCommandGenerator.h"
28 cmNinjaTargetGenerator *
29 cmNinjaTargetGenerator::New(cmTarget* target)
31 switch (target->GetType())
33 case cmTarget::EXECUTABLE:
34 case cmTarget::SHARED_LIBRARY:
35 case cmTarget::STATIC_LIBRARY:
36 case cmTarget::MODULE_LIBRARY:
37 case cmTarget::OBJECT_LIBRARY:
38 return new cmNinjaNormalTargetGenerator(target);
40 case cmTarget::UTILITY:
41 return new cmNinjaUtilityTargetGenerator(target);;
43 case cmTarget::GLOBAL_TARGET: {
44 // We only want to process global targets that live in the home
45 // (i.e. top-level) directory. CMake creates copies of these targets
46 // in every directory, which we don't need.
47 cmMakefile *mf = target->GetMakefile();
48 if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0)
49 return new cmNinjaUtilityTargetGenerator(target);
58 cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
60 MacOSXContentGenerator(0),
61 OSXBundleGenerator(0),
64 Makefile(target->GetMakefile()),
66 static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
69 this->GeneratorTarget =
70 this->GetGlobalGenerator()->GetGeneratorTarget(target);
71 MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
74 cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
76 delete this->MacOSXContentGenerator;
79 cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
81 return *this->GetGlobalGenerator()->GetBuildFileStream();
84 cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const
86 return *this->GetGlobalGenerator()->GetRulesFileStream();
89 cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
91 return this->LocalGenerator->GetGlobalNinjaGenerator();
94 const char* cmNinjaTargetGenerator::GetConfigName() const
96 return this->LocalGenerator->GetConfigName();
99 // TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
100 const char* cmNinjaTargetGenerator::GetFeature(const char* feature)
102 return this->Target->GetFeature(feature, this->GetConfigName());
105 // TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
106 bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature)
108 return cmSystemTools::IsOn(this->GetFeature(feature));
111 // TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
112 void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags,
115 // Add language-specific flags.
116 this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName());
118 if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
120 this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
124 // TODO: Most of the code is picked up from
125 // void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink),
126 // void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
129 cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
130 const std::string& language)
134 this->AddFeatureFlags(flags, language.c_str());
136 this->GetLocalGenerator()->AddArchitectureFlags(flags,
137 this->GeneratorTarget,
139 this->GetConfigName());
141 // TODO: Fortran support.
142 // // Fortran-specific flags computed for this target.
143 // if(*l == "Fortran")
145 // this->AddFortranFlags(flags);
148 // Add shared-library flags if needed.
149 this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
151 this->GetConfigName());
153 // Add include directory flags.
155 std::vector<std::string> includes;
156 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
157 this->LocalGenerator->GetIncludeDirectories(includes,
158 this->GeneratorTarget,
159 language.c_str(), config);
160 std::string includeFlags =
161 this->LocalGenerator->GetIncludeFlags(includes, language.c_str(),
162 language == "RC" ? true : false); // full include paths for RC
163 // needed by cmcldeps
164 if(cmGlobalNinjaGenerator::IsMinGW())
165 cmSystemTools::ReplaceString(includeFlags, "\\", "/");
167 this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
170 // Append old-style preprocessor definition flags.
171 this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
173 // Add target-specific flags.
174 if(this->Target->GetProperty("COMPILE_FLAGS"))
176 std::string langIncludeExpr = "CMAKE_";
177 langIncludeExpr += language;
178 langIncludeExpr += "_FLAG_REGEX";
179 const char* regex = this->Makefile->
180 GetDefinition(langIncludeExpr.c_str());
183 cmsys::RegularExpression r(regex);
184 std::vector<std::string> args;
185 cmSystemTools::ParseWindowsCommandLine(
186 this->Target->GetProperty("COMPILE_FLAGS"),
188 for(std::vector<std::string>::iterator i = args.begin();
189 i != args.end(); ++i)
191 if(r.find(i->c_str()))
193 this->LocalGenerator->AppendFlags
200 this->LocalGenerator->AppendFlags
201 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
205 // Add source file specific flags.
206 this->LocalGenerator->AppendFlags(flags,
207 source->GetProperty("COMPILE_FLAGS"));
209 // TODO: Handle Apple frameworks.
214 // TODO: Refactor with
215 // void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
217 cmNinjaTargetGenerator::
218 ComputeDefines(cmSourceFile *source, const std::string& language)
220 std::set<std::string> defines;
222 // Add the export symbol definition for shared library objects.
223 if(const char* exportMacro = this->Target->GetExportMacro())
225 this->LocalGenerator->AppendDefines(defines, exportMacro);
228 // Add preprocessor definitions for this target and configuration.
229 this->LocalGenerator->AppendDefines
231 this->Target->GetCompileDefinitions(this->GetConfigName()));
232 this->LocalGenerator->AppendDefines
234 source->GetProperty("COMPILE_DEFINITIONS"));
236 std::string defPropName = "COMPILE_DEFINITIONS_";
237 defPropName += cmSystemTools::UpperCase(this->GetConfigName());
238 this->LocalGenerator->AppendDefines
240 source->GetProperty(defPropName.c_str()));
243 std::string definesString;
244 this->LocalGenerator->JoinDefines(defines, definesString,
247 return definesString;
250 cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
252 // Static libraries never depend on other targets for linking.
253 if (this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
254 this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
255 return cmNinjaDeps();
257 cmComputeLinkInformation* cli =
258 this->Target->GetLinkInformation(this->GetConfigName());
260 return cmNinjaDeps();
262 const std::vector<std::string> &deps = cli->GetDepends();
263 cmNinjaDeps result(deps.size());
264 std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
266 // Add a dependency on the link definitions file, if any.
267 if(!this->ModuleDefinitionFile.empty())
269 result.push_back(this->ModuleDefinitionFile);
276 cmNinjaTargetGenerator
277 ::GetSourceFilePath(cmSourceFile* source) const
279 return ConvertToNinjaPath(source->GetFullPath().c_str());
283 cmNinjaTargetGenerator
284 ::GetObjectFilePath(cmSourceFile* source) const
286 std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
289 std::string const& objectName = this->GeneratorTarget->Objects[source];
290 path += this->LocalGenerator->GetTargetDirectory(*this->Target);
296 std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
298 std::string dir = this->Target->GetDirectory(this->GetConfigName());
299 return ConvertToNinjaPath(dir.c_str());
303 cmNinjaTargetGenerator
304 ::GetTargetFilePath(const std::string& name) const
306 std::string path = this->GetTargetOutputDir();
307 if (path.empty() || path == ".")
314 std::string cmNinjaTargetGenerator::GetTargetName() const
316 return this->Target->GetName();
320 bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
322 cmMakefile* mf = this->GetMakefile();
323 if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
324 mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
327 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
328 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
329 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
330 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
332 pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
334 pdbPath += this->Target->GetPDBName(this->GetConfigName());
337 vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
338 ConvertToNinjaPath(pdbPath.c_str()).c_str(),
339 cmLocalGenerator::SHELL);
340 EnsureParentDirectoryExists(pdbPath);
347 cmNinjaTargetGenerator
348 ::WriteLanguageRules(const std::string& language)
350 #ifdef NINJA_GEN_VERBOSE_FILES
351 this->GetRulesFileStream()
352 << "# Rules for language " << language << "\n\n";
354 this->WriteCompileRule(language);
358 cmNinjaTargetGenerator
359 ::WriteCompileRule(const std::string& language)
361 cmLocalGenerator::RuleVariables vars;
362 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
363 vars.CMTarget = this->GetTarget();
364 std::string lang = language;
365 vars.Language = lang.c_str();
367 vars.Object = "$out";
368 std::string flags = "$FLAGS";
369 vars.Defines = "$DEFINES";
370 vars.TargetPDB = "$TARGET_PDB";
371 vars.ObjectDir = "$OBJECT_DIR";
373 cmMakefile* mf = this->GetMakefile();
375 bool useClDeps = false;
376 std::string clBinary;
377 std::string clDepsBinary;
378 std::string clShowPrefix;
379 if (lang == "C" || lang == "CXX" || lang == "RC")
381 clDepsBinary = mf->GetSafeDefinition("CMAKE_CMCLDEPS_EXECUTABLE");
382 if (!clDepsBinary.empty() && !mf->GetIsSourceFileTryCompile())
384 clShowPrefix = mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDE_PREFIX");
385 clBinary = mf->GetDefinition("CMAKE_C_COMPILER") ?
386 mf->GetSafeDefinition("CMAKE_C_COMPILER") :
387 mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
388 if (!clBinary.empty() && !clShowPrefix.empty())
391 const std::string quote = " \"";
392 clBinary = quote + clBinary + "\" ";
393 clDepsBinary = quote + clDepsBinary + "\" ";
394 clShowPrefix = quote + clShowPrefix + "\" ";
395 vars.DependencyFile = "$DEP_FILE";
402 std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
403 const char *depfileFlags = mf->GetDefinition(depfileFlagsName.c_str());
404 if (depfileFlags || useClDeps) {
405 std::string depFlagsStr = depfileFlags ? depfileFlags : "";
406 depfile = "$DEP_FILE";
407 cmSystemTools::ReplaceString(depFlagsStr, "<DEPFILE>", "\"$DEP_FILE\"");
408 cmSystemTools::ReplaceString(depFlagsStr, "<OBJECT>", "$out");
409 cmSystemTools::ReplaceString(depFlagsStr, "<CMAKE_C_COMPILER>",
410 mf->GetDefinition("CMAKE_C_COMPILER"));
411 flags += " " + depFlagsStr;
413 vars.Flags = flags.c_str();
416 // Rule for compiling object file.
417 std::string compileCmdVar = "CMAKE_";
418 compileCmdVar += language;
419 compileCmdVar += "_COMPILE_OBJECT";
420 std::string compileCmd = mf->GetRequiredDefinition(compileCmdVar.c_str());
421 std::vector<std::string> compileCmds;
422 cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
426 std::string cmdPrefix = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " +
427 clShowPrefix + clBinary;
428 compileCmds.front().insert(0, cmdPrefix);
431 for (std::vector<std::string>::iterator i = compileCmds.begin();
432 i != compileCmds.end(); ++i)
433 this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
435 std::string cmdLine =
436 this->GetLocalGenerator()->BuildCommandLine(compileCmds);
439 // Write the rule for compiling file of the given language.
440 cmOStringStream comment;
441 comment << "Rule for compiling " << language << " files.";
442 cmOStringStream description;
443 description << "Building " << language << " object $out";
444 this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
452 cmNinjaTargetGenerator
453 ::WriteObjectBuildStatements()
456 cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
457 this->GetBuildFileStream()
458 << "# Object build statements for "
459 << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
461 << this->GetTargetName()
464 for(std::vector<cmSourceFile*>::const_iterator
465 si = this->GeneratorTarget->CustomCommands.begin();
466 si != this->GeneratorTarget->CustomCommands.end(); ++si)
468 cmCustomCommand const* cc = (*si)->GetCustomCommand();
469 this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
471 this->OSXBundleGenerator->GenerateMacOSXContentStatements(
472 this->GeneratorTarget->HeaderSources,
473 this->MacOSXContentGenerator);
474 this->OSXBundleGenerator->GenerateMacOSXContentStatements(
475 this->GeneratorTarget->ExtraSources,
476 this->MacOSXContentGenerator);
477 for(std::vector<cmSourceFile*>::const_iterator
478 si = this->GeneratorTarget->ExternalObjects.begin();
479 si != this->GeneratorTarget->ExternalObjects.end(); ++si)
481 this->Objects.push_back(this->GetSourceFilePath(*si));
483 for(std::vector<cmSourceFile*>::const_iterator
484 si = this->GeneratorTarget->ObjectSources.begin();
485 si != this->GeneratorTarget->ObjectSources.end(); ++si)
487 this->WriteObjectBuildStatement(*si);
489 if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
491 this->ModuleDefinitionFile = this->ConvertToNinjaPath(
492 this->GeneratorTarget->ModuleDefinitionFile.c_str());
496 // Add object library contents as external objects.
497 std::vector<std::string> objs;
498 this->GeneratorTarget->UseObjectLibraries(objs);
499 for(std::vector<std::string>::iterator oi = objs.begin();
500 oi != objs.end(); ++oi)
502 this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
506 this->GetBuildFileStream() << "\n";
510 cmNinjaTargetGenerator
511 ::WriteObjectBuildStatement(cmSourceFile* source)
514 const std::string language = source->GetLanguage();
515 std::string rule = this->LanguageCompilerRule(language);
518 std::string objectFileName = this->GetObjectFilePath(source);
519 outputs.push_back(objectFileName);
520 // Add this object to the list of object files.
521 this->Objects.push_back(objectFileName);
523 cmNinjaDeps explicitDeps;
524 std::string sourceFileName;
525 if (language == "RC")
526 sourceFileName = source->GetFullPath();
528 sourceFileName = this->GetSourceFilePath(source);
529 explicitDeps.push_back(sourceFileName);
531 // Ensure that the target dependencies are built before any source file in
532 // the target, using order-only dependencies.
533 cmNinjaDeps orderOnlyDeps;
534 this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
536 cmNinjaDeps implicitDeps;
537 if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
538 std::vector<std::string> depList;
539 cmSystemTools::ExpandListArgument(objectDeps, depList);
540 std::transform(depList.begin(), depList.end(),
541 std::back_inserter(implicitDeps), MapToNinjaPath());
544 // Add order-only dependencies on custom command outputs.
545 for(std::vector<cmSourceFile*>::const_iterator
546 si = this->GeneratorTarget->CustomCommands.begin();
547 si != this->GeneratorTarget->CustomCommands.end(); ++si)
549 cmCustomCommand const* cc = (*si)->GetCustomCommand();
550 const std::vector<std::string>& ccoutputs = cc->GetOutputs();
551 std::transform(ccoutputs.begin(), ccoutputs.end(),
552 std::back_inserter(orderOnlyDeps), MapToNinjaPath());
555 // If the source file is GENERATED and does not have a custom command
556 // (either attached to this source file or another one), assume that one of
557 // the target dependencies, OBJECT_DEPENDS or header file custom commands
558 // will rebuild the file.
559 if (source->GetPropertyAsBool("GENERATED") && !source->GetCustomCommand() &&
560 !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
561 this->GetGlobalGenerator()->AddAssumedSourceDependencies(sourceFileName,
566 vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
567 vars["DEFINES"] = this->ComputeDefines(source, language);
568 vars["DEP_FILE"] = objectFileName + ".d";;
569 EnsureParentDirectoryExists(objectFileName);
571 std::string objectDir = cmSystemTools::GetFilenamePath(objectFileName);
572 objectDir = this->GetLocalGenerator()->Convert(objectDir.c_str(),
573 cmLocalGenerator::START_OUTPUT,
574 cmLocalGenerator::SHELL);
575 vars["OBJECT_DIR"] = objectDir;
578 this->SetMsvcTargetPdbVariable(vars);
580 if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS"))
582 cmLocalGenerator::RuleVariables compileObjectVars;
583 std::string lang = language;
584 compileObjectVars.Language = lang.c_str();
586 std::string escapedSourceFileName = sourceFileName;
588 if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str()))
590 escapedSourceFileName = cmSystemTools::CollapseFullPath(
591 escapedSourceFileName.c_str(),
592 this->GetGlobalGenerator()->GetCMakeInstance()->
593 GetHomeOutputDirectory());
596 escapedSourceFileName =
597 this->LocalGenerator->ConvertToOutputFormat(
598 escapedSourceFileName.c_str(), cmLocalGenerator::SHELL);
600 compileObjectVars.Source = escapedSourceFileName.c_str();
601 compileObjectVars.Object = objectFileName.c_str();
602 compileObjectVars.ObjectDir = objectDir.c_str();
603 compileObjectVars.Flags = vars["FLAGS"].c_str();
604 compileObjectVars.Defines = vars["DEFINES"].c_str();
606 // Rule for compiling object file.
607 std::string compileCmdVar = "CMAKE_";
608 compileCmdVar += language;
609 compileCmdVar += "_COMPILE_OBJECT";
610 std::string compileCmd =
611 this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
612 std::vector<std::string> compileCmds;
613 cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
615 for (std::vector<std::string>::iterator i = compileCmds.begin();
616 i != compileCmds.end(); ++i)
617 this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars);
619 std::string cmdLine =
620 this->GetLocalGenerator()->BuildCommandLine(compileCmds);
622 this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine,
626 cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
635 if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
636 std::vector<std::string> outputList;
637 cmSystemTools::ExpandListArgument(objectOutputs, outputList);
638 std::transform(outputList.begin(), outputList.end(), outputList.begin(),
640 cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
641 "Additional output files.",
647 //----------------------------------------------------------------------------
649 cmNinjaTargetGenerator
650 ::AddModuleDefinitionFlag(std::string& flags)
652 if(this->ModuleDefinitionFile.empty())
657 // TODO: Create a per-language flag variable.
658 const char* defFileFlag =
659 this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
665 // Append the flag and value. Use ConvertToLinkReference to help
666 // vs6's "cl -link" pass it to the linker.
667 std::string flag = defFileFlag;
668 flag += (this->LocalGenerator->ConvertToLinkReference(
669 this->ModuleDefinitionFile.c_str()));
670 this->LocalGenerator->AppendFlags(flags, flag.c_str());
674 cmNinjaTargetGenerator
675 ::EnsureDirectoryExists(const std::string& path) const
677 if (cmSystemTools::FileIsFullPath(path.c_str()))
679 cmSystemTools::MakeDirectory(path.c_str());
683 const std::string fullPath = std::string(this->GetGlobalGenerator()->
684 GetCMakeInstance()->GetHomeOutputDirectory())
686 cmSystemTools::MakeDirectory(fullPath.c_str());
691 cmNinjaTargetGenerator
692 ::EnsureParentDirectoryExists(const std::string& path) const
694 EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path.c_str()));
698 //----------------------------------------------------------------------------
700 cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
701 cmSourceFile& source, const char* pkgloc)
703 // Skip OS X content when not building a Framework or Bundle.
704 if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty())
710 this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
712 // Get the input file location.
713 std::string input = source.GetFullPath();
715 this->Generator->GetLocalGenerator()->ConvertToNinjaPath(input.c_str());
717 // Get the output file location.
718 std::string output = macdir;
720 output += cmSystemTools::GetFilenameName(input);
722 this->Generator->GetLocalGenerator()->ConvertToNinjaPath(output.c_str());
724 // Write a build statement to copy the content into the bundle.
725 this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input,
728 // Add as a dependency of all target so that it gets called.
729 this->Generator->GetGlobalGenerator()->AddDependencyToAll(output);