1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmMakefileTargetGenerator.h"
14 #include "cmGeneratorTarget.h"
15 #include "cmGeneratedFileStream.h"
16 #include "cmGlobalGenerator.h"
17 #include "cmGlobalUnixMakefileGenerator3.h"
18 #include "cmLocalUnixMakefileGenerator3.h"
19 #include "cmMakefile.h"
20 #include "cmSourceFile.h"
23 #include "cmComputeLinkInformation.h"
25 #include "cmMakefileExecutableTargetGenerator.h"
26 #include "cmMakefileLibraryTargetGenerator.h"
27 #include "cmMakefileUtilityTargetGenerator.h"
30 cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target)
31 : OSXBundleGenerator(0)
32 , MacOSXContentGenerator(0)
34 this->BuildFileStream = 0;
35 this->InfoFileStream = 0;
36 this->FlagFileStream = 0;
37 this->CustomCommandDriver = OnBuild;
38 this->FortranModuleDirectoryComputed = false;
39 this->Target = target;
40 this->Makefile = this->Target->GetMakefile();
41 this->LocalGenerator =
42 static_cast<cmLocalUnixMakefileGenerator3*>(
43 this->Makefile->GetLocalGenerator());
44 this->ConfigName = this->LocalGenerator->ConfigurationName.c_str();
45 this->GlobalGenerator =
46 static_cast<cmGlobalUnixMakefileGenerator3*>(
47 this->LocalGenerator->GetGlobalGenerator());
48 this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target);
49 cmake* cm = this->GlobalGenerator->GetCMakeInstance();
50 this->NoRuleMessages = false;
51 if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES"))
53 this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus);
55 MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
58 cmMakefileTargetGenerator::~cmMakefileTargetGenerator()
60 delete MacOSXContentGenerator;
63 cmMakefileTargetGenerator *
64 cmMakefileTargetGenerator::New(cmTarget *tgt)
66 cmMakefileTargetGenerator *result = 0;
68 switch (tgt->GetType())
70 case cmTarget::EXECUTABLE:
71 result = new cmMakefileExecutableTargetGenerator(tgt);
73 case cmTarget::STATIC_LIBRARY:
74 case cmTarget::SHARED_LIBRARY:
75 case cmTarget::MODULE_LIBRARY:
76 case cmTarget::OBJECT_LIBRARY:
77 result = new cmMakefileLibraryTargetGenerator(tgt);
79 case cmTarget::UTILITY:
80 result = new cmMakefileUtilityTargetGenerator(tgt);
84 // break; /* unreachable */
89 //----------------------------------------------------------------------------
90 void cmMakefileTargetGenerator::CreateRuleFile()
92 // Create a directory for this target.
93 this->TargetBuildDirectory =
94 this->LocalGenerator->GetTargetDirectory(*this->Target);
95 this->TargetBuildDirectoryFull =
96 this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
97 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
99 // Construct the rule file name.
100 this->BuildFileName = this->TargetBuildDirectory;
101 this->BuildFileName += "/build.make";
102 this->BuildFileNameFull = this->TargetBuildDirectoryFull;
103 this->BuildFileNameFull += "/build.make";
105 // Construct the rule file name.
106 this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
107 this->ProgressFileNameFull += "/progress.make";
109 // reset the progress count
110 this->NumberOfProgressActions = 0;
112 // Open the rule file. This should be copy-if-different because the
113 // rules may depend on this file itself.
114 this->BuildFileStream =
115 new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
116 this->BuildFileStream->SetCopyIfDifferent(true);
117 if(!this->BuildFileStream)
121 this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
122 this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
125 //----------------------------------------------------------------------------
126 void cmMakefileTargetGenerator::WriteTargetBuildRules()
128 // write the custom commands for this target
129 // Look for files registered for cleaning in this directory.
130 if(const char* additional_clean_files =
131 this->Makefile->GetProperty
132 ("ADDITIONAL_MAKE_CLEAN_FILES"))
134 cmSystemTools::ExpandListArgument(additional_clean_files,
138 // add custom commands to the clean rules?
139 const char* clean_no_custom =
140 this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
141 bool clean = cmSystemTools::IsOff(clean_no_custom);
143 // First generate the object rule files. Save a list of all object
144 // files for this target.
145 for(std::vector<cmSourceFile*>::const_iterator
146 si = this->GeneratorTarget->CustomCommands.begin();
147 si != this->GeneratorTarget->CustomCommands.end(); ++si)
149 cmCustomCommand const* cc = (*si)->GetCustomCommand();
150 this->GenerateCustomRuleFile(*cc);
153 const std::vector<std::string>& outputs = cc->GetOutputs();
154 for(std::vector<std::string>::const_iterator o = outputs.begin();
155 o != outputs.end(); ++o)
157 this->CleanFiles.push_back
158 (this->Convert(o->c_str(),
159 cmLocalGenerator::START_OUTPUT,
160 cmLocalGenerator::UNCHANGED));
164 this->OSXBundleGenerator->GenerateMacOSXContentStatements(
165 this->GeneratorTarget->HeaderSources,
166 this->MacOSXContentGenerator);
167 this->OSXBundleGenerator->GenerateMacOSXContentStatements(
168 this->GeneratorTarget->ExtraSources,
169 this->MacOSXContentGenerator);
170 for(std::vector<cmSourceFile*>::const_iterator
171 si = this->GeneratorTarget->ExternalObjects.begin();
172 si != this->GeneratorTarget->ExternalObjects.end(); ++si)
174 this->ExternalObjects.push_back((*si)->GetFullPath());
176 for(std::vector<cmSourceFile*>::const_iterator
177 si = this->GeneratorTarget->ObjectSources.begin();
178 si != this->GeneratorTarget->ObjectSources.end(); ++si)
180 // Generate this object file's rule file.
181 this->WriteObjectRuleFiles(**si);
184 // Add object library contents as external objects.
185 this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
188 //----------------------------------------------------------------------------
189 void cmMakefileTargetGenerator::WriteCommonCodeRules()
191 const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")?
192 "$(CMAKE_BINARY_DIR)/" : "");
194 // Include the dependencies for the target.
195 std::string dependFileNameFull = this->TargetBuildDirectoryFull;
196 dependFileNameFull += "/depend.make";
197 *this->BuildFileStream
198 << "# Include any dependencies generated for this target.\n"
199 << this->LocalGenerator->IncludeDirective << " " << root
200 << this->Convert(dependFileNameFull.c_str(),
201 cmLocalGenerator::HOME_OUTPUT,
202 cmLocalGenerator::MAKEFILE)
205 if(!this->NoRuleMessages)
207 // Include the progress variables for the target.
208 *this->BuildFileStream
209 << "# Include the progress variables for this target.\n"
210 << this->LocalGenerator->IncludeDirective << " " << root
211 << this->Convert(this->ProgressFileNameFull.c_str(),
212 cmLocalGenerator::HOME_OUTPUT,
213 cmLocalGenerator::MAKEFILE)
217 // make sure the depend file exists
218 if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
220 // Write an empty dependency file.
221 cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
223 << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
224 << "# This may be replaced when dependencies are built." << std::endl;
227 // Open the flags file. This should be copy-if-different because the
228 // rules may depend on this file itself.
229 this->FlagFileNameFull = this->TargetBuildDirectoryFull;
230 this->FlagFileNameFull += "/flags.make";
231 this->FlagFileStream =
232 new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
233 this->FlagFileStream->SetCopyIfDifferent(true);
234 if(!this->FlagFileStream)
238 this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
240 // Include the flags for the target.
241 *this->BuildFileStream
242 << "# Include the compile flags for this target's objects.\n"
243 << this->LocalGenerator->IncludeDirective << " " << root
244 << this->Convert(this->FlagFileNameFull.c_str(),
245 cmLocalGenerator::HOME_OUTPUT,
246 cmLocalGenerator::MAKEFILE)
250 //----------------------------------------------------------------------------
251 std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
253 ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
254 if (i == this->FlagsByLanguage.end())
257 const char *lang = l.c_str();
259 // Add language feature flags.
260 this->AddFeatureFlags(flags, lang);
262 this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
263 lang, this->ConfigName);
265 // Fortran-specific flags computed for this target.
268 this->AddFortranFlags(flags);
271 this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
272 lang, this->ConfigName);
274 // Add include directory flags.
275 this->AddIncludeFlags(flags, lang);
277 // Append old-style preprocessor definition flags.
278 this->LocalGenerator->
279 AppendFlags(flags, this->Makefile->GetDefineFlags());
281 // Add include directory flags.
282 this->LocalGenerator->
283 AppendFlags(flags,this->GetFrameworkFlags().c_str());
285 ByLanguageMap::value_type entry(l, flags);
286 i = this->FlagsByLanguage.insert(entry).first;
291 std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
293 ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
294 if (i == this->DefinesByLanguage.end())
296 std::set<std::string> defines;
297 const char *lang = l.c_str();
298 // Add the export symbol definition for shared library objects.
299 if(const char* exportMacro = this->Target->GetExportMacro())
301 this->LocalGenerator->AppendDefines(defines, exportMacro);
304 // Add preprocessor definitions for this target and configuration.
305 this->LocalGenerator->AppendDefines
306 (defines, this->Target->GetCompileDefinitions(
307 this->LocalGenerator->ConfigurationName.c_str()));
309 std::string definesString;
310 this->LocalGenerator->JoinDefines(defines, definesString, lang);
312 ByLanguageMap::value_type entry(l, definesString);
313 i = this->DefinesByLanguage.insert(entry).first;
318 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
320 // write language flags for target
321 std::set<cmStdString> languages;
322 this->Target->GetLanguages(languages);
323 // put the compiler in the rules.make file so that if it changes
325 for(std::set<cmStdString>::const_iterator l = languages.begin();
326 l != languages.end(); ++l)
328 cmStdString compiler = "CMAKE_";
330 compiler += "_COMPILER";
331 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
332 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
335 for(std::set<cmStdString>::const_iterator l = languages.begin();
336 l != languages.end(); ++l)
338 *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
339 *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
343 // Add target-specific flags.
344 if(this->Target->GetProperty("COMPILE_FLAGS"))
347 this->LocalGenerator->AppendFlags
348 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
349 *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
354 //----------------------------------------------------------------------------
356 cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
357 (cmSourceFile& source, const char* pkgloc)
359 // Skip OS X content when not building a Framework or Bundle.
360 if(this->Generator->MacContentDirectory.empty())
366 this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
368 // Get the input file location.
369 std::string input = source.GetFullPath();
371 // Get the output file location.
372 std::string output = macdir;
374 output += cmSystemTools::GetFilenameName(input);
375 this->Generator->CleanFiles.push_back(
376 this->Generator->Convert(output.c_str(),
377 cmLocalGenerator::START_OUTPUT));
378 output = this->Generator->Convert(output.c_str(),
379 cmLocalGenerator::HOME_OUTPUT);
381 // Create a rule to copy the content into the bundle.
382 std::vector<std::string> depends;
383 std::vector<std::string> commands;
384 depends.push_back(input);
385 std::string copyEcho = "Copying OS X content ";
387 this->Generator->LocalGenerator->AppendEcho(
388 commands, copyEcho.c_str(),
389 cmLocalUnixMakefileGenerator3::EchoBuild);
390 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
391 copyCommand += this->Generator->Convert(input.c_str(),
392 cmLocalGenerator::NONE,
393 cmLocalGenerator::SHELL);
395 copyCommand += this->Generator->Convert(output.c_str(),
396 cmLocalGenerator::NONE,
397 cmLocalGenerator::SHELL);
398 commands.push_back(copyCommand);
399 this->Generator->LocalGenerator->WriteMakeRule(
400 *this->Generator->BuildFileStream, 0,
402 depends, commands, false);
403 this->Generator->ExtraFiles.insert(output);
406 //----------------------------------------------------------------------------
407 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
409 // Identify the language of the source file.
410 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
413 // don't know anything about this file so skip it
417 // Get the full path name of the object file.
418 std::string const& objectName = this->GeneratorTarget->Objects[&source];
419 std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
423 // Avoid generating duplicate rules.
424 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
426 this->ObjectFiles.insert(obj);
431 err << "Warning: Source file \""
432 << source.GetFullPath()
433 << "\" is listed multiple times for target \""
434 << this->Target->GetName()
436 cmSystemTools::Message(err.str().c_str(), "Warning");
440 // Create the directory containing the object file. This may be a
441 // subdirectory under the target's directory.
442 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
443 cmSystemTools::MakeDirectory
444 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
446 // Save this in the target's list of object files.
447 this->Objects.push_back(obj);
448 this->CleanFiles.push_back(obj);
451 //std::string relativeObj
452 //= this->LocalGenerator->GetHomeRelativeOutputPath();
453 //relativeObj += obj;
455 // we compute some depends when writing the depend.make that we will also
456 // use in the build.make, same with depMakeFile
457 std::vector<std::string> depends;
458 std::string depMakeFile;
460 // generate the build rule file
461 this->WriteObjectBuildFile(obj, lang, source, depends);
463 // The object file should be checked for dependency integrity.
464 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
468 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
469 std::string srcFullPath =
470 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
471 this->LocalGenerator->
472 AddImplicitDepends(*this->Target, lang,
474 srcFullPath.c_str());
477 //----------------------------------------------------------------------------
479 cmMakefileTargetGenerator
480 ::AppendFortranFormatFlags(std::string& flags, cmSourceFile& source)
482 const char* srcfmt = source.GetProperty("Fortran_FORMAT");
483 cmLocalGenerator::FortranFormat format =
484 this->LocalGenerator->GetFortranFormat(srcfmt);
485 if(format == cmLocalGenerator::FortranFormatNone)
487 const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT");
488 format = this->LocalGenerator->GetFortranFormat(tgtfmt);
493 case cmLocalGenerator::FortranFormatFixed:
494 var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break;
495 case cmLocalGenerator::FortranFormatFree:
496 var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break;
501 this->LocalGenerator->AppendFlags(
502 flags, this->Makefile->GetDefinition(var));
506 //----------------------------------------------------------------------------
508 cmMakefileTargetGenerator
509 ::WriteObjectBuildFile(std::string &obj,
511 cmSourceFile& source,
512 std::vector<std::string>& depends)
514 this->LocalGenerator->AppendRuleDepend(depends,
515 this->FlagFileNameFull.c_str());
516 this->LocalGenerator->AppendRuleDepends(depends,
517 this->FlagFileDepends[lang]);
519 // generate the depend scanning rule
520 this->WriteObjectDependRules(source, depends);
522 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
524 // Write the build rule.
526 // Build the set of compiler flags.
529 // Add language-specific flags.
530 std::string langFlags = "$(";
532 langFlags += "_FLAGS)";
533 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
535 // Add target-specific flags.
536 if(this->Target->GetProperty("COMPILE_FLAGS"))
538 std::string langIncludeExpr = "CMAKE_";
539 langIncludeExpr += lang;
540 langIncludeExpr += "_FLAG_REGEX";
541 const char* regex = this->Makefile->
542 GetDefinition(langIncludeExpr.c_str());
545 cmsys::RegularExpression r(regex);
546 std::vector<std::string> args;
547 cmSystemTools::ParseWindowsCommandLine(
548 this->Target->GetProperty("COMPILE_FLAGS"),
550 for(std::vector<std::string>::iterator i = args.begin();
551 i != args.end(); ++i)
553 if(r.find(i->c_str()))
555 this->LocalGenerator->AppendFlags
562 this->LocalGenerator->AppendFlags
563 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
567 // Add Fortran format flags.
568 if(strcmp(lang, "Fortran") == 0)
570 this->AppendFortranFormatFlags(flags, source);
573 // Add flags from source file properties.
574 if (source.GetProperty("COMPILE_FLAGS"))
576 this->LocalGenerator->AppendFlags
577 (flags, source.GetProperty("COMPILE_FLAGS"));
578 *this->FlagFileStream << "# Custom flags: "
579 << relativeObj << "_FLAGS = "
580 << source.GetProperty("COMPILE_FLAGS")
585 // Add language-specific defines.
586 std::set<std::string> defines;
588 // Add source-sepcific preprocessor definitions.
589 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
591 this->LocalGenerator->AppendDefines(defines, compile_defs);
592 *this->FlagFileStream << "# Custom defines: "
593 << relativeObj << "_DEFINES = "
594 << compile_defs << "\n"
597 std::string configUpper =
598 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
599 std::string defPropName = "COMPILE_DEFINITIONS_";
600 defPropName += configUpper;
601 if(const char* config_compile_defs =
602 source.GetProperty(defPropName.c_str()))
604 this->LocalGenerator->AppendDefines(defines, config_compile_defs);
605 *this->FlagFileStream
606 << "# Custom defines: "
607 << relativeObj << "_DEFINES_" << configUpper
608 << " = " << config_compile_defs << "\n"
612 // Get the output paths for source and object files.
613 std::string sourceFile = source.GetFullPath();
614 if(this->LocalGenerator->UseRelativePaths)
616 sourceFile = this->Convert(sourceFile.c_str(),
617 cmLocalGenerator::START_OUTPUT);
619 sourceFile = this->Convert(sourceFile.c_str(),
620 cmLocalGenerator::NONE,
621 cmLocalGenerator::SHELL);
623 // Construct the build message.
624 std::vector<std::string> no_commands;
625 std::vector<std::string> commands;
627 // add in a progress call if needed
628 this->AppendProgress(commands);
630 if(!this->NoRuleMessages)
632 std::string buildEcho = "Building ";
634 buildEcho += " object ";
635 buildEcho += relativeObj;
636 this->LocalGenerator->AppendEcho
637 (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
640 std::string targetOutPathReal;
641 std::string targetOutPathPDB;
643 std::string targetFullPathReal;
644 std::string targetFullPathPDB;
645 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
646 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
647 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
648 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
651 this->Target->GetFullPath(this->ConfigName, false, true);
652 targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
653 targetFullPathPDB += "/";
654 targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
656 targetOutPathReal = this->Convert(targetFullPathReal.c_str(),
657 cmLocalGenerator::START_OUTPUT,
658 cmLocalGenerator::SHELL);
660 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
661 cmLocalGenerator::SHELL);
663 cmLocalGenerator::RuleVariables vars;
664 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
665 vars.CMTarget = this->Target;
666 vars.Language = lang;
667 vars.Target = targetOutPathReal.c_str();
668 vars.TargetPDB = targetOutPathPDB.c_str();
669 vars.Source = sourceFile.c_str();
670 std::string shellObj =
671 this->Convert(obj.c_str(),
672 cmLocalGenerator::NONE,
673 cmLocalGenerator::SHELL).c_str();
674 vars.Object = shellObj.c_str();
675 std::string objectDir = cmSystemTools::GetFilenamePath(obj);
676 objectDir = this->Convert(objectDir.c_str(),
677 cmLocalGenerator::START_OUTPUT,
678 cmLocalGenerator::SHELL);
679 vars.ObjectDir = objectDir.c_str();
680 vars.Flags = flags.c_str();
682 std::string definesString = "$(";
683 definesString += lang;
684 definesString += "_DEFINES)";
686 this->LocalGenerator->JoinDefines(defines, definesString, lang);
688 vars.Defines = definesString.c_str();
690 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
691 (strcmp(lang, "CXX") == 0));
693 // Construct the compile rules.
695 std::string compileRuleVar = "CMAKE_";
696 compileRuleVar += lang;
697 compileRuleVar += "_COMPILE_OBJECT";
698 std::string compileRule =
699 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
700 std::vector<std::string> compileCommands;
701 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
703 if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
704 lang_is_c_or_cxx && compileCommands.size() == 1)
706 std::string compileCommand = compileCommands[0];
707 this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
708 std::string workingDirectory =
709 this->LocalGenerator->Convert(
710 this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
711 compileCommand.replace(compileCommand.find(langFlags),
712 langFlags.size(), this->GetFlags(lang));
713 std::string langDefines = std::string("$(") + lang + "_DEFINES)";
714 compileCommand.replace(compileCommand.find(langDefines),
715 langDefines.size(), this->GetDefines(lang));
716 this->GlobalGenerator->AddCXXCompileCommand(
717 source.GetFullPath(), workingDirectory, compileCommand);
720 // Expand placeholders in the commands.
721 for(std::vector<std::string>::iterator i = compileCommands.begin();
722 i != compileCommands.end(); ++i)
724 this->LocalGenerator->ExpandRuleVariables(*i, vars);
727 // Change the command working directory to the local build tree.
728 this->LocalGenerator->CreateCDCommand
730 this->Makefile->GetStartOutputDirectory(),
731 cmLocalGenerator::HOME_OUTPUT);
732 commands.insert(commands.end(),
733 compileCommands.begin(), compileCommands.end());
737 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
739 depends, commands, false);
741 // Check for extra outputs created by the compilation.
742 if(const char* extra_outputs_str =
743 source.GetProperty("OBJECT_OUTPUTS"))
745 std::vector<std::string> extra_outputs;
746 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
747 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
748 eoi != extra_outputs.end(); ++eoi)
750 // Register this as an extra output for the object file rule.
751 // This will cause the object file to be rebuilt if the extra
752 // output is missing.
753 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
755 // Register this as an extra file to clean.
756 this->CleanFiles.push_back(eoi->c_str());
760 bool do_preprocess_rules = lang_is_c_or_cxx &&
761 this->LocalGenerator->GetCreatePreprocessedSourceRules();
762 bool do_assembly_rules = lang_is_c_or_cxx &&
763 this->LocalGenerator->GetCreateAssemblySourceRules();
764 if(do_preprocess_rules || do_assembly_rules)
766 std::vector<std::string> force_depends;
767 force_depends.push_back("cmake_force");
768 std::string::size_type dot_pos = relativeObj.rfind(".");
769 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
770 dot_pos = obj.rfind(".");
771 std::string objBase = obj.substr(0, dot_pos);
773 if(do_preprocess_rules)
776 std::string relativeObjI = relativeObjBase + ".i";
777 std::string objI = objBase + ".i";
779 std::string preprocessEcho = "Preprocessing ";
780 preprocessEcho += lang;
781 preprocessEcho += " source to ";
782 preprocessEcho += objI;
783 this->LocalGenerator->AppendEcho(
784 commands, preprocessEcho.c_str(),
785 cmLocalUnixMakefileGenerator3::EchoBuild
788 std::string preprocessRuleVar = "CMAKE_";
789 preprocessRuleVar += lang;
790 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
791 if(const char* preprocessRule =
792 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
794 std::vector<std::string> preprocessCommands;
795 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
797 std::string shellObjI =
798 this->Convert(objI.c_str(),
799 cmLocalGenerator::NONE,
800 cmLocalGenerator::SHELL).c_str();
801 vars.PreprocessedSource = shellObjI.c_str();
803 // Expand placeholders in the commands.
804 for(std::vector<std::string>::iterator i = preprocessCommands.begin();
805 i != preprocessCommands.end(); ++i)
807 this->LocalGenerator->ExpandRuleVariables(*i, vars);
810 this->LocalGenerator->CreateCDCommand
812 this->Makefile->GetStartOutputDirectory(),
813 cmLocalGenerator::HOME_OUTPUT);
814 commands.insert(commands.end(),
815 preprocessCommands.begin(),
816 preprocessCommands.end());
820 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
821 cmd += preprocessRuleVar;
822 commands.push_back(cmd);
825 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
826 relativeObjI.c_str(),
827 force_depends, commands, false);
830 if(do_assembly_rules)
833 std::string relativeObjS = relativeObjBase + ".s";
834 std::string objS = objBase + ".s";
836 std::string assemblyEcho = "Compiling ";
837 assemblyEcho += lang;
838 assemblyEcho += " source to assembly ";
839 assemblyEcho += objS;
840 this->LocalGenerator->AppendEcho(
841 commands, assemblyEcho.c_str(),
842 cmLocalUnixMakefileGenerator3::EchoBuild
845 std::string assemblyRuleVar = "CMAKE_";
846 assemblyRuleVar += lang;
847 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
848 if(const char* assemblyRule =
849 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
851 std::vector<std::string> assemblyCommands;
852 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
854 std::string shellObjS =
855 this->Convert(objS.c_str(),
856 cmLocalGenerator::NONE,
857 cmLocalGenerator::SHELL).c_str();
858 vars.AssemblySource = shellObjS.c_str();
860 // Expand placeholders in the commands.
861 for(std::vector<std::string>::iterator i = assemblyCommands.begin();
862 i != assemblyCommands.end(); ++i)
864 this->LocalGenerator->ExpandRuleVariables(*i, vars);
867 this->LocalGenerator->CreateCDCommand
869 this->Makefile->GetStartOutputDirectory(),
870 cmLocalGenerator::HOME_OUTPUT);
871 commands.insert(commands.end(),
872 assemblyCommands.begin(),
873 assemblyCommands.end());
877 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
878 cmd += assemblyRuleVar;
879 commands.push_back(cmd);
882 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
883 relativeObjS.c_str(),
884 force_depends, commands, false);
888 // If the language needs provides-requires mode, create the
889 // corresponding targets.
890 std::string objectRequires = relativeObj;
891 objectRequires += ".requires";
892 std::vector<std::string> p_depends;
893 // always provide an empty requires target
894 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
895 objectRequires.c_str(), p_depends,
898 // write a build rule to recursively build what this obj provides
899 std::string objectProvides = relativeObj;
900 objectProvides += ".provides";
901 std::string temp = relativeObj;
902 temp += ".provides.build";
903 std::vector<std::string> r_commands;
904 std::string tgtMakefileName =
905 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
906 tgtMakefileName += "/build.make";
908 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
912 p_depends.push_back(objectRequires);
913 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
914 objectProvides.c_str(), p_depends,
917 // write the provides.build rule dependency on the obj file
919 p_depends.push_back(relativeObj);
920 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
921 temp.c_str(), p_depends, no_commands,
925 //----------------------------------------------------------------------------
926 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
928 std::vector<std::string> depends;
929 std::vector<std::string> no_commands;
931 // Construct the name of the dependency generation target.
932 std::string depTarget =
933 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
934 depTarget += "/requires";
936 // This target drives dependency generation for all object files.
937 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
938 std::string objTarget;
939 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
940 obj != this->Objects.end(); ++obj)
944 objTarget += ".requires";
945 depends.push_back(objTarget);
949 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
951 depends, no_commands, true);
954 //----------------------------------------------------------------------------
955 void cmMakefileTargetGenerator::WriteTargetCleanRules()
957 std::vector<std::string> depends;
958 std::vector<std::string> commands;
960 // Construct the clean target name.
961 std::string cleanTarget =
962 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
963 cleanTarget += "/clean";
965 // Construct the clean command.
966 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
968 this->LocalGenerator->CreateCDCommand
970 this->Makefile->GetStartOutputDirectory(),
971 cmLocalGenerator::HOME_OUTPUT);
974 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
976 depends, commands, true);
980 //----------------------------------------------------------------------------
981 void cmMakefileTargetGenerator::WriteTargetDependRules()
983 // must write the targets depend info file
984 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
985 this->InfoFileNameFull = dir;
986 this->InfoFileNameFull += "/DependInfo.cmake";
987 this->InfoFileNameFull =
988 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
989 this->InfoFileStream =
990 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
991 this->InfoFileStream->SetCopyIfDifferent(true);
992 if(!*this->InfoFileStream)
996 this->LocalGenerator->
997 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
999 // Store multiple output pairs in the depend info file.
1000 if(!this->MultipleOutputPairs.empty())
1002 *this->InfoFileStream
1004 << "# Pairs of files generated by the same build rule.\n"
1005 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
1006 for(MultipleOutputPairsType::const_iterator pi =
1007 this->MultipleOutputPairs.begin();
1008 pi != this->MultipleOutputPairs.end(); ++pi)
1010 *this->InfoFileStream
1011 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
1012 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
1015 *this->InfoFileStream << " )\n\n";
1018 // Store list of targets linked directly or transitively.
1020 *this->InfoFileStream
1022 << "# Targets to which this target links.\n"
1023 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
1024 std::set<cmTarget const*> emitted;
1025 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1026 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1028 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
1029 for(cmComputeLinkInformation::ItemVector::const_iterator
1030 i = items.begin(); i != items.end(); ++i)
1032 cmTarget const* linkee = i->Target;
1033 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
1035 cmMakefile* mf = linkee->GetMakefile();
1036 cmLocalGenerator* lg = mf->GetLocalGenerator();
1037 std::string di = mf->GetStartOutputDirectory();
1039 di += lg->GetTargetDirectory(*linkee);
1040 di += "/DependInfo.cmake";
1041 *this->InfoFileStream << " \"" << di << "\"\n";
1045 *this->InfoFileStream
1049 // Check for a target-specific module output directory.
1050 if(const char* mdir = this->GetFortranModuleDirectory())
1052 *this->InfoFileStream
1054 << "# Fortran module output directory.\n"
1055 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
1058 // Target-specific include directories:
1059 *this->InfoFileStream
1061 << "# The include file search paths:\n";
1062 *this->InfoFileStream
1063 << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
1064 std::vector<std::string> includes;
1066 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1067 this->LocalGenerator->GetIncludeDirectories(includes,
1068 this->GeneratorTarget,
1070 for(std::vector<std::string>::iterator i = includes.begin();
1071 i != includes.end(); ++i)
1073 *this->InfoFileStream
1075 << this->LocalGenerator->Convert(i->c_str(),
1076 cmLocalGenerator::HOME_OUTPUT)
1079 *this->InfoFileStream
1081 *this->InfoFileStream
1082 << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
1083 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1084 *this->InfoFileStream
1085 << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
1086 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1087 *this->InfoFileStream
1088 << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
1089 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1091 // and now write the rule to use it
1092 std::vector<std::string> depends;
1093 std::vector<std::string> commands;
1095 // Construct the name of the dependency generation target.
1096 std::string depTarget =
1097 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1098 depTarget += "/depend";
1100 // Add a command to call CMake to scan dependencies. CMake will
1101 // touch the corresponding depends file after scanning dependencies.
1102 cmOStringStream depCmd;
1103 // TODO: Account for source file properties and directory-level
1104 // definitions when scanning for dependencies.
1105 #if !defined(_WIN32) || defined(__CYGWIN__)
1106 // This platform supports symlinks, so cmSystemTools will translate
1107 // paths. Make sure PWD is set to the original name of the home
1108 // output directory to help cmSystemTools to create the same
1109 // translation table for the dependency scanning process.
1111 << (this->LocalGenerator->Convert(
1112 this->Makefile->GetHomeOutputDirectory(),
1113 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1116 // Generate a call this signature:
1118 // cmake -E cmake_depends <generator>
1119 // <home-src-dir> <start-src-dir>
1120 // <home-out-dir> <start-out-dir>
1121 // <dep-info> --color=$(COLOR)
1123 // This gives the dependency scanner enough information to recreate
1124 // the state of our local generator sufficiently for its needs.
1125 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1126 << this->GlobalGenerator->GetName() << "\" "
1127 << this->Convert(this->Makefile->GetHomeDirectory(),
1128 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1130 << this->Convert(this->Makefile->GetStartDirectory(),
1131 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1133 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1134 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1136 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1137 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1139 << this->Convert(this->InfoFileNameFull.c_str(),
1140 cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1141 if(this->LocalGenerator->GetColorMakefile())
1143 depCmd << " --color=$(COLOR)";
1145 commands.push_back(depCmd.str());
1147 // Make sure all custom command outputs in this target are built.
1148 if(this->CustomCommandDriver == OnDepends)
1150 this->DriveCustomCommands(depends);
1154 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1156 depends, commands, true);
1159 //----------------------------------------------------------------------------
1161 cmMakefileTargetGenerator
1162 ::DriveCustomCommands(std::vector<std::string>& depends)
1164 // Depend on all custom command outputs.
1165 const std::vector<cmSourceFile*>& sources =
1166 this->Target->GetSourceFiles();
1167 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1168 source != sources.end(); ++source)
1170 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1172 const std::vector<std::string>& outputs = cc->GetOutputs();
1173 for(std::vector<std::string>::const_iterator o = outputs.begin();
1174 o != outputs.end(); ++o)
1176 depends.push_back(*o);
1182 //----------------------------------------------------------------------------
1183 void cmMakefileTargetGenerator
1184 ::WriteObjectDependRules(cmSourceFile& source,
1185 std::vector<std::string>& depends)
1187 // Create the list of dependencies known at cmake time. These are
1188 // shared between the object file and dependency scanning rule.
1189 depends.push_back(source.GetFullPath());
1190 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1192 std::vector<std::string> deps;
1193 cmSystemTools::ExpandListArgument(objectDeps, deps);
1194 for(std::vector<std::string>::iterator i = deps.begin();
1195 i != deps.end(); ++i)
1197 depends.push_back(i->c_str());
1202 //----------------------------------------------------------------------------
1203 void cmMakefileTargetGenerator
1204 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1206 // Collect the commands.
1207 std::vector<std::string> commands;
1208 std::string comment = this->LocalGenerator->ConstructComment(cc);
1209 if(!comment.empty())
1211 // add in a progress call if needed
1212 this->AppendProgress(commands);
1213 if(!this->NoRuleMessages)
1215 this->LocalGenerator
1216 ->AppendEcho(commands, comment.c_str(),
1217 cmLocalUnixMakefileGenerator3::EchoGenerate);
1221 // Now append the actual user-specified commands.
1222 cmOStringStream content;
1223 this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1224 cmLocalGenerator::HOME_OUTPUT,
1227 // Collect the dependencies.
1228 std::vector<std::string> depends;
1229 this->LocalGenerator->AppendCustomDepend(depends, cc);
1231 // Check whether we need to bother checking for a symbolic output.
1232 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1235 const std::vector<std::string>& outputs = cc.GetOutputs();
1236 std::vector<std::string>::const_iterator o = outputs.begin();
1238 bool symbolic = false;
1241 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1243 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1246 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1247 o->c_str(), depends, commands,
1250 // If the rule has changed make sure the output is rebuilt.
1253 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1257 // Write rules to drive building any outputs beyond the first.
1258 const char* in = o->c_str();
1259 for(++o; o != outputs.end(); ++o)
1261 bool symbolic = false;
1264 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1266 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1269 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1272 // Setup implicit dependency scanning.
1273 for(cmCustomCommand::ImplicitDependsList::const_iterator
1274 idi = cc.GetImplicitDepends().begin();
1275 idi != cc.GetImplicitDepends().end(); ++idi)
1277 std::string objFullPath =
1278 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1279 std::string srcFullPath =
1280 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1281 this->LocalGenerator->
1282 AddImplicitDepends(*this->Target, idi->first.c_str(),
1283 objFullPath.c_str(),
1284 srcFullPath.c_str());
1288 //----------------------------------------------------------------------------
1290 cmMakefileTargetGenerator
1291 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1293 // Add a rule to build the primary output if the extra output needs
1295 std::vector<std::string> commands;
1296 std::vector<std::string> depends;
1297 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1298 if(!emptyCommand.empty())
1300 commands.push_back(emptyCommand);
1302 depends.push_back(in);
1303 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1304 out, depends, commands,
1307 // Register the extra output as paired with the first output so that
1308 // the check-build-system step will remove the primary output if any
1309 // extra outputs are missing. This forces the rule to regenerate
1311 this->AddMultipleOutputPair(out, in);
1314 //----------------------------------------------------------------------------
1316 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1318 this->NumberOfProgressActions++;
1319 if(this->NoRuleMessages)
1323 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1324 progressDir += cmake::GetCMakeFilesDirectory();
1325 cmOStringStream progCmd;
1326 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1327 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1328 cmLocalGenerator::FULL,
1329 cmLocalGenerator::SHELL);
1330 progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1331 commands.push_back(progCmd.str());
1334 //----------------------------------------------------------------------------
1336 cmMakefileTargetGenerator
1337 ::WriteObjectsVariable(std::string& variableName,
1338 std::string& variableNameExternal)
1340 // Write a make variable assignment that lists all objects for the
1343 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1345 *this->BuildFileStream
1346 << "# Object files for target " << this->Target->GetName() << "\n"
1347 << variableName.c_str() << " =";
1349 const char* objName =
1350 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1351 const char* lineContinue =
1352 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1355 lineContinue = "\\";
1357 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1358 i != this->Objects.end(); ++i)
1360 *this->BuildFileStream << " " << lineContinue << "\n";
1363 *this->BuildFileStream <<
1364 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1365 cmLocalGenerator::MAKEFILE);
1369 *this->BuildFileStream <<
1370 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1373 *this->BuildFileStream << "\n";
1375 // Write a make variable assignment that lists all external objects
1377 variableNameExternal =
1378 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1379 "_EXTERNAL_OBJECTS");
1380 *this->BuildFileStream
1382 << "# External object files for target "
1383 << this->Target->GetName() << "\n"
1384 << variableNameExternal.c_str() << " =";
1385 for(std::vector<std::string>::const_iterator i =
1386 this->ExternalObjects.begin();
1387 i != this->ExternalObjects.end(); ++i)
1389 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1390 *this->BuildFileStream
1391 << " " << lineContinue << "\n"
1392 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1395 *this->BuildFileStream <<
1396 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1397 cmLocalGenerator::MAKEFILE);
1401 *this->BuildFileStream <<
1402 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1405 *this->BuildFileStream << "\n" << "\n";
1408 //----------------------------------------------------------------------------
1410 cmMakefileTargetGenerator
1411 ::WriteObjectsString(std::string& buildObjs)
1413 std::vector<std::string> objStrings;
1414 this->WriteObjectsStrings(objStrings);
1415 buildObjs = objStrings[0];
1418 //----------------------------------------------------------------------------
1419 class cmMakefileTargetGeneratorObjectStrings
1422 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1423 cmLocalUnixMakefileGenerator3* lg,
1424 std::string::size_type limit):
1425 Strings(strings), LocalGenerator(lg), LengthLimit(limit)
1429 void Feed(std::string const& obj)
1431 // Construct the name of the next object.
1433 this->LocalGenerator->Convert(obj.c_str(),
1434 cmLocalGenerator::START_OUTPUT,
1435 cmLocalGenerator::RESPONSE);
1437 // Roll over to next string if the limit will be exceeded.
1438 if(this->LengthLimit != std::string::npos &&
1439 (this->CurrentString.length() + 1 + this->NextObject.length()
1440 > this->LengthLimit))
1442 this->Strings.push_back(this->CurrentString);
1443 this->CurrentString = "";
1447 // Separate from previous object.
1448 this->CurrentString += this->Space;
1451 // Append this object.
1452 this->CurrentString += this->NextObject;
1456 this->Strings.push_back(this->CurrentString);
1459 std::vector<std::string>& Strings;
1460 cmLocalUnixMakefileGenerator3* LocalGenerator;
1461 std::string::size_type LengthLimit;
1462 std::string CurrentString;
1463 std::string NextObject;
1467 //----------------------------------------------------------------------------
1469 cmMakefileTargetGenerator
1470 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1471 std::string::size_type limit)
1473 cmMakefileTargetGeneratorObjectStrings
1474 helper(objStrings, this->LocalGenerator, limit);
1475 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1476 i != this->Objects.end(); ++i)
1480 for(std::vector<std::string>::const_iterator i =
1481 this->ExternalObjects.begin();
1482 i != this->ExternalObjects.end(); ++i)
1489 //----------------------------------------------------------------------------
1490 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1493 // Compute the name of the driver target.
1495 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1496 std::string buildTargetRuleName = dir;
1497 buildTargetRuleName += relink?"/preinstall":"/build";
1498 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1499 cmLocalGenerator::HOME_OUTPUT,
1500 cmLocalGenerator::UNCHANGED);
1502 // Build the list of target outputs to drive.
1503 std::vector<std::string> depends;
1506 depends.push_back(main_output);
1509 const char* comment = 0;
1512 // Setup the comment for the preinstall driver.
1513 comment = "Rule to relink during preinstall.";
1517 // Setup the comment for the main build driver.
1518 comment = "Rule to build all files generated by this target.";
1520 // Make sure all custom command outputs in this target are built.
1521 if(this->CustomCommandDriver == OnBuild)
1523 this->DriveCustomCommands(depends);
1526 // Make sure the extra files are built.
1527 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1528 i != this->ExtraFiles.end(); ++i)
1530 depends.push_back(*i);
1534 // Write the driver rule.
1535 std::vector<std::string> no_commands;
1536 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1537 buildTargetRuleName.c_str(),
1538 depends, no_commands, true);
1541 //----------------------------------------------------------------------------
1542 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1544 if(!this->Makefile->IsOn("APPLE"))
1546 return std::string();
1549 std::set<cmStdString> emitted;
1550 #ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */
1551 emitted.insert("/System/Library/Frameworks");
1553 std::vector<std::string> includes;
1555 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1556 this->LocalGenerator->GetIncludeDirectories(includes,
1557 this->GeneratorTarget,
1559 // check all include directories for frameworks as this
1560 // will already have added a -F for the framework
1561 for(std::vector<std::string>::iterator i = includes.begin();
1562 i != includes.end(); ++i)
1564 if(this->Target->NameResolvesToFramework(i->c_str()))
1566 std::string frameworkDir = *i;
1567 frameworkDir += "/../";
1568 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1569 emitted.insert(frameworkDir);
1574 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1575 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1577 std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
1578 for(std::vector<std::string>::const_iterator i = frameworks.begin();
1579 i != frameworks.end(); ++i)
1581 if(emitted.insert(*i).second)
1584 flags += this->Convert(i->c_str(),
1585 cmLocalGenerator::START_OUTPUT,
1586 cmLocalGenerator::SHELL, true);
1594 //----------------------------------------------------------------------------
1595 void cmMakefileTargetGenerator
1596 ::AppendTargetDepends(std::vector<std::string>& depends)
1598 // Static libraries never depend on anything for linking.
1599 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1604 // Loop over all library dependencies.
1605 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1606 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1608 std::vector<std::string> const& libDeps = cli->GetDepends();
1609 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1610 j != libDeps.end(); ++j)
1612 depends.push_back(*j);
1617 //----------------------------------------------------------------------------
1618 void cmMakefileTargetGenerator
1619 ::AppendObjectDepends(std::vector<std::string>& depends)
1621 // Add dependencies on the compiled object files.
1622 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
1623 std::string objTarget;
1624 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
1625 obj != this->Objects.end(); ++obj)
1627 objTarget = relPath;
1629 depends.push_back(objTarget);
1632 // Add dependencies on the external object files.
1633 for(std::vector<std::string>::const_iterator obj
1634 = this->ExternalObjects.begin();
1635 obj != this->ExternalObjects.end(); ++obj)
1637 depends.push_back(*obj);
1640 // Add a dependency on the rule file itself.
1641 this->LocalGenerator->AppendRuleDepend(depends,
1642 this->BuildFileNameFull.c_str());
1645 //----------------------------------------------------------------------------
1646 void cmMakefileTargetGenerator
1647 ::AppendLinkDepends(std::vector<std::string>& depends)
1649 this->AppendObjectDepends(depends);
1651 // Add dependencies on targets that must be built first.
1652 this->AppendTargetDepends(depends);
1654 // Add a dependency on the link definitions file, if any.
1655 if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
1657 depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
1660 // Add user-specified dependencies.
1661 if(const char* linkDepends =
1662 this->Target->GetProperty("LINK_DEPENDS"))
1664 cmSystemTools::ExpandListArgument(linkDepends, depends);
1668 //----------------------------------------------------------------------------
1669 std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
1671 std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
1672 if(this->Target->HasImplibGNUtoMS())
1674 std::string ruleVar = "CMAKE_";
1675 ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
1676 ruleVar += "_GNUtoMS_RULE";
1677 if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
1685 //----------------------------------------------------------------------------
1686 void cmMakefileTargetGenerator
1687 ::CloseFileStreams()
1689 delete this->BuildFileStream;
1690 delete this->InfoFileStream;
1691 delete this->FlagFileStream;
1694 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1695 const char* linkLang,
1696 std::string& linkFlags)
1698 // check for language flags that are not allowed at link time, and
1699 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1700 // which fails, there may be more]
1702 std::string removeFlags = "CMAKE_";
1703 removeFlags += linkLang;
1704 removeFlags += flagVar;
1705 std::string removeflags =
1706 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1707 std::vector<std::string> removeList;
1708 cmSystemTools::ExpandListArgument(removeflags, removeList);
1709 for(std::vector<std::string>::iterator i = removeList.begin();
1710 i != removeList.end(); ++i)
1712 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1716 //----------------------------------------------------------------------------
1718 cmMakefileTargetGenerator
1719 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1721 MultipleOutputPairsType::value_type p(depender, dependee);
1722 this->MultipleOutputPairs.insert(p);
1725 //----------------------------------------------------------------------------
1727 cmMakefileTargetGenerator
1728 ::CreateLinkScript(const char* name,
1729 std::vector<std::string> const& link_commands,
1730 std::vector<std::string>& makefile_commands,
1731 std::vector<std::string>& makefile_depends)
1733 // Create the link script file.
1734 std::string linkScriptName = this->TargetBuildDirectoryFull;
1735 linkScriptName += "/";
1736 linkScriptName += name;
1737 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1738 linkScriptStream.SetCopyIfDifferent(true);
1739 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1740 cmd != link_commands.end(); ++cmd)
1742 // Do not write out empty commands or commands beginning in the
1744 if(!cmd->empty() && (*cmd)[0] != ':')
1746 linkScriptStream << *cmd << "\n";
1750 // Create the makefile command to invoke the link script.
1751 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1752 link_command += this->Convert(linkScriptName.c_str(),
1753 cmLocalGenerator::START_OUTPUT,
1754 cmLocalGenerator::SHELL);
1755 link_command += " --verbose=$(VERBOSE)";
1756 makefile_commands.push_back(link_command);
1757 makefile_depends.push_back(linkScriptName);
1760 //----------------------------------------------------------------------------
1762 cmMakefileTargetGenerator
1763 ::CreateResponseFile(const char* name, std::string const& options,
1764 std::vector<std::string>& makefile_depends)
1766 // Create the response file.
1767 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1768 responseFileNameFull += "/";
1769 responseFileNameFull += name;
1770 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1771 responseStream.SetCopyIfDifferent(true);
1772 responseStream << options << "\n";
1774 // Add a dependency so the target will rebuild when the set of
1776 makefile_depends.push_back(responseFileNameFull);
1778 // Construct the name to be used on the command line.
1779 std::string responseFileName = this->TargetBuildDirectory;
1780 responseFileName += "/";
1781 responseFileName += name;
1782 return responseFileName;
1785 //----------------------------------------------------------------------------
1787 cmMakefileTargetGenerator
1788 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1789 bool useResponseFile, std::string& buildObjs,
1790 std::vector<std::string>& makefile_depends)
1792 std::string variableName;
1793 std::string variableNameExternal;
1794 this->WriteObjectsVariable(variableName, variableNameExternal);
1797 // MSVC response files cannot exceed 128K.
1798 std::string::size_type const responseFileLimit = 131000;
1800 // Construct the individual object list strings.
1801 std::vector<std::string> object_strings;
1802 this->WriteObjectsStrings(object_strings, responseFileLimit);
1804 // Lookup the response file reference flag.
1805 std::string responseFlagVar = "CMAKE_";
1806 responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
1807 responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
1808 const char* responseFlag =
1809 this->Makefile->GetDefinition(responseFlagVar.c_str());
1815 // Write a response file for each string.
1816 const char* sep = "";
1817 for(unsigned int i = 0; i < object_strings.size(); ++i)
1819 // Number the response files.
1821 sprintf(rsp, "objects%u.rsp", i+1);
1823 // Create this response file.
1824 std::string objects_rsp =
1825 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1827 // Separate from previous response file references.
1831 // Reference the response file.
1832 buildObjs += responseFlag;
1833 buildObjs += this->Convert(objects_rsp.c_str(),
1834 cmLocalGenerator::NONE,
1835 cmLocalGenerator::SHELL);
1838 else if(useLinkScript)
1840 if(!useArchiveRules)
1842 this->WriteObjectsString(buildObjs);
1848 buildObjs += variableName;
1849 buildObjs += ") $(";
1850 buildObjs += variableNameExternal;
1855 //----------------------------------------------------------------------------
1856 void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
1859 std::string responseVar = "CMAKE_";
1860 responseVar += lang;
1861 responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
1862 bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
1865 std::vector<std::string> includes;
1866 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1867 this->LocalGenerator->GetIncludeDirectories(includes,
1868 this->GeneratorTarget,
1871 std::string includeFlags =
1872 this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile);
1873 if(includeFlags.empty())
1880 std::string name = "includes_";
1883 std::string arg = "@" +
1884 this->CreateResponseFile(name.c_str(), includeFlags,
1885 this->FlagFileDepends[lang]);
1886 this->LocalGenerator->AppendFlags(flags, arg.c_str());
1890 this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
1894 //----------------------------------------------------------------------------
1895 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1897 // Compute the module directory.
1898 if(!this->FortranModuleDirectoryComputed)
1900 const char* target_mod_dir =
1901 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1902 const char* moddir_flag =
1903 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1904 if(target_mod_dir && moddir_flag)
1906 // Compute the full path to the module directory.
1907 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1909 // Already a full path.
1910 this->FortranModuleDirectory = target_mod_dir;
1914 // Interpret relative to the current output directory.
1915 this->FortranModuleDirectory =
1916 this->Makefile->GetCurrentOutputDirectory();
1917 this->FortranModuleDirectory += "/";
1918 this->FortranModuleDirectory += target_mod_dir;
1921 // Make sure the module output directory exists.
1922 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1924 this->FortranModuleDirectoryComputed = true;
1927 // Return the computed directory.
1928 if(this->FortranModuleDirectory.empty())
1934 return this->FortranModuleDirectory.c_str();
1938 //----------------------------------------------------------------------------
1939 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1941 // Enable module output if necessary.
1942 if(const char* modout_flag =
1943 this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG"))
1945 this->LocalGenerator->AppendFlags(flags, modout_flag);
1948 // Add a module output directory flag if necessary.
1949 const char* mod_dir = this->GetFortranModuleDirectory();
1952 mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
1956 const char* moddir_flag =
1957 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1958 std::string modflag = moddir_flag;
1959 modflag += this->Convert(mod_dir,
1960 cmLocalGenerator::START_OUTPUT,
1961 cmLocalGenerator::SHELL);
1962 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1965 // If there is a separate module path flag then duplicate the
1966 // include path with it. This compiler does not search the include
1967 // path for modules.
1968 if(const char* modpath_flag =
1969 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1971 std::vector<std::string> includes;
1972 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1973 this->LocalGenerator->GetIncludeDirectories(includes,
1974 this->GeneratorTarget,
1976 for(std::vector<std::string>::const_iterator idi = includes.begin();
1977 idi != includes.end(); ++idi)
1979 std::string flg = modpath_flag;
1980 flg += this->Convert(idi->c_str(),
1981 cmLocalGenerator::NONE,
1982 cmLocalGenerator::SHELL);
1983 this->LocalGenerator->AppendFlags(flags, flg.c_str());
1988 //----------------------------------------------------------------------------
1989 void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
1991 if(this->GeneratorTarget->ModuleDefinitionFile.empty())
1996 // TODO: Create a per-language flag variable.
1997 const char* defFileFlag =
1998 this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
2004 // Append the flag and value. Use ConvertToLinkReference to help
2005 // vs6's "cl -link" pass it to the linker.
2006 std::string flag = defFileFlag;
2007 flag += (this->LocalGenerator->ConvertToLinkReference(
2008 this->GeneratorTarget->ModuleDefinitionFile.c_str()));
2009 this->LocalGenerator->AppendFlags(flags, flag.c_str());
2012 //----------------------------------------------------------------------------
2013 const char* cmMakefileTargetGenerator::GetFeature(const char* feature)
2015 return this->Target->GetFeature(feature, this->ConfigName);
2018 //----------------------------------------------------------------------------
2019 bool cmMakefileTargetGenerator::GetFeatureAsBool(const char* feature)
2021 return cmSystemTools::IsOn(this->GetFeature(feature));
2024 //----------------------------------------------------------------------------
2025 void cmMakefileTargetGenerator::AddFeatureFlags(
2026 std::string& flags, const char* lang
2029 // Add language-specific flags.
2030 this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
2032 if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
2034 this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");