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->Target,
263 lang, this->ConfigName);
265 // Fortran-specific flags computed for this target.
268 this->AddFortranFlags(flags);
271 this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang);
273 // Add include directory flags.
274 this->AddIncludeFlags(flags, lang);
276 // Append old-style preprocessor definition flags.
277 this->LocalGenerator->
278 AppendFlags(flags, this->Makefile->GetDefineFlags());
280 // Add include directory flags.
281 this->LocalGenerator->
282 AppendFlags(flags,this->GetFrameworkFlags().c_str());
284 ByLanguageMap::value_type entry(l, flags);
285 i = this->FlagsByLanguage.insert(entry).first;
290 std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
292 ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
293 if (i == this->DefinesByLanguage.end())
296 const char *lang = l.c_str();
297 // Add the export symbol definition for shared library objects.
298 if(const char* exportMacro = this->Target->GetExportMacro())
300 this->LocalGenerator->AppendDefines(defines, exportMacro, lang);
303 // Add preprocessor definitions for this target and configuration.
304 this->LocalGenerator->AppendDefines
305 (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang);
306 this->LocalGenerator->AppendDefines
307 (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang);
308 std::string defPropName = "COMPILE_DEFINITIONS_";
310 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
311 this->LocalGenerator->AppendDefines
312 (defines, this->Makefile->GetProperty(defPropName.c_str()), lang);
313 this->LocalGenerator->AppendDefines
314 (defines, this->Target->GetProperty(defPropName.c_str()), lang);
316 ByLanguageMap::value_type entry(l, defines);
317 i = this->DefinesByLanguage.insert(entry).first;
322 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
324 // write language flags for target
325 std::set<cmStdString> languages;
326 this->Target->GetLanguages(languages);
327 // put the compiler in the rules.make file so that if it changes
329 for(std::set<cmStdString>::const_iterator l = languages.begin();
330 l != languages.end(); ++l)
332 cmStdString compiler = "CMAKE_";
334 compiler += "_COMPILER";
335 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
336 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
339 for(std::set<cmStdString>::const_iterator l = languages.begin();
340 l != languages.end(); ++l)
342 *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
343 *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
347 // Add target-specific flags.
348 if(this->Target->GetProperty("COMPILE_FLAGS"))
351 this->LocalGenerator->AppendFlags
352 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
353 *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
358 //----------------------------------------------------------------------------
360 cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
361 (cmSourceFile& source, const char* pkgloc)
363 // Skip OS X content when not building a Framework or Bundle.
364 if(this->Generator->MacContentDirectory.empty())
370 this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
372 // Get the input file location.
373 std::string input = source.GetFullPath();
375 // Get the output file location.
376 std::string output = macdir;
378 output += cmSystemTools::GetFilenameName(input);
379 this->Generator->CleanFiles.push_back(
380 this->Generator->Convert(output.c_str(),
381 cmLocalGenerator::START_OUTPUT));
382 output = this->Generator->Convert(output.c_str(),
383 cmLocalGenerator::HOME_OUTPUT);
385 // Create a rule to copy the content into the bundle.
386 std::vector<std::string> depends;
387 std::vector<std::string> commands;
388 depends.push_back(input);
389 std::string copyEcho = "Copying OS X content ";
391 this->Generator->LocalGenerator->AppendEcho(
392 commands, copyEcho.c_str(),
393 cmLocalUnixMakefileGenerator3::EchoBuild);
394 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
395 copyCommand += this->Generator->Convert(input.c_str(),
396 cmLocalGenerator::NONE,
397 cmLocalGenerator::SHELL);
399 copyCommand += this->Generator->Convert(output.c_str(),
400 cmLocalGenerator::NONE,
401 cmLocalGenerator::SHELL);
402 commands.push_back(copyCommand);
403 this->Generator->LocalGenerator->WriteMakeRule(
404 *this->Generator->BuildFileStream, 0,
406 depends, commands, false);
407 this->Generator->ExtraFiles.insert(output);
410 //----------------------------------------------------------------------------
411 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
413 // Identify the language of the source file.
414 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
417 // don't know anything about this file so skip it
421 // Get the full path name of the object file.
422 std::string const& objectName = this->GeneratorTarget->Objects[&source];
423 std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
427 // Avoid generating duplicate rules.
428 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
430 this->ObjectFiles.insert(obj);
435 err << "Warning: Source file \""
436 << source.GetFullPath()
437 << "\" is listed multiple times for target \""
438 << this->Target->GetName()
440 cmSystemTools::Message(err.str().c_str(), "Warning");
444 // Create the directory containing the object file. This may be a
445 // subdirectory under the target's directory.
446 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
447 cmSystemTools::MakeDirectory
448 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
450 // Save this in the target's list of object files.
451 this->Objects.push_back(obj);
452 this->CleanFiles.push_back(obj);
455 //std::string relativeObj
456 //= this->LocalGenerator->GetHomeRelativeOutputPath();
457 //relativeObj += obj;
459 // we compute some depends when writing the depend.make that we will also
460 // use in the build.make, same with depMakeFile
461 std::vector<std::string> depends;
462 std::string depMakeFile;
464 // generate the build rule file
465 this->WriteObjectBuildFile(obj, lang, source, depends);
467 // The object file should be checked for dependency integrity.
468 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
472 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
473 std::string srcFullPath =
474 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
475 this->LocalGenerator->
476 AddImplicitDepends(*this->Target, lang,
478 srcFullPath.c_str());
481 //----------------------------------------------------------------------------
483 cmMakefileTargetGenerator
484 ::AppendFortranFormatFlags(std::string& flags, cmSourceFile& source)
486 const char* srcfmt = source.GetProperty("Fortran_FORMAT");
487 cmLocalGenerator::FortranFormat format =
488 this->LocalGenerator->GetFortranFormat(srcfmt);
489 if(format == cmLocalGenerator::FortranFormatNone)
491 const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT");
492 format = this->LocalGenerator->GetFortranFormat(tgtfmt);
497 case cmLocalGenerator::FortranFormatFixed:
498 var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break;
499 case cmLocalGenerator::FortranFormatFree:
500 var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break;
505 this->LocalGenerator->AppendFlags(
506 flags, this->Makefile->GetDefinition(var));
510 //----------------------------------------------------------------------------
512 cmMakefileTargetGenerator
513 ::WriteObjectBuildFile(std::string &obj,
515 cmSourceFile& source,
516 std::vector<std::string>& depends)
518 this->LocalGenerator->AppendRuleDepend(depends,
519 this->FlagFileNameFull.c_str());
520 this->LocalGenerator->AppendRuleDepends(depends,
521 this->FlagFileDepends[lang]);
523 // generate the depend scanning rule
524 this->WriteObjectDependRules(source, depends);
526 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
528 // Write the build rule.
530 // Build the set of compiler flags.
533 // Add language-specific flags.
534 std::string langFlags = "$(";
536 langFlags += "_FLAGS)";
537 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
539 // Add target-specific flags.
540 if(this->Target->GetProperty("COMPILE_FLAGS"))
542 std::string langIncludeExpr = "CMAKE_";
543 langIncludeExpr += lang;
544 langIncludeExpr += "_FLAG_REGEX";
545 const char* regex = this->Makefile->
546 GetDefinition(langIncludeExpr.c_str());
549 cmsys::RegularExpression r(regex);
550 std::vector<std::string> args;
551 cmSystemTools::ParseWindowsCommandLine(
552 this->Target->GetProperty("COMPILE_FLAGS"),
554 for(std::vector<std::string>::iterator i = args.begin();
555 i != args.end(); ++i)
557 if(r.find(i->c_str()))
559 this->LocalGenerator->AppendFlags
566 this->LocalGenerator->AppendFlags
567 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
571 // Add Fortran format flags.
572 if(strcmp(lang, "Fortran") == 0)
574 this->AppendFortranFormatFlags(flags, source);
577 // Add flags from source file properties.
578 if (source.GetProperty("COMPILE_FLAGS"))
580 this->LocalGenerator->AppendFlags
581 (flags, source.GetProperty("COMPILE_FLAGS"));
582 *this->FlagFileStream << "# Custom flags: "
583 << relativeObj << "_FLAGS = "
584 << source.GetProperty("COMPILE_FLAGS")
589 // Add language-specific defines.
590 std::string defines = "$(";
592 defines += "_DEFINES)";
594 // Add source-sepcific preprocessor definitions.
595 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
597 this->LocalGenerator->AppendDefines(defines, compile_defs, lang);
598 *this->FlagFileStream << "# Custom defines: "
599 << relativeObj << "_DEFINES = "
600 << compile_defs << "\n"
603 std::string configUpper =
604 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
605 std::string defPropName = "COMPILE_DEFINITIONS_";
606 defPropName += configUpper;
607 if(const char* config_compile_defs =
608 source.GetProperty(defPropName.c_str()))
610 this->LocalGenerator->AppendDefines(defines, config_compile_defs, lang);
611 *this->FlagFileStream
612 << "# Custom defines: "
613 << relativeObj << "_DEFINES_" << configUpper
614 << " = " << config_compile_defs << "\n"
618 // Get the output paths for source and object files.
619 std::string sourceFile = source.GetFullPath();
620 if(this->LocalGenerator->UseRelativePaths)
622 sourceFile = this->Convert(sourceFile.c_str(),
623 cmLocalGenerator::START_OUTPUT);
625 sourceFile = this->Convert(sourceFile.c_str(),
626 cmLocalGenerator::NONE,
627 cmLocalGenerator::SHELL);
629 // Construct the build message.
630 std::vector<std::string> no_commands;
631 std::vector<std::string> commands;
633 // add in a progress call if needed
634 this->AppendProgress(commands);
636 if(!this->NoRuleMessages)
638 std::string buildEcho = "Building ";
640 buildEcho += " object ";
641 buildEcho += relativeObj;
642 this->LocalGenerator->AppendEcho
643 (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
646 std::string targetOutPathPDB;
648 std::string targetFullPathPDB;
649 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
650 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
651 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
652 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
654 targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
655 targetFullPathPDB += "/";
656 targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
659 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
660 cmLocalGenerator::SHELL);
662 cmLocalGenerator::RuleVariables vars;
663 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
664 vars.CMTarget = this->Target;
665 vars.Language = lang;
666 vars.TargetPDB = targetOutPathPDB.c_str();
667 vars.Source = sourceFile.c_str();
668 std::string shellObj =
669 this->Convert(obj.c_str(),
670 cmLocalGenerator::NONE,
671 cmLocalGenerator::SHELL).c_str();
672 vars.Object = shellObj.c_str();
673 std::string objectDir = cmSystemTools::GetFilenamePath(obj);
674 objectDir = this->Convert(objectDir.c_str(),
675 cmLocalGenerator::START_OUTPUT,
676 cmLocalGenerator::SHELL);
677 vars.ObjectDir = objectDir.c_str();
678 vars.Flags = flags.c_str();
679 vars.Defines = defines.c_str();
681 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
682 (strcmp(lang, "CXX") == 0));
684 // Construct the compile rules.
686 std::string compileRuleVar = "CMAKE_";
687 compileRuleVar += lang;
688 compileRuleVar += "_COMPILE_OBJECT";
689 std::string compileRule =
690 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
691 std::vector<std::string> compileCommands;
692 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
694 if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
695 lang_is_c_or_cxx && compileCommands.size() == 1)
697 std::string compileCommand = compileCommands[0];
698 this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
699 std::string workingDirectory =
700 this->LocalGenerator->Convert(
701 this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
702 compileCommand.replace(compileCommand.find(langFlags),
703 langFlags.size(), this->GetFlags(lang));
704 std::string langDefines = std::string("$(") + lang + "_DEFINES)";
705 compileCommand.replace(compileCommand.find(langDefines),
706 langDefines.size(), this->GetDefines(lang));
707 this->GlobalGenerator->AddCXXCompileCommand(
708 source.GetFullPath(), workingDirectory, compileCommand);
711 // Expand placeholders in the commands.
712 for(std::vector<std::string>::iterator i = compileCommands.begin();
713 i != compileCommands.end(); ++i)
715 this->LocalGenerator->ExpandRuleVariables(*i, vars);
718 // Change the command working directory to the local build tree.
719 this->LocalGenerator->CreateCDCommand
721 this->Makefile->GetStartOutputDirectory(),
722 cmLocalGenerator::HOME_OUTPUT);
723 commands.insert(commands.end(),
724 compileCommands.begin(), compileCommands.end());
728 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
730 depends, commands, false);
732 // Check for extra outputs created by the compilation.
733 if(const char* extra_outputs_str =
734 source.GetProperty("OBJECT_OUTPUTS"))
736 std::vector<std::string> extra_outputs;
737 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
738 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
739 eoi != extra_outputs.end(); ++eoi)
741 // Register this as an extra output for the object file rule.
742 // This will cause the object file to be rebuilt if the extra
743 // output is missing.
744 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
746 // Register this as an extra file to clean.
747 this->CleanFiles.push_back(eoi->c_str());
751 bool do_preprocess_rules = lang_is_c_or_cxx &&
752 this->LocalGenerator->GetCreatePreprocessedSourceRules();
753 bool do_assembly_rules = lang_is_c_or_cxx &&
754 this->LocalGenerator->GetCreateAssemblySourceRules();
755 if(do_preprocess_rules || do_assembly_rules)
757 std::vector<std::string> force_depends;
758 force_depends.push_back("cmake_force");
759 std::string::size_type dot_pos = relativeObj.rfind(".");
760 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
761 dot_pos = obj.rfind(".");
762 std::string objBase = obj.substr(0, dot_pos);
764 if(do_preprocess_rules)
767 std::string relativeObjI = relativeObjBase + ".i";
768 std::string objI = objBase + ".i";
770 std::string preprocessEcho = "Preprocessing ";
771 preprocessEcho += lang;
772 preprocessEcho += " source to ";
773 preprocessEcho += objI;
774 this->LocalGenerator->AppendEcho(
775 commands, preprocessEcho.c_str(),
776 cmLocalUnixMakefileGenerator3::EchoBuild
779 std::string preprocessRuleVar = "CMAKE_";
780 preprocessRuleVar += lang;
781 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
782 if(const char* preprocessRule =
783 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
785 std::vector<std::string> preprocessCommands;
786 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
788 std::string shellObjI =
789 this->Convert(objI.c_str(),
790 cmLocalGenerator::NONE,
791 cmLocalGenerator::SHELL).c_str();
792 vars.PreprocessedSource = shellObjI.c_str();
794 // Expand placeholders in the commands.
795 for(std::vector<std::string>::iterator i = preprocessCommands.begin();
796 i != preprocessCommands.end(); ++i)
798 this->LocalGenerator->ExpandRuleVariables(*i, vars);
801 this->LocalGenerator->CreateCDCommand
803 this->Makefile->GetStartOutputDirectory(),
804 cmLocalGenerator::HOME_OUTPUT);
805 commands.insert(commands.end(),
806 preprocessCommands.begin(),
807 preprocessCommands.end());
811 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
812 cmd += preprocessRuleVar;
813 commands.push_back(cmd);
816 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
817 relativeObjI.c_str(),
818 force_depends, commands, false);
821 if(do_assembly_rules)
824 std::string relativeObjS = relativeObjBase + ".s";
825 std::string objS = objBase + ".s";
827 std::string assemblyEcho = "Compiling ";
828 assemblyEcho += lang;
829 assemblyEcho += " source to assembly ";
830 assemblyEcho += objS;
831 this->LocalGenerator->AppendEcho(
832 commands, assemblyEcho.c_str(),
833 cmLocalUnixMakefileGenerator3::EchoBuild
836 std::string assemblyRuleVar = "CMAKE_";
837 assemblyRuleVar += lang;
838 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
839 if(const char* assemblyRule =
840 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
842 std::vector<std::string> assemblyCommands;
843 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
845 std::string shellObjS =
846 this->Convert(objS.c_str(),
847 cmLocalGenerator::NONE,
848 cmLocalGenerator::SHELL).c_str();
849 vars.AssemblySource = shellObjS.c_str();
851 // Expand placeholders in the commands.
852 for(std::vector<std::string>::iterator i = assemblyCommands.begin();
853 i != assemblyCommands.end(); ++i)
855 this->LocalGenerator->ExpandRuleVariables(*i, vars);
858 this->LocalGenerator->CreateCDCommand
860 this->Makefile->GetStartOutputDirectory(),
861 cmLocalGenerator::HOME_OUTPUT);
862 commands.insert(commands.end(),
863 assemblyCommands.begin(),
864 assemblyCommands.end());
868 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
869 cmd += assemblyRuleVar;
870 commands.push_back(cmd);
873 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
874 relativeObjS.c_str(),
875 force_depends, commands, false);
879 // If the language needs provides-requires mode, create the
880 // corresponding targets.
881 std::string objectRequires = relativeObj;
882 objectRequires += ".requires";
883 std::vector<std::string> p_depends;
884 // always provide an empty requires target
885 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
886 objectRequires.c_str(), p_depends,
889 // write a build rule to recursively build what this obj provides
890 std::string objectProvides = relativeObj;
891 objectProvides += ".provides";
892 std::string temp = relativeObj;
893 temp += ".provides.build";
894 std::vector<std::string> r_commands;
895 std::string tgtMakefileName =
896 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
897 tgtMakefileName += "/build.make";
899 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
903 p_depends.push_back(objectRequires);
904 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
905 objectProvides.c_str(), p_depends,
908 // write the provides.build rule dependency on the obj file
910 p_depends.push_back(relativeObj);
911 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
912 temp.c_str(), p_depends, no_commands,
916 //----------------------------------------------------------------------------
917 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
919 std::vector<std::string> depends;
920 std::vector<std::string> no_commands;
922 // Construct the name of the dependency generation target.
923 std::string depTarget =
924 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
925 depTarget += "/requires";
927 // This target drives dependency generation for all object files.
928 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
929 std::string objTarget;
930 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
931 obj != this->Objects.end(); ++obj)
935 objTarget += ".requires";
936 depends.push_back(objTarget);
940 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
942 depends, no_commands, true);
945 //----------------------------------------------------------------------------
946 void cmMakefileTargetGenerator::WriteTargetCleanRules()
948 std::vector<std::string> depends;
949 std::vector<std::string> commands;
951 // Construct the clean target name.
952 std::string cleanTarget =
953 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
954 cleanTarget += "/clean";
956 // Construct the clean command.
957 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
959 this->LocalGenerator->CreateCDCommand
961 this->Makefile->GetStartOutputDirectory(),
962 cmLocalGenerator::HOME_OUTPUT);
965 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
967 depends, commands, true);
971 //----------------------------------------------------------------------------
972 void cmMakefileTargetGenerator::WriteTargetDependRules()
974 // must write the targets depend info file
975 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
976 this->InfoFileNameFull = dir;
977 this->InfoFileNameFull += "/DependInfo.cmake";
978 this->InfoFileNameFull =
979 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
980 this->InfoFileStream =
981 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
982 this->InfoFileStream->SetCopyIfDifferent(true);
983 if(!*this->InfoFileStream)
987 this->LocalGenerator->
988 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
990 // Store multiple output pairs in the depend info file.
991 if(!this->MultipleOutputPairs.empty())
993 *this->InfoFileStream
995 << "# Pairs of files generated by the same build rule.\n"
996 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
997 for(MultipleOutputPairsType::const_iterator pi =
998 this->MultipleOutputPairs.begin();
999 pi != this->MultipleOutputPairs.end(); ++pi)
1001 *this->InfoFileStream
1002 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
1003 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
1006 *this->InfoFileStream << " )\n\n";
1009 // Store list of targets linked directly or transitively.
1011 *this->InfoFileStream
1013 << "# Targets to which this target links.\n"
1014 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
1015 std::set<cmTarget const*> emitted;
1016 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1017 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1019 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
1020 for(cmComputeLinkInformation::ItemVector::const_iterator
1021 i = items.begin(); i != items.end(); ++i)
1023 cmTarget const* linkee = i->Target;
1024 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
1026 cmMakefile* mf = linkee->GetMakefile();
1027 cmLocalGenerator* lg = mf->GetLocalGenerator();
1028 std::string di = mf->GetStartOutputDirectory();
1030 di += lg->GetTargetDirectory(*linkee);
1031 di += "/DependInfo.cmake";
1032 *this->InfoFileStream << " \"" << di << "\"\n";
1036 *this->InfoFileStream
1040 // Check for a target-specific module output directory.
1041 if(const char* mdir = this->GetFortranModuleDirectory())
1043 *this->InfoFileStream
1045 << "# Fortran module output directory.\n"
1046 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
1049 // Target-specific include directories:
1050 *this->InfoFileStream
1052 << "# The include file search paths:\n";
1053 *this->InfoFileStream
1054 << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
1055 std::vector<std::string> includes;
1056 this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1057 for(std::vector<std::string>::iterator i = includes.begin();
1058 i != includes.end(); ++i)
1060 *this->InfoFileStream
1062 << this->LocalGenerator->Convert(i->c_str(),
1063 cmLocalGenerator::HOME_OUTPUT)
1066 *this->InfoFileStream
1068 *this->InfoFileStream
1069 << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
1070 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1071 *this->InfoFileStream
1072 << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
1073 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1074 *this->InfoFileStream
1075 << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
1076 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1078 // and now write the rule to use it
1079 std::vector<std::string> depends;
1080 std::vector<std::string> commands;
1082 // Construct the name of the dependency generation target.
1083 std::string depTarget =
1084 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1085 depTarget += "/depend";
1087 // Add a command to call CMake to scan dependencies. CMake will
1088 // touch the corresponding depends file after scanning dependencies.
1089 cmOStringStream depCmd;
1090 // TODO: Account for source file properties and directory-level
1091 // definitions when scanning for dependencies.
1092 #if !defined(_WIN32) || defined(__CYGWIN__)
1093 // This platform supports symlinks, so cmSystemTools will translate
1094 // paths. Make sure PWD is set to the original name of the home
1095 // output directory to help cmSystemTools to create the same
1096 // translation table for the dependency scanning process.
1098 << (this->LocalGenerator->Convert(
1099 this->Makefile->GetHomeOutputDirectory(),
1100 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1103 // Generate a call this signature:
1105 // cmake -E cmake_depends <generator>
1106 // <home-src-dir> <start-src-dir>
1107 // <home-out-dir> <start-out-dir>
1108 // <dep-info> --color=$(COLOR)
1110 // This gives the dependency scanner enough information to recreate
1111 // the state of our local generator sufficiently for its needs.
1112 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1113 << this->GlobalGenerator->GetName() << "\" "
1114 << this->Convert(this->Makefile->GetHomeDirectory(),
1115 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1117 << this->Convert(this->Makefile->GetStartDirectory(),
1118 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1120 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1121 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1123 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1124 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1126 << this->Convert(this->InfoFileNameFull.c_str(),
1127 cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1128 if(this->LocalGenerator->GetColorMakefile())
1130 depCmd << " --color=$(COLOR)";
1132 commands.push_back(depCmd.str());
1134 // Make sure all custom command outputs in this target are built.
1135 if(this->CustomCommandDriver == OnDepends)
1137 this->DriveCustomCommands(depends);
1141 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1143 depends, commands, true);
1146 //----------------------------------------------------------------------------
1148 cmMakefileTargetGenerator
1149 ::DriveCustomCommands(std::vector<std::string>& depends)
1151 // Depend on all custom command outputs.
1152 const std::vector<cmSourceFile*>& sources =
1153 this->Target->GetSourceFiles();
1154 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1155 source != sources.end(); ++source)
1157 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1159 const std::vector<std::string>& outputs = cc->GetOutputs();
1160 for(std::vector<std::string>::const_iterator o = outputs.begin();
1161 o != outputs.end(); ++o)
1163 depends.push_back(*o);
1169 //----------------------------------------------------------------------------
1170 void cmMakefileTargetGenerator
1171 ::WriteObjectDependRules(cmSourceFile& source,
1172 std::vector<std::string>& depends)
1174 // Create the list of dependencies known at cmake time. These are
1175 // shared between the object file and dependency scanning rule.
1176 depends.push_back(source.GetFullPath());
1177 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1179 std::vector<std::string> deps;
1180 cmSystemTools::ExpandListArgument(objectDeps, deps);
1181 for(std::vector<std::string>::iterator i = deps.begin();
1182 i != deps.end(); ++i)
1184 depends.push_back(i->c_str());
1189 //----------------------------------------------------------------------------
1190 void cmMakefileTargetGenerator
1191 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1193 // Collect the commands.
1194 std::vector<std::string> commands;
1195 std::string comment = this->LocalGenerator->ConstructComment(cc);
1196 if(!comment.empty())
1198 // add in a progress call if needed
1199 this->AppendProgress(commands);
1200 if(!this->NoRuleMessages)
1202 this->LocalGenerator
1203 ->AppendEcho(commands, comment.c_str(),
1204 cmLocalUnixMakefileGenerator3::EchoGenerate);
1208 // Now append the actual user-specified commands.
1209 cmOStringStream content;
1210 this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1211 cmLocalGenerator::HOME_OUTPUT,
1214 // Collect the dependencies.
1215 std::vector<std::string> depends;
1216 this->LocalGenerator->AppendCustomDepend(depends, cc);
1218 // Check whether we need to bother checking for a symbolic output.
1219 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1222 const std::vector<std::string>& outputs = cc.GetOutputs();
1223 std::vector<std::string>::const_iterator o = outputs.begin();
1225 bool symbolic = false;
1228 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1230 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1233 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1234 o->c_str(), depends, commands,
1237 // If the rule has changed make sure the output is rebuilt.
1240 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1244 // Write rules to drive building any outputs beyond the first.
1245 const char* in = o->c_str();
1246 for(++o; o != outputs.end(); ++o)
1248 bool symbolic = false;
1251 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1253 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1256 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1259 // Setup implicit dependency scanning.
1260 for(cmCustomCommand::ImplicitDependsList::const_iterator
1261 idi = cc.GetImplicitDepends().begin();
1262 idi != cc.GetImplicitDepends().end(); ++idi)
1264 std::string objFullPath =
1265 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1266 std::string srcFullPath =
1267 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1268 this->LocalGenerator->
1269 AddImplicitDepends(*this->Target, idi->first.c_str(),
1270 objFullPath.c_str(),
1271 srcFullPath.c_str());
1275 //----------------------------------------------------------------------------
1277 cmMakefileTargetGenerator
1278 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1280 // Add a rule to build the primary output if the extra output needs
1282 std::vector<std::string> commands;
1283 std::vector<std::string> depends;
1284 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1285 if(!emptyCommand.empty())
1287 commands.push_back(emptyCommand);
1289 depends.push_back(in);
1290 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1291 out, depends, commands,
1294 // Register the extra output as paired with the first output so that
1295 // the check-build-system step will remove the primary output if any
1296 // extra outputs are missing. This forces the rule to regenerate
1298 this->AddMultipleOutputPair(out, in);
1301 //----------------------------------------------------------------------------
1303 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1305 this->NumberOfProgressActions++;
1306 if(this->NoRuleMessages)
1310 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1311 progressDir += cmake::GetCMakeFilesDirectory();
1312 cmOStringStream progCmd;
1313 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1314 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1315 cmLocalGenerator::FULL,
1316 cmLocalGenerator::SHELL);
1317 progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1318 commands.push_back(progCmd.str());
1321 //----------------------------------------------------------------------------
1323 cmMakefileTargetGenerator
1324 ::WriteObjectsVariable(std::string& variableName,
1325 std::string& variableNameExternal)
1327 // Write a make variable assignment that lists all objects for the
1330 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1332 *this->BuildFileStream
1333 << "# Object files for target " << this->Target->GetName() << "\n"
1334 << variableName.c_str() << " =";
1336 const char* objName =
1337 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1338 const char* lineContinue =
1339 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1342 lineContinue = "\\";
1344 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1345 i != this->Objects.end(); ++i)
1347 *this->BuildFileStream << " " << lineContinue << "\n";
1350 *this->BuildFileStream <<
1351 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1352 cmLocalGenerator::MAKEFILE);
1356 *this->BuildFileStream <<
1357 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1360 *this->BuildFileStream << "\n";
1362 // Write a make variable assignment that lists all external objects
1364 variableNameExternal =
1365 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1366 "_EXTERNAL_OBJECTS");
1367 *this->BuildFileStream
1369 << "# External object files for target "
1370 << this->Target->GetName() << "\n"
1371 << variableNameExternal.c_str() << " =";
1372 for(std::vector<std::string>::const_iterator i =
1373 this->ExternalObjects.begin();
1374 i != this->ExternalObjects.end(); ++i)
1376 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1377 *this->BuildFileStream
1378 << " " << lineContinue << "\n"
1379 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1382 *this->BuildFileStream <<
1383 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1384 cmLocalGenerator::MAKEFILE);
1388 *this->BuildFileStream <<
1389 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1392 *this->BuildFileStream << "\n" << "\n";
1395 //----------------------------------------------------------------------------
1397 cmMakefileTargetGenerator
1398 ::WriteObjectsString(std::string& buildObjs)
1400 std::vector<std::string> objStrings;
1401 this->WriteObjectsStrings(objStrings);
1402 buildObjs = objStrings[0];
1405 //----------------------------------------------------------------------------
1406 class cmMakefileTargetGeneratorObjectStrings
1409 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1410 cmLocalUnixMakefileGenerator3* lg,
1411 std::string::size_type limit):
1412 Strings(strings), LocalGenerator(lg), LengthLimit(limit)
1416 void Feed(std::string const& obj)
1418 // Construct the name of the next object.
1420 this->LocalGenerator->Convert(obj.c_str(),
1421 cmLocalGenerator::START_OUTPUT,
1422 cmLocalGenerator::RESPONSE);
1424 // Roll over to next string if the limit will be exceeded.
1425 if(this->LengthLimit != std::string::npos &&
1426 (this->CurrentString.length() + 1 + this->NextObject.length()
1427 > this->LengthLimit))
1429 this->Strings.push_back(this->CurrentString);
1430 this->CurrentString = "";
1434 // Separate from previous object.
1435 this->CurrentString += this->Space;
1438 // Append this object.
1439 this->CurrentString += this->NextObject;
1443 this->Strings.push_back(this->CurrentString);
1446 std::vector<std::string>& Strings;
1447 cmLocalUnixMakefileGenerator3* LocalGenerator;
1448 std::string::size_type LengthLimit;
1449 std::string CurrentString;
1450 std::string NextObject;
1454 //----------------------------------------------------------------------------
1456 cmMakefileTargetGenerator
1457 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1458 std::string::size_type limit)
1460 cmMakefileTargetGeneratorObjectStrings
1461 helper(objStrings, this->LocalGenerator, limit);
1462 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1463 i != this->Objects.end(); ++i)
1467 for(std::vector<std::string>::const_iterator i =
1468 this->ExternalObjects.begin();
1469 i != this->ExternalObjects.end(); ++i)
1476 //----------------------------------------------------------------------------
1477 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1480 // Compute the name of the driver target.
1482 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1483 std::string buildTargetRuleName = dir;
1484 buildTargetRuleName += relink?"/preinstall":"/build";
1485 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1486 cmLocalGenerator::HOME_OUTPUT,
1487 cmLocalGenerator::UNCHANGED);
1489 // Build the list of target outputs to drive.
1490 std::vector<std::string> depends;
1493 depends.push_back(main_output);
1496 const char* comment = 0;
1499 // Setup the comment for the preinstall driver.
1500 comment = "Rule to relink during preinstall.";
1504 // Setup the comment for the main build driver.
1505 comment = "Rule to build all files generated by this target.";
1507 // Make sure all custom command outputs in this target are built.
1508 if(this->CustomCommandDriver == OnBuild)
1510 this->DriveCustomCommands(depends);
1513 // Make sure the extra files are built.
1514 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1515 i != this->ExtraFiles.end(); ++i)
1517 depends.push_back(*i);
1521 // Write the driver rule.
1522 std::vector<std::string> no_commands;
1523 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1524 buildTargetRuleName.c_str(),
1525 depends, no_commands, true);
1528 //----------------------------------------------------------------------------
1529 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1531 if(!this->Makefile->IsOn("APPLE"))
1533 return std::string();
1536 std::set<cmStdString> emitted;
1537 #ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */
1538 emitted.insert("/System/Library/Frameworks");
1540 std::vector<std::string> includes;
1541 this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1542 std::vector<std::string>::iterator i;
1543 // check all include directories for frameworks as this
1544 // will already have added a -F for the framework
1545 for(i = includes.begin(); i != includes.end(); ++i)
1547 if(this->Target->NameResolvesToFramework(i->c_str()))
1549 std::string frameworkDir = *i;
1550 frameworkDir += "/../";
1551 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1552 emitted.insert(frameworkDir);
1557 std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1558 for(i = frameworks.begin();
1559 i != frameworks.end(); ++i)
1561 if(emitted.insert(*i).second)
1564 flags += this->Convert(i->c_str(),
1565 cmLocalGenerator::START_OUTPUT,
1566 cmLocalGenerator::SHELL, true);
1573 //----------------------------------------------------------------------------
1574 void cmMakefileTargetGenerator
1575 ::AppendTargetDepends(std::vector<std::string>& depends)
1577 // Static libraries never depend on anything for linking.
1578 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1583 // Loop over all library dependencies.
1584 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1585 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1587 std::vector<std::string> const& libDeps = cli->GetDepends();
1588 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1589 j != libDeps.end(); ++j)
1591 depends.push_back(*j);
1596 //----------------------------------------------------------------------------
1597 void cmMakefileTargetGenerator
1598 ::AppendObjectDepends(std::vector<std::string>& depends)
1600 // Add dependencies on the compiled object files.
1601 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
1602 std::string objTarget;
1603 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
1604 obj != this->Objects.end(); ++obj)
1606 objTarget = relPath;
1608 depends.push_back(objTarget);
1611 // Add dependencies on the external object files.
1612 for(std::vector<std::string>::const_iterator obj
1613 = this->ExternalObjects.begin();
1614 obj != this->ExternalObjects.end(); ++obj)
1616 depends.push_back(*obj);
1619 // Add a dependency on the rule file itself.
1620 this->LocalGenerator->AppendRuleDepend(depends,
1621 this->BuildFileNameFull.c_str());
1624 //----------------------------------------------------------------------------
1625 void cmMakefileTargetGenerator
1626 ::AppendLinkDepends(std::vector<std::string>& depends)
1628 this->AppendObjectDepends(depends);
1630 // Add dependencies on targets that must be built first.
1631 this->AppendTargetDepends(depends);
1633 // Add a dependency on the link definitions file, if any.
1634 if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
1636 depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
1639 // Add user-specified dependencies.
1640 if(const char* linkDepends =
1641 this->Target->GetProperty("LINK_DEPENDS"))
1643 cmSystemTools::ExpandListArgument(linkDepends, depends);
1647 //----------------------------------------------------------------------------
1648 std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
1650 std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
1651 if(this->Target->HasImplibGNUtoMS())
1653 std::string ruleVar = "CMAKE_";
1654 ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
1655 ruleVar += "_GNUtoMS_RULE";
1656 if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
1664 //----------------------------------------------------------------------------
1665 void cmMakefileTargetGenerator
1666 ::CloseFileStreams()
1668 delete this->BuildFileStream;
1669 delete this->InfoFileStream;
1670 delete this->FlagFileStream;
1673 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1674 const char* linkLang,
1675 std::string& linkFlags)
1677 // check for language flags that are not allowed at link time, and
1678 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1679 // which fails, there may be more]
1681 std::string removeFlags = "CMAKE_";
1682 removeFlags += linkLang;
1683 removeFlags += flagVar;
1684 std::string removeflags =
1685 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1686 std::vector<std::string> removeList;
1687 cmSystemTools::ExpandListArgument(removeflags, removeList);
1688 for(std::vector<std::string>::iterator i = removeList.begin();
1689 i != removeList.end(); ++i)
1691 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1695 //----------------------------------------------------------------------------
1697 cmMakefileTargetGenerator
1698 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1700 MultipleOutputPairsType::value_type p(depender, dependee);
1701 this->MultipleOutputPairs.insert(p);
1704 //----------------------------------------------------------------------------
1706 cmMakefileTargetGenerator
1707 ::CreateLinkScript(const char* name,
1708 std::vector<std::string> const& link_commands,
1709 std::vector<std::string>& makefile_commands,
1710 std::vector<std::string>& makefile_depends)
1712 // Create the link script file.
1713 std::string linkScriptName = this->TargetBuildDirectoryFull;
1714 linkScriptName += "/";
1715 linkScriptName += name;
1716 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1717 linkScriptStream.SetCopyIfDifferent(true);
1718 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1719 cmd != link_commands.end(); ++cmd)
1721 // Do not write out empty commands or commands beginning in the
1723 if(!cmd->empty() && (*cmd)[0] != ':')
1725 linkScriptStream << *cmd << "\n";
1729 // Create the makefile command to invoke the link script.
1730 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1731 link_command += this->Convert(linkScriptName.c_str(),
1732 cmLocalGenerator::START_OUTPUT,
1733 cmLocalGenerator::SHELL);
1734 link_command += " --verbose=$(VERBOSE)";
1735 makefile_commands.push_back(link_command);
1736 makefile_depends.push_back(linkScriptName);
1739 //----------------------------------------------------------------------------
1741 cmMakefileTargetGenerator
1742 ::CreateResponseFile(const char* name, std::string const& options,
1743 std::vector<std::string>& makefile_depends)
1745 // Create the response file.
1746 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1747 responseFileNameFull += "/";
1748 responseFileNameFull += name;
1749 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1750 responseStream.SetCopyIfDifferent(true);
1751 responseStream << options << "\n";
1753 // Add a dependency so the target will rebuild when the set of
1755 makefile_depends.push_back(responseFileNameFull);
1757 // Construct the name to be used on the command line.
1758 std::string responseFileName = this->TargetBuildDirectory;
1759 responseFileName += "/";
1760 responseFileName += name;
1761 return responseFileName;
1764 //----------------------------------------------------------------------------
1766 cmMakefileTargetGenerator
1767 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1768 bool useResponseFile, std::string& buildObjs,
1769 std::vector<std::string>& makefile_depends)
1771 std::string variableName;
1772 std::string variableNameExternal;
1773 this->WriteObjectsVariable(variableName, variableNameExternal);
1776 // MSVC response files cannot exceed 128K.
1777 std::string::size_type const responseFileLimit = 131000;
1779 // Construct the individual object list strings.
1780 std::vector<std::string> object_strings;
1781 this->WriteObjectsStrings(object_strings, responseFileLimit);
1783 // Lookup the response file reference flag.
1784 std::string responseFlagVar = "CMAKE_";
1785 responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
1786 responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
1787 const char* responseFlag =
1788 this->Makefile->GetDefinition(responseFlagVar.c_str());
1794 // Write a response file for each string.
1795 const char* sep = "";
1796 for(unsigned int i = 0; i < object_strings.size(); ++i)
1798 // Number the response files.
1800 sprintf(rsp, "objects%u.rsp", i+1);
1802 // Create this response file.
1803 std::string objects_rsp =
1804 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1806 // Separate from previous response file references.
1810 // Reference the response file.
1811 buildObjs += responseFlag;
1812 buildObjs += this->Convert(objects_rsp.c_str(),
1813 cmLocalGenerator::NONE,
1814 cmLocalGenerator::SHELL);
1817 else if(useLinkScript)
1819 if(!useArchiveRules)
1821 this->WriteObjectsString(buildObjs);
1827 buildObjs += variableName;
1828 buildObjs += ") $(";
1829 buildObjs += variableNameExternal;
1834 //----------------------------------------------------------------------------
1835 void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
1838 std::string responseVar = "CMAKE_";
1839 responseVar += lang;
1840 responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
1841 bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
1844 std::vector<std::string> includes;
1845 this->LocalGenerator->GetIncludeDirectories(includes, this->Target, lang);
1847 std::string includeFlags =
1848 this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile);
1849 if(includeFlags.empty())
1856 std::string name = "includes_";
1859 std::string arg = "@" +
1860 this->CreateResponseFile(name.c_str(), includeFlags,
1861 this->FlagFileDepends[lang]);
1862 this->LocalGenerator->AppendFlags(flags, arg.c_str());
1866 this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
1870 //----------------------------------------------------------------------------
1871 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1873 // Compute the module directory.
1874 if(!this->FortranModuleDirectoryComputed)
1876 const char* target_mod_dir =
1877 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1878 const char* moddir_flag =
1879 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1880 if(target_mod_dir && moddir_flag)
1882 // Compute the full path to the module directory.
1883 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1885 // Already a full path.
1886 this->FortranModuleDirectory = target_mod_dir;
1890 // Interpret relative to the current output directory.
1891 this->FortranModuleDirectory =
1892 this->Makefile->GetCurrentOutputDirectory();
1893 this->FortranModuleDirectory += "/";
1894 this->FortranModuleDirectory += target_mod_dir;
1897 // Make sure the module output directory exists.
1898 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1900 this->FortranModuleDirectoryComputed = true;
1903 // Return the computed directory.
1904 if(this->FortranModuleDirectory.empty())
1910 return this->FortranModuleDirectory.c_str();
1914 //----------------------------------------------------------------------------
1915 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1917 // Enable module output if necessary.
1918 if(const char* modout_flag =
1919 this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG"))
1921 this->LocalGenerator->AppendFlags(flags, modout_flag);
1924 // Add a module output directory flag if necessary.
1925 const char* mod_dir = this->GetFortranModuleDirectory();
1928 mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
1932 const char* moddir_flag =
1933 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1934 std::string modflag = moddir_flag;
1935 modflag += this->Convert(mod_dir,
1936 cmLocalGenerator::START_OUTPUT,
1937 cmLocalGenerator::SHELL);
1938 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1941 // If there is a separate module path flag then duplicate the
1942 // include path with it. This compiler does not search the include
1943 // path for modules.
1944 if(const char* modpath_flag =
1945 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1947 std::vector<std::string> includes;
1948 this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1949 for(std::vector<std::string>::const_iterator idi = includes.begin();
1950 idi != includes.end(); ++idi)
1952 std::string flg = modpath_flag;
1953 flg += this->Convert(idi->c_str(),
1954 cmLocalGenerator::NONE,
1955 cmLocalGenerator::SHELL);
1956 this->LocalGenerator->AppendFlags(flags, flg.c_str());
1961 //----------------------------------------------------------------------------
1962 void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
1964 if(this->GeneratorTarget->ModuleDefinitionFile.empty())
1969 // TODO: Create a per-language flag variable.
1970 const char* defFileFlag =
1971 this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
1977 // Append the flag and value. Use ConvertToLinkReference to help
1978 // vs6's "cl -link" pass it to the linker.
1979 std::string flag = defFileFlag;
1980 flag += (this->LocalGenerator->ConvertToLinkReference(
1981 this->GeneratorTarget->ModuleDefinitionFile.c_str()));
1982 this->LocalGenerator->AppendFlags(flags, flag.c_str());
1985 //----------------------------------------------------------------------------
1986 const char* cmMakefileTargetGenerator::GetFeature(const char* feature)
1988 return this->Target->GetFeature(feature, this->ConfigName);
1991 //----------------------------------------------------------------------------
1992 bool cmMakefileTargetGenerator::GetFeatureAsBool(const char* feature)
1994 return cmSystemTools::IsOn(this->GetFeature(feature));
1997 //----------------------------------------------------------------------------
1998 void cmMakefileTargetGenerator::AddFeatureFlags(
1999 std::string& flags, const char* lang
2002 // Add language-specific flags.
2003 this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
2005 if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
2007 this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");