Do not call CollapseFullPath for PDB file names
[cmake.git] / Source / cmMakefileTargetGenerator.cxx
blobe3d9bbc3eebf138238b56987a5d38d125f03020d
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-09-17 12:42:31 $
7 Version: $Revision: 1.122 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmMakefileTargetGenerator.h"
19 #include "cmGeneratedFileStream.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmGlobalUnixMakefileGenerator3.h"
22 #include "cmLocalUnixMakefileGenerator3.h"
23 #include "cmMakefile.h"
24 #include "cmSourceFile.h"
25 #include "cmTarget.h"
26 #include "cmake.h"
27 #include "cmComputeLinkInformation.h"
29 #include "cmMakefileExecutableTargetGenerator.h"
30 #include "cmMakefileLibraryTargetGenerator.h"
31 #include "cmMakefileUtilityTargetGenerator.h"
34 cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target)
36 this->BuildFileStream = 0;
37 this->InfoFileStream = 0;
38 this->FlagFileStream = 0;
39 this->CustomCommandDriver = OnBuild;
40 this->FortranModuleDirectoryComputed = false;
41 this->Target = target;
42 this->Makefile = this->Target->GetMakefile();
43 this->LocalGenerator =
44 static_cast<cmLocalUnixMakefileGenerator3*>(
45 this->Makefile->GetLocalGenerator());
46 this->ConfigName = this->LocalGenerator->ConfigurationName.c_str();
47 this->GlobalGenerator =
48 static_cast<cmGlobalUnixMakefileGenerator3*>(
49 this->LocalGenerator->GetGlobalGenerator());
50 cmake* cm = this->GlobalGenerator->GetCMakeInstance();
51 this->NoRuleMessages = false;
52 if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES"))
54 this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus);
58 cmMakefileTargetGenerator *
59 cmMakefileTargetGenerator::New(cmTarget *tgt)
61 cmMakefileTargetGenerator *result = 0;
63 switch (tgt->GetType())
65 case cmTarget::EXECUTABLE:
66 result = new cmMakefileExecutableTargetGenerator(tgt);
67 break;
68 case cmTarget::STATIC_LIBRARY:
69 case cmTarget::SHARED_LIBRARY:
70 case cmTarget::MODULE_LIBRARY:
71 result = new cmMakefileLibraryTargetGenerator(tgt);
72 break;
73 case cmTarget::UTILITY:
74 result = new cmMakefileUtilityTargetGenerator(tgt);
75 break;
76 default:
77 return result;
78 // break; /* unreachable */
80 return result;
83 //----------------------------------------------------------------------------
84 void cmMakefileTargetGenerator::CreateRuleFile()
86 // Create a directory for this target.
87 this->TargetBuildDirectory =
88 this->LocalGenerator->GetTargetDirectory(*this->Target);
89 this->TargetBuildDirectoryFull =
90 this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
91 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
93 // Construct the rule file name.
94 this->BuildFileName = this->TargetBuildDirectory;
95 this->BuildFileName += "/build.make";
96 this->BuildFileNameFull = this->TargetBuildDirectoryFull;
97 this->BuildFileNameFull += "/build.make";
99 // Construct the rule file name.
100 this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
101 this->ProgressFileNameFull += "/progress.make";
103 // reset the progress count
104 this->NumberOfProgressActions = 0;
106 // Open the rule file. This should be copy-if-different because the
107 // rules may depend on this file itself.
108 this->BuildFileStream =
109 new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
110 this->BuildFileStream->SetCopyIfDifferent(true);
111 if(!this->BuildFileStream)
113 return;
115 this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
116 this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
119 //----------------------------------------------------------------------------
120 void cmMakefileTargetGenerator::WriteTargetBuildRules()
122 // write the custom commands for this target
123 // Look for files registered for cleaning in this directory.
124 if(const char* additional_clean_files =
125 this->Makefile->GetProperty
126 ("ADDITIONAL_MAKE_CLEAN_FILES"))
128 cmSystemTools::ExpandListArgument(additional_clean_files,
129 this->CleanFiles);
132 // add custom commands to the clean rules?
133 const char* clean_no_custom =
134 this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
135 bool clean = cmSystemTools::IsOff(clean_no_custom);
137 // First generate the object rule files. Save a list of all object
138 // files for this target.
139 const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
140 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
141 source != sources.end(); ++source)
143 cmTarget::SourceFileFlags tsFlags =
144 this->Target->GetTargetSourceFileFlags(*source);
145 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
147 this->GenerateCustomRuleFile(*cc);
148 if (clean)
150 const std::vector<std::string>& outputs = cc->GetOutputs();
151 for(std::vector<std::string>::const_iterator o = outputs.begin();
152 o != outputs.end(); ++o)
154 this->CleanFiles.push_back
155 (this->Convert(o->c_str(),
156 cmLocalGenerator::START_OUTPUT,
157 cmLocalGenerator::UNCHANGED));
161 else if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
163 this->WriteMacOSXContentRules(*(*source), tsFlags.MacFolder);
165 else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
167 if(!this->GlobalGenerator->IgnoreFile
168 ((*source)->GetExtension().c_str()))
170 // Generate this object file's rule file.
171 this->WriteObjectRuleFiles(*(*source));
173 else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
175 // This is an external object file. Just add it.
176 this->ExternalObjects.push_back((*source)->GetFullPath());
178 else
180 // We only get here if a source file is not an external object
181 // and has an extension that is listed as an ignored file type
182 // for this language. No message or diagnosis should be
183 // given.
190 //----------------------------------------------------------------------------
191 void cmMakefileTargetGenerator::WriteCommonCodeRules()
193 // Include the dependencies for the target.
194 std::string dependFileNameFull = this->TargetBuildDirectoryFull;
195 dependFileNameFull += "/depend.make";
196 *this->BuildFileStream
197 << "# Include any dependencies generated for this target.\n"
198 << this->LocalGenerator->IncludeDirective << " "
199 << this->Convert(dependFileNameFull.c_str(),
200 cmLocalGenerator::HOME_OUTPUT,
201 cmLocalGenerator::MAKEFILE)
202 << "\n\n";
204 if(!this->NoRuleMessages)
206 // Include the progress variables for the target.
207 *this->BuildFileStream
208 << "# Include the progress variables for this target.\n"
209 << this->LocalGenerator->IncludeDirective << " "
210 << this->Convert(this->ProgressFileNameFull.c_str(),
211 cmLocalGenerator::HOME_OUTPUT,
212 cmLocalGenerator::MAKEFILE)
213 << "\n\n";
216 // make sure the depend file exists
217 if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
219 // Write an empty dependency file.
220 cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
221 depFileStream
222 << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
223 << "# This may be replaced when dependencies are built." << std::endl;
226 // Open the flags file. This should be copy-if-different because the
227 // rules may depend on this file itself.
228 this->FlagFileNameFull = this->TargetBuildDirectoryFull;
229 this->FlagFileNameFull += "/flags.make";
230 this->FlagFileStream =
231 new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
232 this->FlagFileStream->SetCopyIfDifferent(true);
233 if(!this->FlagFileStream)
235 return;
237 this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
239 // Include the flags for the target.
240 *this->BuildFileStream
241 << "# Include the compile flags for this target's objects.\n"
242 << this->LocalGenerator->IncludeDirective << " "
243 << this->Convert(this->FlagFileNameFull.c_str(),
244 cmLocalGenerator::HOME_OUTPUT,
245 cmLocalGenerator::MAKEFILE)
246 << "\n\n";
249 //----------------------------------------------------------------------------
250 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
252 // write language flags for target
253 std::set<cmStdString> languages;
254 this->Target->GetLanguages(languages);
255 // put the compiler in the rules.make file so that if it changes
256 // things rebuild
257 for(std::set<cmStdString>::const_iterator l = languages.begin();
258 l != languages.end(); ++l)
260 cmStdString compiler = "CMAKE_";
261 compiler += *l;
262 compiler += "_COMPILER";
263 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
264 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
267 for(std::set<cmStdString>::const_iterator l = languages.begin();
268 l != languages.end(); ++l)
270 const char *lang = l->c_str();
271 std::string flags;
272 std::string defines;
273 bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
274 (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
276 // Add the export symbol definition for shared library objects.
277 if(const char* exportMacro = this->Target->GetExportMacro())
279 this->LocalGenerator->AppendDefines(defines, exportMacro, lang);
282 // Add preprocessor definitions for this target and configuration.
283 this->LocalGenerator->AppendDefines
284 (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang);
285 this->LocalGenerator->AppendDefines
286 (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang);
287 std::string defPropName = "COMPILE_DEFINITIONS_";
288 defPropName +=
289 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
290 this->LocalGenerator->AppendDefines
291 (defines, this->Makefile->GetProperty(defPropName.c_str()), lang);
292 this->LocalGenerator->AppendDefines
293 (defines, this->Target->GetProperty(defPropName.c_str()), lang);
295 // Add language-specific flags.
296 this->LocalGenerator
297 ->AddLanguageFlags(flags, lang,
298 this->LocalGenerator->ConfigurationName.c_str());
300 // Fortran-specific flags computed for this target.
301 if(*l == "Fortran")
303 this->AddFortranFlags(flags);
306 // Add shared-library flags if needed.
307 this->LocalGenerator->AddSharedFlags(flags, lang, shared);
309 // Add include directory flags.
310 this->LocalGenerator->
311 AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
312 // Add include directory flags.
313 this->LocalGenerator->
314 AppendFlags(flags,this->GetFrameworkFlags().c_str());
316 *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
317 *this->FlagFileStream << lang << "_DEFINES = " << defines << "\n\n";
320 // Add target-specific flags.
321 if(this->Target->GetProperty("COMPILE_FLAGS"))
323 std::string flags;
324 this->LocalGenerator->AppendFlags
325 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
326 *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
330 //----------------------------------------------------------------------------
331 void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source,
332 const char* pkgloc)
334 // Skip OS X content when not building a Framework or Bundle.
335 if(this->MacContentDirectory.empty())
337 return;
340 // Construct the full path to the content subdirectory.
341 std::string macdir = this->MacContentDirectory;
342 macdir += pkgloc;
343 cmSystemTools::MakeDirectory(macdir.c_str());
345 // Record use of this content location. Only the first level
346 // directory is needed.
348 std::string loc = pkgloc;
349 loc = loc.substr(0, loc.find('/'));
350 this->MacContentFolders.insert(loc);
353 // Get the input file location.
354 std::string input = source.GetFullPath();
356 // Get the output file location.
357 std::string output = macdir;
358 output += "/";
359 output += cmSystemTools::GetFilenameName(input);
360 this->CleanFiles.push_back(this->Convert(output.c_str(),
361 cmLocalGenerator::START_OUTPUT));
362 output = this->Convert(output.c_str(), cmLocalGenerator::HOME_OUTPUT);
364 // Create a rule to copy the content into the bundle.
365 std::vector<std::string> depends;
366 std::vector<std::string> commands;
367 depends.push_back(input);
368 std::string copyEcho = "Copying OS X content ";
369 copyEcho += output;
370 this->LocalGenerator->AppendEcho(commands, copyEcho.c_str(),
371 cmLocalUnixMakefileGenerator3::EchoBuild);
372 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
373 copyCommand += this->Convert(input.c_str(),
374 cmLocalGenerator::NONE,
375 cmLocalGenerator::SHELL);
376 copyCommand += " ";
377 copyCommand += this->Convert(output.c_str(),
378 cmLocalGenerator::NONE,
379 cmLocalGenerator::SHELL);
380 commands.push_back(copyCommand);
381 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
382 output.c_str(),
383 depends, commands, false);
384 this->ExtraFiles.insert(output);
387 //----------------------------------------------------------------------------
388 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
390 // Identify the language of the source file.
391 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
392 if(!lang)
394 // don't know anything about this file so skip it
395 return;
398 // Get the full path name of the object file.
399 bool hasSourceExtension;
400 std::string objNoTargetDir;
401 std::string obj =
402 this->LocalGenerator->GetObjectFileName(*this->Target, source,
403 &objNoTargetDir,
404 &hasSourceExtension);
406 // Avoid generating duplicate rules.
407 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
409 this->ObjectFiles.insert(obj);
411 else
413 cmOStringStream err;
414 err << "Warning: Source file \""
415 << source.GetFullPath()
416 << "\" is listed multiple times for target \""
417 << this->Target->GetName()
418 << "\".";
419 cmSystemTools::Message(err.str().c_str(), "Warning");
420 return;
423 // Create the directory containing the object file. This may be a
424 // subdirectory under the target's directory.
425 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
426 cmSystemTools::MakeDirectory
427 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
429 // Save this in the target's list of object files.
430 this->Objects.push_back(obj);
431 this->CleanFiles.push_back(obj);
433 // TODO: Remove
434 //std::string relativeObj
435 //= this->LocalGenerator->GetHomeRelativeOutputPath();
436 //relativeObj += obj;
438 // we compute some depends when writing the depend.make that we will also
439 // use in the build.make, same with depMakeFile
440 std::vector<std::string> depends;
441 std::string depMakeFile;
443 // generate the build rule file
444 this->WriteObjectBuildFile(obj, lang, source, depends);
446 // The object file should be checked for dependency integrity.
447 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
448 objFullPath += "/";
449 objFullPath += obj;
450 objFullPath =
451 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
452 std::string srcFullPath =
453 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
454 this->LocalGenerator->
455 AddImplicitDepends(*this->Target, lang,
456 objFullPath.c_str(),
457 srcFullPath.c_str());
459 // add this to the list of objects for this local generator
460 if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
462 objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
464 cmLocalUnixMakefileGenerator3::LocalObjectInfo& info =
465 this->LocalGenerator->LocalObjectFiles[objNoTargetDir];
466 info.HasSourceExtension = hasSourceExtension;
467 info.push_back(
468 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target, lang)
472 //----------------------------------------------------------------------------
473 void
474 cmMakefileTargetGenerator
475 ::WriteObjectBuildFile(std::string &obj,
476 const char *lang,
477 cmSourceFile& source,
478 std::vector<std::string>& depends)
480 this->LocalGenerator->AppendRuleDepend(depends,
481 this->FlagFileNameFull.c_str());
483 // generate the depend scanning rule
484 this->WriteObjectDependRules(source, depends);
486 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
487 relativeObj += obj;
488 // Write the build rule.
490 // Build the set of compiler flags.
491 std::string flags;
493 // Add language-specific flags.
494 std::string langFlags = "$(";
495 langFlags += lang;
496 langFlags += "_FLAGS)";
497 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
499 // Add target-specific flags.
500 if(this->Target->GetProperty("COMPILE_FLAGS"))
502 std::string langIncludeExpr = "CMAKE_";
503 langIncludeExpr += lang;
504 langIncludeExpr += "_FLAG_REGEX";
505 const char* regex = this->Makefile->
506 GetDefinition(langIncludeExpr.c_str());
507 if(regex)
509 cmsys::RegularExpression r(regex);
510 std::vector<std::string> args;
511 cmSystemTools::ParseWindowsCommandLine(
512 this->Target->GetProperty("COMPILE_FLAGS"),
513 args);
514 for(std::vector<std::string>::iterator i = args.begin();
515 i != args.end(); ++i)
517 if(r.find(i->c_str()))
519 this->LocalGenerator->AppendFlags
520 (flags, i->c_str());
524 else
526 this->LocalGenerator->AppendFlags
527 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
531 // Add flags from source file properties.
532 if (source.GetProperty("COMPILE_FLAGS"))
534 this->LocalGenerator->AppendFlags
535 (flags, source.GetProperty("COMPILE_FLAGS"));
536 *this->FlagFileStream << "# Custom flags: "
537 << relativeObj << "_FLAGS = "
538 << source.GetProperty("COMPILE_FLAGS")
539 << "\n"
540 << "\n";
543 // Add language-specific defines.
544 std::string defines = "$(";
545 defines += lang;
546 defines += "_DEFINES)";
548 // Add source-sepcific preprocessor definitions.
549 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
551 this->LocalGenerator->AppendDefines(defines, compile_defs, lang);
552 *this->FlagFileStream << "# Custom defines: "
553 << relativeObj << "_DEFINES = "
554 << compile_defs << "\n"
555 << "\n";
557 std::string configUpper =
558 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
559 std::string defPropName = "COMPILE_DEFINITIONS_";
560 defPropName += configUpper;
561 if(const char* config_compile_defs =
562 source.GetProperty(defPropName.c_str()))
564 this->LocalGenerator->AppendDefines(defines, config_compile_defs, lang);
565 *this->FlagFileStream
566 << "# Custom defines: "
567 << relativeObj << "_DEFINES_" << configUpper
568 << " = " << config_compile_defs << "\n"
569 << "\n";
572 // Get the output paths for source and object files.
573 std::string sourceFile = source.GetFullPath();
574 if(this->LocalGenerator->UseRelativePaths)
576 sourceFile = this->Convert(sourceFile.c_str(),
577 cmLocalGenerator::START_OUTPUT);
579 sourceFile = this->Convert(sourceFile.c_str(),
580 cmLocalGenerator::NONE,
581 cmLocalGenerator::SHELL);
582 std::string objectFile = this->Convert(obj.c_str(),
583 cmLocalGenerator::START_OUTPUT,
584 cmLocalGenerator::SHELL);
586 // Construct the build message.
587 std::vector<std::string> no_commands;
588 std::vector<std::string> commands;
590 // add in a progress call if needed
591 this->AppendProgress(commands);
593 if(!this->NoRuleMessages)
595 std::string buildEcho = "Building ";
596 buildEcho += lang;
597 buildEcho += " object ";
598 buildEcho += relativeObj;
599 this->LocalGenerator->AppendEcho
600 (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
603 std::string targetOutPathPDB;
605 std::string targetFullPathPDB;
606 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
607 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
608 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
609 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
611 targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
612 targetFullPathPDB += "/";
613 targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
615 targetOutPathPDB =
616 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
617 cmLocalGenerator::SHELL);
619 cmLocalGenerator::RuleVariables vars;
620 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
621 vars.CMTarget = this->Target;
622 vars.Language = lang;
623 vars.TargetPDB = targetOutPathPDB.c_str();
624 vars.Source = sourceFile.c_str();
625 std::string shellObj =
626 this->Convert(obj.c_str(),
627 cmLocalGenerator::NONE,
628 cmLocalGenerator::SHELL).c_str();
629 vars.Object = shellObj.c_str();
630 std::string objectDir = cmSystemTools::GetFilenamePath(obj);
631 objectDir = this->Convert(objectDir.c_str(),
632 cmLocalGenerator::START_OUTPUT,
633 cmLocalGenerator::SHELL);
634 vars.ObjectDir = objectDir.c_str();
635 vars.Flags = flags.c_str();
636 vars.Defines = defines.c_str();
638 // Construct the compile rules.
640 std::string compileRuleVar = "CMAKE_";
641 compileRuleVar += lang;
642 compileRuleVar += "_COMPILE_OBJECT";
643 std::string compileRule =
644 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
645 std::vector<std::string> compileCommands;
646 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
648 // Expand placeholders in the commands.
649 for(std::vector<std::string>::iterator i = compileCommands.begin();
650 i != compileCommands.end(); ++i)
652 this->LocalGenerator->ExpandRuleVariables(*i, vars);
655 // Change the command working directory to the local build tree.
656 this->LocalGenerator->CreateCDCommand
657 (compileCommands,
658 this->Makefile->GetStartOutputDirectory(),
659 cmLocalGenerator::HOME_OUTPUT);
660 commands.insert(commands.end(),
661 compileCommands.begin(), compileCommands.end());
664 // Write the rule.
665 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
666 relativeObj.c_str(),
667 depends, commands, false);
669 // Check for extra outputs created by the compilation.
670 if(const char* extra_outputs_str =
671 source.GetProperty("OBJECT_OUTPUTS"))
673 std::vector<std::string> extra_outputs;
674 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
675 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
676 eoi != extra_outputs.end(); ++eoi)
678 // Register this as an extra output for the object file rule.
679 // This will cause the object file to be rebuilt if the extra
680 // output is missing.
681 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
683 // Register this as an extra file to clean.
684 this->CleanFiles.push_back(eoi->c_str());
688 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
689 (strcmp(lang, "CXX") == 0));
690 bool do_preprocess_rules = lang_is_c_or_cxx &&
691 this->LocalGenerator->GetCreatePreprocessedSourceRules();
692 bool do_assembly_rules = lang_is_c_or_cxx &&
693 this->LocalGenerator->GetCreateAssemblySourceRules();
694 if(do_preprocess_rules || do_assembly_rules)
696 std::vector<std::string> force_depends;
697 force_depends.push_back("cmake_force");
698 std::string::size_type dot_pos = relativeObj.rfind(".");
699 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
700 dot_pos = obj.rfind(".");
701 std::string objBase = obj.substr(0, dot_pos);
703 if(do_preprocess_rules)
705 commands.clear();
706 std::string relativeObjI = relativeObjBase + ".i";
707 std::string objI = objBase + ".i";
709 std::string preprocessEcho = "Preprocessing ";
710 preprocessEcho += lang;
711 preprocessEcho += " source to ";
712 preprocessEcho += objI;
713 this->LocalGenerator->AppendEcho(
714 commands, preprocessEcho.c_str(),
715 cmLocalUnixMakefileGenerator3::EchoBuild
718 std::string preprocessRuleVar = "CMAKE_";
719 preprocessRuleVar += lang;
720 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
721 if(const char* preprocessRule =
722 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
724 std::vector<std::string> preprocessCommands;
725 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
727 std::string shellObjI =
728 this->Convert(objI.c_str(),
729 cmLocalGenerator::NONE,
730 cmLocalGenerator::SHELL).c_str();
731 vars.PreprocessedSource = shellObjI.c_str();
733 // Expand placeholders in the commands.
734 for(std::vector<std::string>::iterator i = preprocessCommands.begin();
735 i != preprocessCommands.end(); ++i)
737 this->LocalGenerator->ExpandRuleVariables(*i, vars);
740 this->LocalGenerator->CreateCDCommand
741 (preprocessCommands,
742 this->Makefile->GetStartOutputDirectory(),
743 cmLocalGenerator::HOME_OUTPUT);
744 commands.insert(commands.end(),
745 preprocessCommands.begin(),
746 preprocessCommands.end());
748 else
750 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
751 cmd += preprocessRuleVar;
752 commands.push_back(cmd);
755 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
756 relativeObjI.c_str(),
757 force_depends, commands, false);
760 if(do_assembly_rules)
762 commands.clear();
763 std::string relativeObjS = relativeObjBase + ".s";
764 std::string objS = objBase + ".s";
766 std::string assemblyEcho = "Compiling ";
767 assemblyEcho += lang;
768 assemblyEcho += " source to assembly ";
769 assemblyEcho += objS;
770 this->LocalGenerator->AppendEcho(
771 commands, assemblyEcho.c_str(),
772 cmLocalUnixMakefileGenerator3::EchoBuild
775 std::string assemblyRuleVar = "CMAKE_";
776 assemblyRuleVar += lang;
777 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
778 if(const char* assemblyRule =
779 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
781 std::vector<std::string> assemblyCommands;
782 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
784 std::string shellObjS =
785 this->Convert(objS.c_str(),
786 cmLocalGenerator::NONE,
787 cmLocalGenerator::SHELL).c_str();
788 vars.AssemblySource = shellObjS.c_str();
790 // Expand placeholders in the commands.
791 for(std::vector<std::string>::iterator i = assemblyCommands.begin();
792 i != assemblyCommands.end(); ++i)
794 this->LocalGenerator->ExpandRuleVariables(*i, vars);
797 this->LocalGenerator->CreateCDCommand
798 (assemblyCommands,
799 this->Makefile->GetStartOutputDirectory(),
800 cmLocalGenerator::HOME_OUTPUT);
801 commands.insert(commands.end(),
802 assemblyCommands.begin(),
803 assemblyCommands.end());
805 else
807 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
808 cmd += assemblyRuleVar;
809 commands.push_back(cmd);
812 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
813 relativeObjS.c_str(),
814 force_depends, commands, false);
818 // If the language needs provides-requires mode, create the
819 // corresponding targets.
820 std::string objectRequires = relativeObj;
821 objectRequires += ".requires";
822 std::vector<std::string> p_depends;
823 // always provide an empty requires target
824 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
825 objectRequires.c_str(), p_depends,
826 no_commands, true);
828 // write a build rule to recursively build what this obj provides
829 std::string objectProvides = relativeObj;
830 objectProvides += ".provides";
831 std::string temp = relativeObj;
832 temp += ".provides.build";
833 std::vector<std::string> r_commands;
834 std::string tgtMakefileName =
835 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
836 tgtMakefileName += "/build.make";
837 r_commands.push_back
838 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
839 temp.c_str()));
841 p_depends.clear();
842 p_depends.push_back(objectRequires);
843 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
844 objectProvides.c_str(), p_depends,
845 r_commands, true);
847 // write the provides.build rule dependency on the obj file
848 p_depends.clear();
849 p_depends.push_back(relativeObj);
850 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
851 temp.c_str(), p_depends, no_commands,
852 true);
855 //----------------------------------------------------------------------------
856 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
858 std::vector<std::string> depends;
859 std::vector<std::string> no_commands;
861 // Construct the name of the dependency generation target.
862 std::string depTarget =
863 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
864 depTarget += "/requires";
866 // This target drives dependency generation for all object files.
867 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
868 std::string objTarget;
869 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
870 obj != this->Objects.end(); ++obj)
872 objTarget = relPath;
873 objTarget += *obj;
874 objTarget += ".requires";
875 depends.push_back(objTarget);
878 // Write the rule.
879 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
880 depTarget.c_str(),
881 depends, no_commands, true);
884 //----------------------------------------------------------------------------
885 void cmMakefileTargetGenerator::WriteTargetCleanRules()
887 std::vector<std::string> depends;
888 std::vector<std::string> commands;
890 // Construct the clean target name.
891 std::string cleanTarget =
892 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
893 cleanTarget += "/clean";
895 // Construct the clean command.
896 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
897 *this->Target);
898 this->LocalGenerator->CreateCDCommand
899 (commands,
900 this->Makefile->GetStartOutputDirectory(),
901 cmLocalGenerator::HOME_OUTPUT);
903 // Write the rule.
904 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
905 cleanTarget.c_str(),
906 depends, commands, true);
910 //----------------------------------------------------------------------------
911 void cmMakefileTargetGenerator::WriteTargetDependRules()
913 // must write the targets depend info file
914 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
915 this->InfoFileNameFull = dir;
916 this->InfoFileNameFull += "/DependInfo.cmake";
917 this->InfoFileNameFull =
918 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
919 this->InfoFileStream =
920 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
921 this->InfoFileStream->SetCopyIfDifferent(true);
922 if(!*this->InfoFileStream)
924 return;
926 this->LocalGenerator->
927 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
929 // Store multiple output pairs in the depend info file.
930 if(!this->MultipleOutputPairs.empty())
932 *this->InfoFileStream
933 << "\n"
934 << "# Pairs of files generated by the same build rule.\n"
935 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
936 for(MultipleOutputPairsType::const_iterator pi =
937 this->MultipleOutputPairs.begin();
938 pi != this->MultipleOutputPairs.end(); ++pi)
940 *this->InfoFileStream
941 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
942 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
943 << "\n";
945 *this->InfoFileStream << " )\n\n";
948 // Store list of targets linked directly or transitively.
950 *this->InfoFileStream
951 << "\n"
952 << "# Targets to which this target links.\n"
953 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
954 std::set<cmTarget const*> emitted;
955 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
956 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
958 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
959 for(cmComputeLinkInformation::ItemVector::const_iterator
960 i = items.begin(); i != items.end(); ++i)
962 cmTarget const* linkee = i->Target;
963 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
965 cmMakefile* mf = linkee->GetMakefile();
966 cmLocalGenerator* lg = mf->GetLocalGenerator();
967 std::string di = mf->GetStartOutputDirectory();
968 di += "/";
969 di += lg->GetTargetDirectory(*linkee);
970 di += "/DependInfo.cmake";
971 *this->InfoFileStream << " \"" << di << "\"\n";
975 *this->InfoFileStream
976 << " )\n";
979 // Check for a target-specific module output directory.
980 if(const char* mdir = this->GetFortranModuleDirectory())
982 *this->InfoFileStream
983 << "\n"
984 << "# Fortran module output directory.\n"
985 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
988 // and now write the rule to use it
989 std::vector<std::string> depends;
990 std::vector<std::string> commands;
992 // Construct the name of the dependency generation target.
993 std::string depTarget =
994 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
995 depTarget += "/depend";
997 // Add a command to call CMake to scan dependencies. CMake will
998 // touch the corresponding depends file after scanning dependencies.
999 cmOStringStream depCmd;
1000 // TODO: Account for source file properties and directory-level
1001 // definitions when scanning for dependencies.
1002 #if !defined(_WIN32) || defined(__CYGWIN__)
1003 // This platform supports symlinks, so cmSystemTools will translate
1004 // paths. Make sure PWD is set to the original name of the home
1005 // output directory to help cmSystemTools to create the same
1006 // translation table for the dependency scanning process.
1007 depCmd << "cd "
1008 << (this->LocalGenerator->Convert(
1009 this->Makefile->GetHomeOutputDirectory(),
1010 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1011 << " && ";
1012 #endif
1013 // Generate a call this signature:
1015 // cmake -E cmake_depends <generator>
1016 // <home-src-dir> <start-src-dir>
1017 // <home-out-dir> <start-out-dir>
1018 // <dep-info> --color=$(COLOR)
1020 // This gives the dependency scanner enough information to recreate
1021 // the state of our local generator sufficiently for its needs.
1022 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1023 << this->GlobalGenerator->GetName() << "\" "
1024 << this->Convert(this->Makefile->GetHomeDirectory(),
1025 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1026 << " "
1027 << this->Convert(this->Makefile->GetStartDirectory(),
1028 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1029 << " "
1030 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1031 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1032 << " "
1033 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1034 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1035 << " "
1036 << this->Convert(this->InfoFileNameFull.c_str(),
1037 cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1038 if(this->LocalGenerator->GetColorMakefile())
1040 depCmd << " --color=$(COLOR)";
1042 commands.push_back(depCmd.str());
1044 // Make sure all custom command outputs in this target are built.
1045 if(this->CustomCommandDriver == OnDepends)
1047 this->DriveCustomCommands(depends);
1050 // Write the rule.
1051 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1052 depTarget.c_str(),
1053 depends, commands, true);
1056 //----------------------------------------------------------------------------
1057 void
1058 cmMakefileTargetGenerator
1059 ::DriveCustomCommands(std::vector<std::string>& depends)
1061 // Depend on all custom command outputs.
1062 const std::vector<cmSourceFile*>& sources =
1063 this->Target->GetSourceFiles();
1064 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1065 source != sources.end(); ++source)
1067 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1069 const std::vector<std::string>& outputs = cc->GetOutputs();
1070 for(std::vector<std::string>::const_iterator o = outputs.begin();
1071 o != outputs.end(); ++o)
1073 depends.push_back(*o);
1079 //----------------------------------------------------------------------------
1080 void cmMakefileTargetGenerator
1081 ::WriteObjectDependRules(cmSourceFile& source,
1082 std::vector<std::string>& depends)
1084 // Create the list of dependencies known at cmake time. These are
1085 // shared between the object file and dependency scanning rule.
1086 depends.push_back(source.GetFullPath());
1087 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1089 std::vector<std::string> deps;
1090 cmSystemTools::ExpandListArgument(objectDeps, deps);
1091 for(std::vector<std::string>::iterator i = deps.begin();
1092 i != deps.end(); ++i)
1094 depends.push_back(i->c_str());
1099 //----------------------------------------------------------------------------
1100 void cmMakefileTargetGenerator
1101 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1103 // Collect the commands.
1104 std::vector<std::string> commands;
1105 std::string comment = this->LocalGenerator->ConstructComment(cc);
1106 if(!comment.empty())
1108 // add in a progress call if needed
1109 this->AppendProgress(commands);
1110 if(!this->NoRuleMessages)
1112 this->LocalGenerator
1113 ->AppendEcho(commands, comment.c_str(),
1114 cmLocalUnixMakefileGenerator3::EchoGenerate);
1118 // Now append the actual user-specified commands.
1119 cmOStringStream content;
1120 this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1121 cmLocalGenerator::HOME_OUTPUT,
1122 &content);
1124 // Collect the dependencies.
1125 std::vector<std::string> depends;
1126 this->LocalGenerator->AppendCustomDepend(depends, cc);
1128 // Check whether we need to bother checking for a symbolic output.
1129 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1131 // Write the rule.
1132 const std::vector<std::string>& outputs = cc.GetOutputs();
1133 std::vector<std::string>::const_iterator o = outputs.begin();
1135 bool symbolic = false;
1136 if(need_symbolic)
1138 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1140 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1143 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1144 o->c_str(), depends, commands,
1145 symbolic);
1147 // If the rule has changed make sure the output is rebuilt.
1148 if(!symbolic)
1150 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1154 // Write rules to drive building any outputs beyond the first.
1155 const char* in = o->c_str();
1156 for(++o; o != outputs.end(); ++o)
1158 bool symbolic = false;
1159 if(need_symbolic)
1161 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1163 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1166 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1169 // Setup implicit dependency scanning.
1170 for(cmCustomCommand::ImplicitDependsList::const_iterator
1171 idi = cc.GetImplicitDepends().begin();
1172 idi != cc.GetImplicitDepends().end(); ++idi)
1174 std::string objFullPath =
1175 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1176 std::string srcFullPath =
1177 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1178 this->LocalGenerator->
1179 AddImplicitDepends(*this->Target, idi->first.c_str(),
1180 objFullPath.c_str(),
1181 srcFullPath.c_str());
1185 //----------------------------------------------------------------------------
1186 void
1187 cmMakefileTargetGenerator
1188 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1190 // Add a rule to build the primary output if the extra output needs
1191 // to be created.
1192 std::vector<std::string> commands;
1193 std::vector<std::string> depends;
1194 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1195 if(!emptyCommand.empty())
1197 commands.push_back(emptyCommand);
1199 depends.push_back(in);
1200 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1201 out, depends, commands,
1202 symbolic);
1204 // Register the extra output as paired with the first output so that
1205 // the check-build-system step will remove the primary output if any
1206 // extra outputs are missing. This forces the rule to regenerate
1207 // all outputs.
1208 this->AddMultipleOutputPair(out, in);
1211 //----------------------------------------------------------------------------
1212 void
1213 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1215 this->NumberOfProgressActions++;
1216 if(this->NoRuleMessages)
1218 return;
1220 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1221 progressDir += cmake::GetCMakeFilesDirectory();
1222 cmOStringStream progCmd;
1223 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1224 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1225 cmLocalGenerator::FULL,
1226 cmLocalGenerator::SHELL);
1227 progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1228 commands.push_back(progCmd.str());
1231 //----------------------------------------------------------------------------
1232 void
1233 cmMakefileTargetGenerator
1234 ::WriteObjectsVariable(std::string& variableName,
1235 std::string& variableNameExternal)
1237 // Write a make variable assignment that lists all objects for the
1238 // target.
1239 variableName =
1240 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1241 "_OBJECTS");
1242 *this->BuildFileStream
1243 << "# Object files for target " << this->Target->GetName() << "\n"
1244 << variableName.c_str() << " =";
1245 std::string object;
1246 const char* objName =
1247 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1248 const char* lineContinue =
1249 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1250 if(!lineContinue)
1252 lineContinue = "\\";
1254 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1255 i != this->Objects.end(); ++i)
1257 *this->BuildFileStream << " " << lineContinue << "\n";
1258 if(objName)
1260 *this->BuildFileStream <<
1261 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1262 cmLocalGenerator::MAKEFILE);
1264 else
1266 *this->BuildFileStream <<
1267 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1270 *this->BuildFileStream << "\n";
1272 // Write a make variable assignment that lists all external objects
1273 // for the target.
1274 variableNameExternal =
1275 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1276 "_EXTERNAL_OBJECTS");
1277 *this->BuildFileStream
1278 << "\n"
1279 << "# External object files for target "
1280 << this->Target->GetName() << "\n"
1281 << variableNameExternal.c_str() << " =";
1282 for(std::vector<std::string>::const_iterator i =
1283 this->ExternalObjects.begin();
1284 i != this->ExternalObjects.end(); ++i)
1286 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1287 *this->BuildFileStream
1288 << " " << lineContinue << "\n"
1289 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1290 if(objName)
1292 *this->BuildFileStream <<
1293 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1294 cmLocalGenerator::MAKEFILE);
1296 else
1298 *this->BuildFileStream <<
1299 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1302 *this->BuildFileStream << "\n" << "\n";
1305 //----------------------------------------------------------------------------
1306 void
1307 cmMakefileTargetGenerator
1308 ::WriteObjectsString(std::string& buildObjs)
1310 std::vector<std::string> objStrings;
1311 this->WriteObjectsStrings(objStrings);
1312 buildObjs = objStrings[0];
1315 //----------------------------------------------------------------------------
1316 class cmMakefileTargetGeneratorObjectStrings
1318 public:
1319 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1320 cmMakefile* mf,
1321 cmLocalUnixMakefileGenerator3* lg,
1322 std::string::size_type limit):
1323 Strings(strings), Makefile(mf), LocalGenerator(lg), LengthLimit(limit)
1325 this->Space = "";
1327 void Feed(std::string const& obj)
1329 // Construct the name of the next object.
1330 this->NextObject =
1331 this->LocalGenerator->Convert(obj.c_str(),
1332 cmLocalGenerator::START_OUTPUT,
1333 cmLocalGenerator::SHELL);
1335 // Roll over to next string if the limit will be exceeded.
1336 if(this->LengthLimit != std::string::npos &&
1337 (this->CurrentString.length() + 1 + this->NextObject.length()
1338 > this->LengthLimit))
1340 this->Strings.push_back(this->CurrentString);
1341 this->CurrentString = "";
1342 this->Space = "";
1345 // Separate from previous object.
1346 this->CurrentString += this->Space;
1347 this->Space = " ";
1349 // Append this object.
1350 this->CurrentString += this->NextObject;
1352 void Done()
1354 this->Strings.push_back(this->CurrentString);
1356 private:
1357 std::vector<std::string>& Strings;
1358 cmMakefile* Makefile;
1359 cmLocalUnixMakefileGenerator3* LocalGenerator;
1360 std::string::size_type LengthLimit;
1361 std::string CurrentString;
1362 std::string NextObject;
1363 const char* Space;
1366 //----------------------------------------------------------------------------
1367 void
1368 cmMakefileTargetGenerator
1369 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1370 std::string::size_type limit)
1372 cmMakefileTargetGeneratorObjectStrings
1373 helper(objStrings, this->Makefile, this->LocalGenerator, limit);
1374 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1375 i != this->Objects.end(); ++i)
1377 helper.Feed(*i);
1379 for(std::vector<std::string>::const_iterator i =
1380 this->ExternalObjects.begin();
1381 i != this->ExternalObjects.end(); ++i)
1383 helper.Feed(*i);
1385 helper.Done();
1388 //----------------------------------------------------------------------------
1389 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1390 bool relink)
1392 // Compute the name of the driver target.
1393 std::string dir =
1394 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1395 std::string buildTargetRuleName = dir;
1396 buildTargetRuleName += relink?"/preinstall":"/build";
1397 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1398 cmLocalGenerator::HOME_OUTPUT,
1399 cmLocalGenerator::UNCHANGED);
1401 // Build the list of target outputs to drive.
1402 std::vector<std::string> depends;
1403 if(main_output)
1405 depends.push_back(main_output);
1408 const char* comment = 0;
1409 if(relink)
1411 // Setup the comment for the preinstall driver.
1412 comment = "Rule to relink during preinstall.";
1414 else
1416 // Setup the comment for the main build driver.
1417 comment = "Rule to build all files generated by this target.";
1419 // Make sure all custom command outputs in this target are built.
1420 if(this->CustomCommandDriver == OnBuild)
1422 this->DriveCustomCommands(depends);
1425 // Make sure the extra files are built.
1426 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1427 i != this->ExtraFiles.end(); ++i)
1429 depends.push_back(*i);
1433 // Write the driver rule.
1434 std::vector<std::string> no_commands;
1435 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1436 buildTargetRuleName.c_str(),
1437 depends, no_commands, true);
1440 //----------------------------------------------------------------------------
1441 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1443 #ifndef __APPLE__
1444 return std::string();
1445 #else
1446 std::set<cmStdString> emitted;
1447 emitted.insert("/System/Library/Frameworks");
1448 std::vector<std::string> includes;
1449 this->LocalGenerator->GetIncludeDirectories(includes);
1450 std::vector<std::string>::iterator i;
1451 // check all include directories for frameworks as this
1452 // will already have added a -F for the framework
1453 for(i = includes.begin(); i != includes.end(); ++i)
1455 if(this->Target->NameResolvesToFramework(i->c_str()))
1457 std::string frameworkDir = *i;
1458 frameworkDir += "/../";
1459 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1460 emitted.insert(frameworkDir);
1464 std::string flags;
1465 std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1466 for(i = frameworks.begin();
1467 i != frameworks.end(); ++i)
1469 if(emitted.insert(*i).second)
1471 flags += "-F";
1472 flags += this->Convert(i->c_str(),
1473 cmLocalGenerator::START_OUTPUT,
1474 cmLocalGenerator::SHELL, true);
1475 flags += " ";
1478 return flags;
1479 #endif
1482 //----------------------------------------------------------------------------
1483 void cmMakefileTargetGenerator
1484 ::AppendTargetDepends(std::vector<std::string>& depends)
1486 // Static libraries never depend on anything for linking.
1487 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1489 return;
1492 // Loop over all library dependencies.
1493 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1494 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1496 std::vector<std::string> const& libDeps = cli->GetDepends();
1497 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1498 j != libDeps.end(); ++j)
1500 depends.push_back(*j);
1505 //----------------------------------------------------------------------------
1506 void cmMakefileTargetGenerator
1507 ::CloseFileStreams()
1509 delete this->BuildFileStream;
1510 delete this->InfoFileStream;
1511 delete this->FlagFileStream;
1514 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1515 const char* linkLang,
1516 std::string& linkFlags)
1518 // check for language flags that are not allowed at link time, and
1519 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1520 // which fails, there may be more]
1522 std::string removeFlags = "CMAKE_";
1523 removeFlags += linkLang;
1524 removeFlags += flagVar;
1525 std::string removeflags =
1526 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1527 std::vector<std::string> removeList;
1528 cmSystemTools::ExpandListArgument(removeflags, removeList);
1529 for(std::vector<std::string>::iterator i = removeList.begin();
1530 i != removeList.end(); ++i)
1532 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1536 //----------------------------------------------------------------------------
1537 void
1538 cmMakefileTargetGenerator
1539 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1541 MultipleOutputPairsType::value_type p(depender, dependee);
1542 this->MultipleOutputPairs.insert(p);
1545 //----------------------------------------------------------------------------
1546 void
1547 cmMakefileTargetGenerator
1548 ::CreateLinkScript(const char* name,
1549 std::vector<std::string> const& link_commands,
1550 std::vector<std::string>& makefile_commands,
1551 std::vector<std::string>& makefile_depends)
1553 // Create the link script file.
1554 std::string linkScriptName = this->TargetBuildDirectoryFull;
1555 linkScriptName += "/";
1556 linkScriptName += name;
1557 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1558 linkScriptStream.SetCopyIfDifferent(true);
1559 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1560 cmd != link_commands.end(); ++cmd)
1562 // Do not write out empty commands or commands beginning in the
1563 // shell no-op ":".
1564 if(!cmd->empty() && (*cmd)[0] != ':')
1566 linkScriptStream << *cmd << "\n";
1570 // Create the makefile command to invoke the link script.
1571 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1572 link_command += this->Convert(linkScriptName.c_str(),
1573 cmLocalGenerator::START_OUTPUT,
1574 cmLocalGenerator::SHELL);
1575 link_command += " --verbose=$(VERBOSE)";
1576 makefile_commands.push_back(link_command);
1577 makefile_depends.push_back(linkScriptName);
1580 //----------------------------------------------------------------------------
1581 std::string
1582 cmMakefileTargetGenerator
1583 ::CreateResponseFile(const char* name, std::string const& options,
1584 std::vector<std::string>& makefile_depends)
1586 // Create the response file.
1587 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1588 responseFileNameFull += "/";
1589 responseFileNameFull += name;
1590 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1591 responseStream.SetCopyIfDifferent(true);
1592 responseStream << options << "\n";
1594 // Add a dependency so the target will rebuild when the set of
1595 // objects changes.
1596 makefile_depends.push_back(responseFileNameFull);
1598 // Construct the name to be used on the command line.
1599 std::string responseFileName = this->TargetBuildDirectory;
1600 responseFileName += "/";
1601 responseFileName += name;
1602 return responseFileName;
1605 //----------------------------------------------------------------------------
1606 void
1607 cmMakefileTargetGenerator
1608 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1609 bool useResponseFile, std::string& buildObjs,
1610 std::vector<std::string>& makefile_depends)
1612 std::string variableName;
1613 std::string variableNameExternal;
1614 this->WriteObjectsVariable(variableName, variableNameExternal);
1615 if(useResponseFile)
1617 // MSVC response files cannot exceed 128K.
1618 std::string::size_type const responseFileLimit = 131000;
1620 // Construct the individual object list strings.
1621 std::vector<std::string> object_strings;
1622 this->WriteObjectsStrings(object_strings, responseFileLimit);
1624 // Write a response file for each string.
1625 const char* sep = "";
1626 for(unsigned int i = 0; i < object_strings.size(); ++i)
1628 // Number the response files.
1629 char rsp[32];
1630 sprintf(rsp, "objects%u.rsp", i+1);
1632 // Create this response file.
1633 std::string objects_rsp =
1634 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1636 // Separate from previous response file references.
1637 buildObjs += sep;
1638 sep = " ";
1640 // Reference the response file.
1641 buildObjs += "@";
1642 buildObjs += this->Convert(objects_rsp.c_str(),
1643 cmLocalGenerator::NONE,
1644 cmLocalGenerator::SHELL);
1647 else if(useLinkScript)
1649 if(!useArchiveRules)
1651 this->WriteObjectsString(buildObjs);
1654 else
1656 buildObjs = "$(";
1657 buildObjs += variableName;
1658 buildObjs += ") $(";
1659 buildObjs += variableNameExternal;
1660 buildObjs += ")";
1664 //----------------------------------------------------------------------------
1665 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1667 // Compute the module directory.
1668 if(!this->FortranModuleDirectoryComputed)
1670 const char* target_mod_dir =
1671 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1672 const char* moddir_flag =
1673 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1674 if(target_mod_dir && moddir_flag)
1676 // Compute the full path to the module directory.
1677 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1679 // Already a full path.
1680 this->FortranModuleDirectory = target_mod_dir;
1682 else
1684 // Interpret relative to the current output directory.
1685 this->FortranModuleDirectory =
1686 this->Makefile->GetCurrentOutputDirectory();
1687 this->FortranModuleDirectory += "/";
1688 this->FortranModuleDirectory += target_mod_dir;
1691 // Make sure the module output directory exists.
1692 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1694 this->FortranModuleDirectoryComputed = true;
1697 // Return the computed directory.
1698 if(this->FortranModuleDirectory.empty())
1700 return 0;
1702 else
1704 return this->FortranModuleDirectory.c_str();
1708 //----------------------------------------------------------------------------
1709 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1711 // Add a module output directory flag if necessary.
1712 if(const char* mod_dir = this->GetFortranModuleDirectory())
1714 const char* moddir_flag =
1715 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1716 std::string modflag = moddir_flag;
1717 modflag += this->Convert(mod_dir,
1718 cmLocalGenerator::START_OUTPUT,
1719 cmLocalGenerator::SHELL);
1720 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1723 // If there is a separate module path flag then duplicate the
1724 // include path with it. This compiler does not search the include
1725 // path for modules.
1726 if(const char* modpath_flag =
1727 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1729 std::vector<std::string> includes;
1730 this->LocalGenerator->GetIncludeDirectories(includes);
1731 for(std::vector<std::string>::const_iterator idi = includes.begin();
1732 idi != includes.end(); ++idi)
1734 std::string flg = modpath_flag;
1735 flg += this->Convert(idi->c_str(),
1736 cmLocalGenerator::NONE,
1737 cmLocalGenerator::SHELL);
1738 this->LocalGenerator->AppendFlags(flags, flg.c_str());