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 this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target,
277 // Add include directory flags.
278 this->AddIncludeFlags(flags, lang);
280 // Append old-style preprocessor definition flags.
281 this->LocalGenerator->
282 AppendFlags(flags, this->Makefile->GetDefineFlags());
284 // Add include directory flags.
285 this->LocalGenerator->
286 AppendFlags(flags,this->GetFrameworkFlags().c_str());
288 // Add target-specific flags.
289 this->LocalGenerator->AddCompileOptions(flags, this->Target,
290 lang, this->ConfigName);
292 ByLanguageMap::value_type entry(l, flags);
293 i = this->FlagsByLanguage.insert(entry).first;
298 std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
300 ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
301 if (i == this->DefinesByLanguage.end())
303 std::set<std::string> defines;
304 const char *lang = l.c_str();
305 // Add the export symbol definition for shared library objects.
306 if(const char* exportMacro = this->Target->GetExportMacro())
308 this->LocalGenerator->AppendDefines(defines, exportMacro);
311 // Add preprocessor definitions for this target and configuration.
312 this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
313 this->LocalGenerator->ConfigurationName.c_str());
315 std::string definesString;
316 this->LocalGenerator->JoinDefines(defines, definesString, lang);
318 ByLanguageMap::value_type entry(l, definesString);
319 i = this->DefinesByLanguage.insert(entry).first;
324 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
326 // write language flags for target
327 std::set<cmStdString> languages;
328 this->Target->GetLanguages(languages);
329 // put the compiler in the rules.make file so that if it changes
331 for(std::set<cmStdString>::const_iterator l = languages.begin();
332 l != languages.end(); ++l)
334 cmStdString compiler = "CMAKE_";
336 compiler += "_COMPILER";
337 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
338 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
341 for(std::set<cmStdString>::const_iterator l = languages.begin();
342 l != languages.end(); ++l)
344 *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
345 *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
351 //----------------------------------------------------------------------------
353 cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
354 (cmSourceFile& source, const char* pkgloc)
356 // Skip OS X content when not building a Framework or Bundle.
357 if(!this->Generator->GetTarget()->IsBundleOnApple())
363 this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
365 // Get the input file location.
366 std::string input = source.GetFullPath();
368 // Get the output file location.
369 std::string output = macdir;
371 output += cmSystemTools::GetFilenameName(input);
372 this->Generator->CleanFiles.push_back(
373 this->Generator->Convert(output.c_str(),
374 cmLocalGenerator::START_OUTPUT));
375 output = this->Generator->Convert(output.c_str(),
376 cmLocalGenerator::HOME_OUTPUT);
378 // Create a rule to copy the content into the bundle.
379 std::vector<std::string> depends;
380 std::vector<std::string> commands;
381 depends.push_back(input);
382 std::string copyEcho = "Copying OS X content ";
384 this->Generator->LocalGenerator->AppendEcho(
385 commands, copyEcho.c_str(),
386 cmLocalUnixMakefileGenerator3::EchoBuild);
387 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
388 copyCommand += this->Generator->Convert(input.c_str(),
389 cmLocalGenerator::NONE,
390 cmLocalGenerator::SHELL);
392 copyCommand += this->Generator->Convert(output.c_str(),
393 cmLocalGenerator::NONE,
394 cmLocalGenerator::SHELL);
395 commands.push_back(copyCommand);
396 this->Generator->LocalGenerator->WriteMakeRule(
397 *this->Generator->BuildFileStream, 0,
399 depends, commands, false);
400 this->Generator->ExtraFiles.insert(output);
403 //----------------------------------------------------------------------------
404 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
406 // Identify the language of the source file.
407 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
410 // don't know anything about this file so skip it
414 // Get the full path name of the object file.
415 std::string const& objectName = this->GeneratorTarget->Objects[&source];
416 std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
420 // Avoid generating duplicate rules.
421 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
423 this->ObjectFiles.insert(obj);
428 err << "Warning: Source file \""
429 << source.GetFullPath()
430 << "\" is listed multiple times for target \""
431 << this->Target->GetName()
433 cmSystemTools::Message(err.str().c_str(), "Warning");
437 // Create the directory containing the object file. This may be a
438 // subdirectory under the target's directory.
439 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
440 cmSystemTools::MakeDirectory
441 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
443 // Save this in the target's list of object files.
444 this->Objects.push_back(obj);
445 this->CleanFiles.push_back(obj);
448 //std::string relativeObj
449 //= this->LocalGenerator->GetHomeRelativeOutputPath();
450 //relativeObj += obj;
452 // we compute some depends when writing the depend.make that we will also
453 // use in the build.make, same with depMakeFile
454 std::vector<std::string> depends;
455 std::string depMakeFile;
457 // generate the build rule file
458 this->WriteObjectBuildFile(obj, lang, source, depends);
460 // The object file should be checked for dependency integrity.
461 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
465 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
466 std::string srcFullPath =
467 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
468 this->LocalGenerator->
469 AddImplicitDepends(*this->Target, lang,
471 srcFullPath.c_str());
474 //----------------------------------------------------------------------------
476 cmMakefileTargetGenerator
477 ::AppendFortranFormatFlags(std::string& flags, cmSourceFile& source)
479 const char* srcfmt = source.GetProperty("Fortran_FORMAT");
480 cmLocalGenerator::FortranFormat format =
481 this->LocalGenerator->GetFortranFormat(srcfmt);
482 if(format == cmLocalGenerator::FortranFormatNone)
484 const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT");
485 format = this->LocalGenerator->GetFortranFormat(tgtfmt);
490 case cmLocalGenerator::FortranFormatFixed:
491 var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break;
492 case cmLocalGenerator::FortranFormatFree:
493 var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break;
498 this->LocalGenerator->AppendFlags(
499 flags, this->Makefile->GetDefinition(var));
503 //----------------------------------------------------------------------------
505 cmMakefileTargetGenerator
506 ::WriteObjectBuildFile(std::string &obj,
508 cmSourceFile& source,
509 std::vector<std::string>& depends)
511 this->LocalGenerator->AppendRuleDepend(depends,
512 this->FlagFileNameFull.c_str());
513 this->LocalGenerator->AppendRuleDepends(depends,
514 this->FlagFileDepends[lang]);
516 // generate the depend scanning rule
517 this->WriteObjectDependRules(source, depends);
519 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
521 // Write the build rule.
523 // Build the set of compiler flags.
526 // Add language-specific flags.
527 std::string langFlags = "$(";
529 langFlags += "_FLAGS)";
530 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
532 std::string configUpper =
533 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
535 // Add Fortran format flags.
536 if(strcmp(lang, "Fortran") == 0)
538 this->AppendFortranFormatFlags(flags, source);
541 // Add flags from source file properties.
542 if (source.GetProperty("COMPILE_FLAGS"))
544 this->LocalGenerator->AppendFlags
545 (flags, source.GetProperty("COMPILE_FLAGS"));
546 *this->FlagFileStream << "# Custom flags: "
547 << relativeObj << "_FLAGS = "
548 << source.GetProperty("COMPILE_FLAGS")
553 // Add language-specific defines.
554 std::set<std::string> defines;
556 // Add source-sepcific preprocessor definitions.
557 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
559 this->LocalGenerator->AppendDefines(defines, compile_defs);
560 *this->FlagFileStream << "# Custom defines: "
561 << relativeObj << "_DEFINES = "
562 << compile_defs << "\n"
565 std::string defPropName = "COMPILE_DEFINITIONS_";
566 defPropName += configUpper;
567 if(const char* config_compile_defs =
568 source.GetProperty(defPropName.c_str()))
570 this->LocalGenerator->AppendDefines(defines, config_compile_defs);
571 *this->FlagFileStream
572 << "# Custom defines: "
573 << relativeObj << "_DEFINES_" << configUpper
574 << " = " << config_compile_defs << "\n"
578 // Get the output paths for source and object files.
579 std::string sourceFile = source.GetFullPath();
580 if(this->LocalGenerator->UseRelativePaths)
582 sourceFile = this->Convert(sourceFile.c_str(),
583 cmLocalGenerator::START_OUTPUT);
585 sourceFile = this->Convert(sourceFile.c_str(),
586 cmLocalGenerator::NONE,
587 cmLocalGenerator::SHELL);
589 // Construct the build message.
590 std::vector<std::string> no_commands;
591 std::vector<std::string> commands;
593 // add in a progress call if needed
594 this->AppendProgress(commands);
596 if(!this->NoRuleMessages)
598 std::string buildEcho = "Building ";
600 buildEcho += " object ";
601 buildEcho += relativeObj;
602 this->LocalGenerator->AppendEcho
603 (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
606 std::string targetOutPathReal;
607 std::string targetOutPathPDB;
609 std::string targetFullPathReal;
610 std::string targetFullPathPDB;
611 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
612 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
613 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
614 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
617 this->Target->GetFullPath(this->ConfigName, false, true);
618 targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
619 targetFullPathPDB += "/";
620 targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
622 targetOutPathReal = this->Convert(targetFullPathReal.c_str(),
623 cmLocalGenerator::START_OUTPUT,
624 cmLocalGenerator::SHELL);
626 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
627 cmLocalGenerator::SHELL);
629 cmLocalGenerator::RuleVariables vars;
630 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
631 vars.CMTarget = this->Target;
632 vars.Language = lang;
633 vars.Target = targetOutPathReal.c_str();
634 vars.TargetPDB = targetOutPathPDB.c_str();
635 vars.Source = sourceFile.c_str();
636 std::string shellObj =
637 this->Convert(obj.c_str(),
638 cmLocalGenerator::NONE,
639 cmLocalGenerator::SHELL).c_str();
640 vars.Object = shellObj.c_str();
641 std::string objectDir = this->Target->GetSupportDirectory();
642 objectDir = this->Convert(objectDir.c_str(),
643 cmLocalGenerator::START_OUTPUT,
644 cmLocalGenerator::SHELL);
645 vars.ObjectDir = objectDir.c_str();
646 vars.Flags = flags.c_str();
648 std::string definesString = "$(";
649 definesString += lang;
650 definesString += "_DEFINES)";
652 this->LocalGenerator->JoinDefines(defines, definesString, lang);
654 vars.Defines = definesString.c_str();
656 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
657 (strcmp(lang, "CXX") == 0));
659 // Construct the compile rules.
661 std::string compileRuleVar = "CMAKE_";
662 compileRuleVar += lang;
663 compileRuleVar += "_COMPILE_OBJECT";
664 std::string compileRule =
665 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
666 std::vector<std::string> compileCommands;
667 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
669 if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
670 lang_is_c_or_cxx && compileCommands.size() == 1)
672 std::string compileCommand = compileCommands[0];
673 this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
674 std::string workingDirectory =
675 this->LocalGenerator->Convert(
676 this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
677 compileCommand.replace(compileCommand.find(langFlags),
678 langFlags.size(), this->GetFlags(lang));
679 std::string langDefines = std::string("$(") + lang + "_DEFINES)";
680 compileCommand.replace(compileCommand.find(langDefines),
681 langDefines.size(), this->GetDefines(lang));
682 this->GlobalGenerator->AddCXXCompileCommand(
683 source.GetFullPath(), workingDirectory, compileCommand);
686 // Expand placeholders in the commands.
687 for(std::vector<std::string>::iterator i = compileCommands.begin();
688 i != compileCommands.end(); ++i)
690 this->LocalGenerator->ExpandRuleVariables(*i, vars);
693 // Change the command working directory to the local build tree.
694 this->LocalGenerator->CreateCDCommand
696 this->Makefile->GetStartOutputDirectory(),
697 cmLocalGenerator::HOME_OUTPUT);
698 commands.insert(commands.end(),
699 compileCommands.begin(), compileCommands.end());
703 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
705 depends, commands, false);
707 // Check for extra outputs created by the compilation.
708 if(const char* extra_outputs_str =
709 source.GetProperty("OBJECT_OUTPUTS"))
711 std::vector<std::string> extra_outputs;
712 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
713 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
714 eoi != extra_outputs.end(); ++eoi)
716 // Register this as an extra output for the object file rule.
717 // This will cause the object file to be rebuilt if the extra
718 // output is missing.
719 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
721 // Register this as an extra file to clean.
722 this->CleanFiles.push_back(eoi->c_str());
726 bool do_preprocess_rules = lang_is_c_or_cxx &&
727 this->LocalGenerator->GetCreatePreprocessedSourceRules();
728 bool do_assembly_rules = lang_is_c_or_cxx &&
729 this->LocalGenerator->GetCreateAssemblySourceRules();
730 if(do_preprocess_rules || do_assembly_rules)
732 std::vector<std::string> force_depends;
733 force_depends.push_back("cmake_force");
734 std::string::size_type dot_pos = relativeObj.rfind(".");
735 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
736 dot_pos = obj.rfind(".");
737 std::string objBase = obj.substr(0, dot_pos);
739 if(do_preprocess_rules)
742 std::string relativeObjI = relativeObjBase + ".i";
743 std::string objI = objBase + ".i";
745 std::string preprocessEcho = "Preprocessing ";
746 preprocessEcho += lang;
747 preprocessEcho += " source to ";
748 preprocessEcho += objI;
749 this->LocalGenerator->AppendEcho(
750 commands, preprocessEcho.c_str(),
751 cmLocalUnixMakefileGenerator3::EchoBuild
754 std::string preprocessRuleVar = "CMAKE_";
755 preprocessRuleVar += lang;
756 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
757 if(const char* preprocessRule =
758 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
760 std::vector<std::string> preprocessCommands;
761 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
763 std::string shellObjI =
764 this->Convert(objI.c_str(),
765 cmLocalGenerator::NONE,
766 cmLocalGenerator::SHELL).c_str();
767 vars.PreprocessedSource = shellObjI.c_str();
769 // Expand placeholders in the commands.
770 for(std::vector<std::string>::iterator i = preprocessCommands.begin();
771 i != preprocessCommands.end(); ++i)
773 this->LocalGenerator->ExpandRuleVariables(*i, vars);
776 this->LocalGenerator->CreateCDCommand
778 this->Makefile->GetStartOutputDirectory(),
779 cmLocalGenerator::HOME_OUTPUT);
780 commands.insert(commands.end(),
781 preprocessCommands.begin(),
782 preprocessCommands.end());
786 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
787 cmd += preprocessRuleVar;
788 commands.push_back(cmd);
791 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
792 relativeObjI.c_str(),
793 force_depends, commands, false);
796 if(do_assembly_rules)
799 std::string relativeObjS = relativeObjBase + ".s";
800 std::string objS = objBase + ".s";
802 std::string assemblyEcho = "Compiling ";
803 assemblyEcho += lang;
804 assemblyEcho += " source to assembly ";
805 assemblyEcho += objS;
806 this->LocalGenerator->AppendEcho(
807 commands, assemblyEcho.c_str(),
808 cmLocalUnixMakefileGenerator3::EchoBuild
811 std::string assemblyRuleVar = "CMAKE_";
812 assemblyRuleVar += lang;
813 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
814 if(const char* assemblyRule =
815 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
817 std::vector<std::string> assemblyCommands;
818 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
820 std::string shellObjS =
821 this->Convert(objS.c_str(),
822 cmLocalGenerator::NONE,
823 cmLocalGenerator::SHELL).c_str();
824 vars.AssemblySource = shellObjS.c_str();
826 // Expand placeholders in the commands.
827 for(std::vector<std::string>::iterator i = assemblyCommands.begin();
828 i != assemblyCommands.end(); ++i)
830 this->LocalGenerator->ExpandRuleVariables(*i, vars);
833 this->LocalGenerator->CreateCDCommand
835 this->Makefile->GetStartOutputDirectory(),
836 cmLocalGenerator::HOME_OUTPUT);
837 commands.insert(commands.end(),
838 assemblyCommands.begin(),
839 assemblyCommands.end());
843 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
844 cmd += assemblyRuleVar;
845 commands.push_back(cmd);
848 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
849 relativeObjS.c_str(),
850 force_depends, commands, false);
854 // If the language needs provides-requires mode, create the
855 // corresponding targets.
856 std::string objectRequires = relativeObj;
857 objectRequires += ".requires";
858 std::vector<std::string> p_depends;
859 // always provide an empty requires target
860 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
861 objectRequires.c_str(), p_depends,
864 // write a build rule to recursively build what this obj provides
865 std::string objectProvides = relativeObj;
866 objectProvides += ".provides";
867 std::string temp = relativeObj;
868 temp += ".provides.build";
869 std::vector<std::string> r_commands;
870 std::string tgtMakefileName =
871 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
872 tgtMakefileName += "/build.make";
874 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
878 p_depends.push_back(objectRequires);
879 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
880 objectProvides.c_str(), p_depends,
883 // write the provides.build rule dependency on the obj file
885 p_depends.push_back(relativeObj);
886 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
887 temp.c_str(), p_depends, no_commands,
891 //----------------------------------------------------------------------------
892 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
894 std::vector<std::string> depends;
895 std::vector<std::string> no_commands;
897 // Construct the name of the dependency generation target.
898 std::string depTarget =
899 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
900 depTarget += "/requires";
902 // This target drives dependency generation for all object files.
903 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
904 std::string objTarget;
905 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
906 obj != this->Objects.end(); ++obj)
910 objTarget += ".requires";
911 depends.push_back(objTarget);
915 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
917 depends, no_commands, true);
920 //----------------------------------------------------------------------------
921 void cmMakefileTargetGenerator::WriteTargetCleanRules()
923 std::vector<std::string> depends;
924 std::vector<std::string> commands;
926 // Construct the clean target name.
927 std::string cleanTarget =
928 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
929 cleanTarget += "/clean";
931 // Construct the clean command.
932 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
934 this->LocalGenerator->CreateCDCommand
936 this->Makefile->GetStartOutputDirectory(),
937 cmLocalGenerator::HOME_OUTPUT);
940 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
942 depends, commands, true);
946 //----------------------------------------------------------------------------
947 void cmMakefileTargetGenerator::WriteTargetDependRules()
949 // must write the targets depend info file
950 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
951 this->InfoFileNameFull = dir;
952 this->InfoFileNameFull += "/DependInfo.cmake";
953 this->InfoFileNameFull =
954 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
955 this->InfoFileStream =
956 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
957 this->InfoFileStream->SetCopyIfDifferent(true);
958 if(!*this->InfoFileStream)
962 this->LocalGenerator->
963 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
965 // Store multiple output pairs in the depend info file.
966 if(!this->MultipleOutputPairs.empty())
968 *this->InfoFileStream
970 << "# Pairs of files generated by the same build rule.\n"
971 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
972 for(MultipleOutputPairsType::const_iterator pi =
973 this->MultipleOutputPairs.begin();
974 pi != this->MultipleOutputPairs.end(); ++pi)
976 *this->InfoFileStream
977 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
978 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
981 *this->InfoFileStream << " )\n\n";
984 // Store list of targets linked directly or transitively.
986 *this->InfoFileStream
988 << "# Targets to which this target links.\n"
989 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
990 std::set<cmTarget const*> emitted;
991 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
992 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
994 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
995 for(cmComputeLinkInformation::ItemVector::const_iterator
996 i = items.begin(); i != items.end(); ++i)
998 cmTarget const* linkee = i->Target;
999 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
1001 cmMakefile* mf = linkee->GetMakefile();
1002 cmLocalGenerator* lg = mf->GetLocalGenerator();
1003 std::string di = mf->GetStartOutputDirectory();
1005 di += lg->GetTargetDirectory(*linkee);
1006 di += "/DependInfo.cmake";
1007 *this->InfoFileStream << " \"" << di << "\"\n";
1011 *this->InfoFileStream
1015 // Check for a target-specific module output directory.
1016 if(const char* mdir = this->GetFortranModuleDirectory())
1018 *this->InfoFileStream
1020 << "# Fortran module output directory.\n"
1021 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
1024 // Target-specific include directories:
1025 *this->InfoFileStream
1027 << "# The include file search paths:\n";
1028 *this->InfoFileStream
1029 << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
1030 std::vector<std::string> includes;
1032 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1033 this->LocalGenerator->GetIncludeDirectories(includes,
1034 this->GeneratorTarget,
1036 for(std::vector<std::string>::iterator i = includes.begin();
1037 i != includes.end(); ++i)
1039 *this->InfoFileStream
1041 << this->LocalGenerator->Convert(i->c_str(),
1042 cmLocalGenerator::HOME_OUTPUT)
1045 *this->InfoFileStream
1047 *this->InfoFileStream
1048 << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
1049 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1050 *this->InfoFileStream
1051 << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
1052 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1053 *this->InfoFileStream
1054 << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
1055 << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1057 // and now write the rule to use it
1058 std::vector<std::string> depends;
1059 std::vector<std::string> commands;
1061 // Construct the name of the dependency generation target.
1062 std::string depTarget =
1063 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1064 depTarget += "/depend";
1066 // Add a command to call CMake to scan dependencies. CMake will
1067 // touch the corresponding depends file after scanning dependencies.
1068 cmOStringStream depCmd;
1069 // TODO: Account for source file properties and directory-level
1070 // definitions when scanning for dependencies.
1071 #if !defined(_WIN32) || defined(__CYGWIN__)
1072 // This platform supports symlinks, so cmSystemTools will translate
1073 // paths. Make sure PWD is set to the original name of the home
1074 // output directory to help cmSystemTools to create the same
1075 // translation table for the dependency scanning process.
1077 << (this->LocalGenerator->Convert(
1078 this->Makefile->GetHomeOutputDirectory(),
1079 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1082 // Generate a call this signature:
1084 // cmake -E cmake_depends <generator>
1085 // <home-src-dir> <start-src-dir>
1086 // <home-out-dir> <start-out-dir>
1087 // <dep-info> --color=$(COLOR)
1089 // This gives the dependency scanner enough information to recreate
1090 // the state of our local generator sufficiently for its needs.
1091 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1092 << this->GlobalGenerator->GetName() << "\" "
1093 << this->Convert(this->Makefile->GetHomeDirectory(),
1094 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1096 << this->Convert(this->Makefile->GetStartDirectory(),
1097 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1099 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1100 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1102 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1103 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1105 << this->Convert(this->InfoFileNameFull.c_str(),
1106 cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1107 if(this->LocalGenerator->GetColorMakefile())
1109 depCmd << " --color=$(COLOR)";
1111 commands.push_back(depCmd.str());
1113 // Make sure all custom command outputs in this target are built.
1114 if(this->CustomCommandDriver == OnDepends)
1116 this->DriveCustomCommands(depends);
1120 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1122 depends, commands, true);
1125 //----------------------------------------------------------------------------
1127 cmMakefileTargetGenerator
1128 ::DriveCustomCommands(std::vector<std::string>& depends)
1130 // Depend on all custom command outputs.
1131 const std::vector<cmSourceFile*>& sources =
1132 this->Target->GetSourceFiles();
1133 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1134 source != sources.end(); ++source)
1136 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1138 const std::vector<std::string>& outputs = cc->GetOutputs();
1139 for(std::vector<std::string>::const_iterator o = outputs.begin();
1140 o != outputs.end(); ++o)
1142 depends.push_back(*o);
1148 //----------------------------------------------------------------------------
1149 void cmMakefileTargetGenerator
1150 ::WriteObjectDependRules(cmSourceFile& source,
1151 std::vector<std::string>& depends)
1153 // Create the list of dependencies known at cmake time. These are
1154 // shared between the object file and dependency scanning rule.
1155 depends.push_back(source.GetFullPath());
1156 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1158 std::vector<std::string> deps;
1159 cmSystemTools::ExpandListArgument(objectDeps, deps);
1160 for(std::vector<std::string>::iterator i = deps.begin();
1161 i != deps.end(); ++i)
1163 depends.push_back(i->c_str());
1168 //----------------------------------------------------------------------------
1169 void cmMakefileTargetGenerator
1170 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1172 // Collect the commands.
1173 std::vector<std::string> commands;
1174 std::string comment = this->LocalGenerator->ConstructComment(cc);
1175 if(!comment.empty())
1177 // add in a progress call if needed
1178 this->AppendProgress(commands);
1179 if(!this->NoRuleMessages)
1181 this->LocalGenerator
1182 ->AppendEcho(commands, comment.c_str(),
1183 cmLocalUnixMakefileGenerator3::EchoGenerate);
1187 // Now append the actual user-specified commands.
1188 cmOStringStream content;
1189 this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1190 cmLocalGenerator::HOME_OUTPUT,
1193 // Collect the dependencies.
1194 std::vector<std::string> depends;
1195 this->LocalGenerator->AppendCustomDepend(depends, cc);
1197 // Check whether we need to bother checking for a symbolic output.
1198 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1201 const std::vector<std::string>& outputs = cc.GetOutputs();
1202 std::vector<std::string>::const_iterator o = outputs.begin();
1204 bool symbolic = false;
1207 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1209 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1212 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1213 o->c_str(), depends, commands,
1216 // If the rule has changed make sure the output is rebuilt.
1219 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1223 // Write rules to drive building any outputs beyond the first.
1224 const char* in = o->c_str();
1225 for(++o; o != outputs.end(); ++o)
1227 bool symbolic = false;
1230 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1232 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1235 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1238 // Setup implicit dependency scanning.
1239 for(cmCustomCommand::ImplicitDependsList::const_iterator
1240 idi = cc.GetImplicitDepends().begin();
1241 idi != cc.GetImplicitDepends().end(); ++idi)
1243 std::string objFullPath =
1244 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1245 std::string srcFullPath =
1246 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1247 this->LocalGenerator->
1248 AddImplicitDepends(*this->Target, idi->first.c_str(),
1249 objFullPath.c_str(),
1250 srcFullPath.c_str());
1254 //----------------------------------------------------------------------------
1256 cmMakefileTargetGenerator
1257 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1259 // Add a rule to build the primary output if the extra output needs
1261 std::vector<std::string> commands;
1262 std::vector<std::string> depends;
1263 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1264 if(!emptyCommand.empty())
1266 commands.push_back(emptyCommand);
1268 depends.push_back(in);
1269 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1270 out, depends, commands,
1273 // Register the extra output as paired with the first output so that
1274 // the check-build-system step will remove the primary output if any
1275 // extra outputs are missing. This forces the rule to regenerate
1277 this->AddMultipleOutputPair(out, in);
1280 //----------------------------------------------------------------------------
1282 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1284 this->NumberOfProgressActions++;
1285 if(this->NoRuleMessages)
1289 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1290 progressDir += cmake::GetCMakeFilesDirectory();
1291 cmOStringStream progCmd;
1292 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1293 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1294 cmLocalGenerator::FULL,
1295 cmLocalGenerator::SHELL);
1296 progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1297 commands.push_back(progCmd.str());
1300 //----------------------------------------------------------------------------
1302 cmMakefileTargetGenerator
1303 ::WriteObjectsVariable(std::string& variableName,
1304 std::string& variableNameExternal)
1306 // Write a make variable assignment that lists all objects for the
1309 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1311 *this->BuildFileStream
1312 << "# Object files for target " << this->Target->GetName() << "\n"
1313 << variableName.c_str() << " =";
1315 const char* objName =
1316 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1317 const char* lineContinue =
1318 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1321 lineContinue = "\\";
1323 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1324 i != this->Objects.end(); ++i)
1326 *this->BuildFileStream << " " << lineContinue << "\n";
1329 *this->BuildFileStream <<
1330 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1331 cmLocalGenerator::MAKEFILE);
1335 *this->BuildFileStream <<
1336 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1339 *this->BuildFileStream << "\n";
1341 // Write a make variable assignment that lists all external objects
1343 variableNameExternal =
1344 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1345 "_EXTERNAL_OBJECTS");
1346 *this->BuildFileStream
1348 << "# External object files for target "
1349 << this->Target->GetName() << "\n"
1350 << variableNameExternal.c_str() << " =";
1351 for(std::vector<std::string>::const_iterator i =
1352 this->ExternalObjects.begin();
1353 i != this->ExternalObjects.end(); ++i)
1355 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1356 *this->BuildFileStream
1357 << " " << lineContinue << "\n"
1358 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1361 *this->BuildFileStream <<
1362 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1363 cmLocalGenerator::MAKEFILE);
1367 *this->BuildFileStream <<
1368 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1371 *this->BuildFileStream << "\n" << "\n";
1374 //----------------------------------------------------------------------------
1376 cmMakefileTargetGenerator
1377 ::WriteObjectsString(std::string& buildObjs)
1379 std::vector<std::string> objStrings;
1380 this->WriteObjectsStrings(objStrings);
1381 buildObjs = objStrings[0];
1384 //----------------------------------------------------------------------------
1385 class cmMakefileTargetGeneratorObjectStrings
1388 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1389 cmLocalUnixMakefileGenerator3* lg,
1390 std::string::size_type limit):
1391 Strings(strings), LocalGenerator(lg), LengthLimit(limit)
1395 void Feed(std::string const& obj)
1397 // Construct the name of the next object.
1399 this->LocalGenerator->Convert(obj.c_str(),
1400 cmLocalGenerator::START_OUTPUT,
1401 cmLocalGenerator::RESPONSE);
1403 // Roll over to next string if the limit will be exceeded.
1404 if(this->LengthLimit != std::string::npos &&
1405 (this->CurrentString.length() + 1 + this->NextObject.length()
1406 > this->LengthLimit))
1408 this->Strings.push_back(this->CurrentString);
1409 this->CurrentString = "";
1413 // Separate from previous object.
1414 this->CurrentString += this->Space;
1417 // Append this object.
1418 this->CurrentString += this->NextObject;
1422 this->Strings.push_back(this->CurrentString);
1425 std::vector<std::string>& Strings;
1426 cmLocalUnixMakefileGenerator3* LocalGenerator;
1427 std::string::size_type LengthLimit;
1428 std::string CurrentString;
1429 std::string NextObject;
1433 //----------------------------------------------------------------------------
1435 cmMakefileTargetGenerator
1436 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1437 std::string::size_type limit)
1439 cmMakefileTargetGeneratorObjectStrings
1440 helper(objStrings, this->LocalGenerator, limit);
1441 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1442 i != this->Objects.end(); ++i)
1446 for(std::vector<std::string>::const_iterator i =
1447 this->ExternalObjects.begin();
1448 i != this->ExternalObjects.end(); ++i)
1455 //----------------------------------------------------------------------------
1456 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1459 // Compute the name of the driver target.
1461 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1462 std::string buildTargetRuleName = dir;
1463 buildTargetRuleName += relink?"/preinstall":"/build";
1464 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1465 cmLocalGenerator::HOME_OUTPUT,
1466 cmLocalGenerator::UNCHANGED);
1468 // Build the list of target outputs to drive.
1469 std::vector<std::string> depends;
1472 depends.push_back(main_output);
1475 const char* comment = 0;
1478 // Setup the comment for the preinstall driver.
1479 comment = "Rule to relink during preinstall.";
1483 // Setup the comment for the main build driver.
1484 comment = "Rule to build all files generated by this target.";
1486 // Make sure all custom command outputs in this target are built.
1487 if(this->CustomCommandDriver == OnBuild)
1489 this->DriveCustomCommands(depends);
1492 // Make sure the extra files are built.
1493 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1494 i != this->ExtraFiles.end(); ++i)
1496 depends.push_back(*i);
1500 // Write the driver rule.
1501 std::vector<std::string> no_commands;
1502 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1503 buildTargetRuleName.c_str(),
1504 depends, no_commands, true);
1507 //----------------------------------------------------------------------------
1508 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1510 if(!this->Makefile->IsOn("APPLE"))
1512 return std::string();
1515 std::set<cmStdString> emitted;
1516 #ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */
1517 emitted.insert("/System/Library/Frameworks");
1519 std::vector<std::string> includes;
1521 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1522 this->LocalGenerator->GetIncludeDirectories(includes,
1523 this->GeneratorTarget,
1525 // check all include directories for frameworks as this
1526 // will already have added a -F for the framework
1527 for(std::vector<std::string>::iterator i = includes.begin();
1528 i != includes.end(); ++i)
1530 if(this->Target->NameResolvesToFramework(i->c_str()))
1532 std::string frameworkDir = *i;
1533 frameworkDir += "/../";
1534 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1535 emitted.insert(frameworkDir);
1540 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1541 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1543 std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
1544 for(std::vector<std::string>::const_iterator i = frameworks.begin();
1545 i != frameworks.end(); ++i)
1547 if(emitted.insert(*i).second)
1550 flags += this->Convert(i->c_str(),
1551 cmLocalGenerator::START_OUTPUT,
1552 cmLocalGenerator::SHELL, true);
1560 //----------------------------------------------------------------------------
1561 void cmMakefileTargetGenerator
1562 ::AppendTargetDepends(std::vector<std::string>& depends)
1564 // Static libraries never depend on anything for linking.
1565 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1570 // Loop over all library dependencies.
1571 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1572 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1574 std::vector<std::string> const& libDeps = cli->GetDepends();
1575 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1576 j != libDeps.end(); ++j)
1578 depends.push_back(*j);
1583 //----------------------------------------------------------------------------
1584 void cmMakefileTargetGenerator
1585 ::AppendObjectDepends(std::vector<std::string>& depends)
1587 // Add dependencies on the compiled object files.
1588 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
1589 std::string objTarget;
1590 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
1591 obj != this->Objects.end(); ++obj)
1593 objTarget = relPath;
1595 depends.push_back(objTarget);
1598 // Add dependencies on the external object files.
1599 for(std::vector<std::string>::const_iterator obj
1600 = this->ExternalObjects.begin();
1601 obj != this->ExternalObjects.end(); ++obj)
1603 depends.push_back(*obj);
1606 // Add a dependency on the rule file itself.
1607 this->LocalGenerator->AppendRuleDepend(depends,
1608 this->BuildFileNameFull.c_str());
1611 //----------------------------------------------------------------------------
1612 void cmMakefileTargetGenerator
1613 ::AppendLinkDepends(std::vector<std::string>& depends)
1615 this->AppendObjectDepends(depends);
1617 // Add dependencies on targets that must be built first.
1618 this->AppendTargetDepends(depends);
1620 // Add a dependency on the link definitions file, if any.
1621 if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
1623 depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
1626 // Add user-specified dependencies.
1627 if(const char* linkDepends =
1628 this->Target->GetProperty("LINK_DEPENDS"))
1630 cmSystemTools::ExpandListArgument(linkDepends, depends);
1634 //----------------------------------------------------------------------------
1635 std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
1637 std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
1638 if(this->Target->HasImplibGNUtoMS())
1640 std::string ruleVar = "CMAKE_";
1641 ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
1642 ruleVar += "_GNUtoMS_RULE";
1643 if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
1651 //----------------------------------------------------------------------------
1652 void cmMakefileTargetGenerator
1653 ::CloseFileStreams()
1655 delete this->BuildFileStream;
1656 delete this->InfoFileStream;
1657 delete this->FlagFileStream;
1660 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1661 const char* linkLang,
1662 std::string& linkFlags)
1664 // check for language flags that are not allowed at link time, and
1665 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1666 // which fails, there may be more]
1668 std::string removeFlags = "CMAKE_";
1669 removeFlags += linkLang;
1670 removeFlags += flagVar;
1671 std::string removeflags =
1672 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1673 std::vector<std::string> removeList;
1674 cmSystemTools::ExpandListArgument(removeflags, removeList);
1675 for(std::vector<std::string>::iterator i = removeList.begin();
1676 i != removeList.end(); ++i)
1678 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1682 //----------------------------------------------------------------------------
1684 cmMakefileTargetGenerator
1685 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1687 MultipleOutputPairsType::value_type p(depender, dependee);
1688 this->MultipleOutputPairs.insert(p);
1691 //----------------------------------------------------------------------------
1693 cmMakefileTargetGenerator
1694 ::CreateLinkScript(const char* name,
1695 std::vector<std::string> const& link_commands,
1696 std::vector<std::string>& makefile_commands,
1697 std::vector<std::string>& makefile_depends)
1699 // Create the link script file.
1700 std::string linkScriptName = this->TargetBuildDirectoryFull;
1701 linkScriptName += "/";
1702 linkScriptName += name;
1703 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1704 linkScriptStream.SetCopyIfDifferent(true);
1705 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1706 cmd != link_commands.end(); ++cmd)
1708 // Do not write out empty commands or commands beginning in the
1710 if(!cmd->empty() && (*cmd)[0] != ':')
1712 linkScriptStream << *cmd << "\n";
1716 // Create the makefile command to invoke the link script.
1717 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1718 link_command += this->Convert(linkScriptName.c_str(),
1719 cmLocalGenerator::START_OUTPUT,
1720 cmLocalGenerator::SHELL);
1721 link_command += " --verbose=$(VERBOSE)";
1722 makefile_commands.push_back(link_command);
1723 makefile_depends.push_back(linkScriptName);
1726 //----------------------------------------------------------------------------
1728 cmMakefileTargetGenerator
1729 ::CreateResponseFile(const char* name, std::string const& options,
1730 std::vector<std::string>& makefile_depends)
1732 // Create the response file.
1733 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1734 responseFileNameFull += "/";
1735 responseFileNameFull += name;
1736 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1737 responseStream.SetCopyIfDifferent(true);
1738 responseStream << options << "\n";
1740 // Add a dependency so the target will rebuild when the set of
1742 makefile_depends.push_back(responseFileNameFull);
1744 // Construct the name to be used on the command line.
1745 std::string responseFileName = this->TargetBuildDirectory;
1746 responseFileName += "/";
1747 responseFileName += name;
1748 return responseFileName;
1751 //----------------------------------------------------------------------------
1753 cmMakefileTargetGenerator
1754 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1755 bool useResponseFile, std::string& buildObjs,
1756 std::vector<std::string>& makefile_depends)
1758 std::string variableName;
1759 std::string variableNameExternal;
1760 this->WriteObjectsVariable(variableName, variableNameExternal);
1763 // MSVC response files cannot exceed 128K.
1764 std::string::size_type const responseFileLimit = 131000;
1766 // Construct the individual object list strings.
1767 std::vector<std::string> object_strings;
1768 this->WriteObjectsStrings(object_strings, responseFileLimit);
1770 // Lookup the response file reference flag.
1771 std::string responseFlagVar = "CMAKE_";
1772 responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
1773 responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
1774 const char* responseFlag =
1775 this->Makefile->GetDefinition(responseFlagVar.c_str());
1781 // Write a response file for each string.
1782 const char* sep = "";
1783 for(unsigned int i = 0; i < object_strings.size(); ++i)
1785 // Number the response files.
1787 sprintf(rsp, "objects%u.rsp", i+1);
1789 // Create this response file.
1790 std::string objects_rsp =
1791 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1793 // Separate from previous response file references.
1797 // Reference the response file.
1798 buildObjs += responseFlag;
1799 buildObjs += this->Convert(objects_rsp.c_str(),
1800 cmLocalGenerator::NONE,
1801 cmLocalGenerator::SHELL);
1804 else if(useLinkScript)
1806 if(!useArchiveRules)
1808 this->WriteObjectsString(buildObjs);
1814 buildObjs += variableName;
1815 buildObjs += ") $(";
1816 buildObjs += variableNameExternal;
1821 //----------------------------------------------------------------------------
1822 void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
1825 std::string responseVar = "CMAKE_";
1826 responseVar += lang;
1827 responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
1828 bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
1831 std::vector<std::string> includes;
1832 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1833 this->LocalGenerator->GetIncludeDirectories(includes,
1834 this->GeneratorTarget,
1837 std::string includeFlags =
1838 this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget,
1839 lang, useResponseFile);
1840 if(includeFlags.empty())
1847 std::string name = "includes_";
1850 std::string arg = "@" +
1851 this->CreateResponseFile(name.c_str(), includeFlags,
1852 this->FlagFileDepends[lang]);
1853 this->LocalGenerator->AppendFlags(flags, arg.c_str());
1857 this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
1861 //----------------------------------------------------------------------------
1862 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1864 // Compute the module directory.
1865 if(!this->FortranModuleDirectoryComputed)
1867 const char* target_mod_dir =
1868 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1869 const char* moddir_flag =
1870 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1871 if(target_mod_dir && moddir_flag)
1873 // Compute the full path to the module directory.
1874 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1876 // Already a full path.
1877 this->FortranModuleDirectory = target_mod_dir;
1881 // Interpret relative to the current output directory.
1882 this->FortranModuleDirectory =
1883 this->Makefile->GetCurrentOutputDirectory();
1884 this->FortranModuleDirectory += "/";
1885 this->FortranModuleDirectory += target_mod_dir;
1888 // Make sure the module output directory exists.
1889 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1891 this->FortranModuleDirectoryComputed = true;
1894 // Return the computed directory.
1895 if(this->FortranModuleDirectory.empty())
1901 return this->FortranModuleDirectory.c_str();
1905 //----------------------------------------------------------------------------
1906 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1908 // Enable module output if necessary.
1909 if(const char* modout_flag =
1910 this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG"))
1912 this->LocalGenerator->AppendFlags(flags, modout_flag);
1915 // Add a module output directory flag if necessary.
1916 const char* mod_dir = this->GetFortranModuleDirectory();
1919 mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
1923 const char* moddir_flag =
1924 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1925 std::string modflag = moddir_flag;
1926 modflag += this->Convert(mod_dir,
1927 cmLocalGenerator::START_OUTPUT,
1928 cmLocalGenerator::SHELL);
1929 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1932 // If there is a separate module path flag then duplicate the
1933 // include path with it. This compiler does not search the include
1934 // path for modules.
1935 if(const char* modpath_flag =
1936 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1938 std::vector<std::string> includes;
1939 const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1940 this->LocalGenerator->GetIncludeDirectories(includes,
1941 this->GeneratorTarget,
1943 for(std::vector<std::string>::const_iterator idi = includes.begin();
1944 idi != includes.end(); ++idi)
1946 std::string flg = modpath_flag;
1947 flg += this->Convert(idi->c_str(),
1948 cmLocalGenerator::NONE,
1949 cmLocalGenerator::SHELL);
1950 this->LocalGenerator->AppendFlags(flags, flg.c_str());
1955 //----------------------------------------------------------------------------
1956 void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
1958 if(this->GeneratorTarget->ModuleDefinitionFile.empty())
1963 // TODO: Create a per-language flag variable.
1964 const char* defFileFlag =
1965 this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
1971 // Append the flag and value. Use ConvertToLinkReference to help
1972 // vs6's "cl -link" pass it to the linker.
1973 std::string flag = defFileFlag;
1974 flag += (this->LocalGenerator->ConvertToLinkReference(
1975 this->GeneratorTarget->ModuleDefinitionFile.c_str()));
1976 this->LocalGenerator->AppendFlags(flags, flag.c_str());
1979 //----------------------------------------------------------------------------
1980 const char* cmMakefileTargetGenerator::GetFeature(const char* feature)
1982 return this->Target->GetFeature(feature, this->ConfigName);
1985 //----------------------------------------------------------------------------
1986 bool cmMakefileTargetGenerator::GetFeatureAsBool(const char* feature)
1988 return cmSystemTools::IsOn(this->GetFeature(feature));
1991 //----------------------------------------------------------------------------
1992 void cmMakefileTargetGenerator::AddFeatureFlags(
1993 std::string& flags, const char* lang
1996 // Add language-specific flags.
1997 this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
1999 if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
2001 this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");