ENH: add submit via cp mode
[cmake.git] / Source / cmMakefileTargetGenerator.cxx
blob3b7ae30c9581bf14f8dfd70d1f0c505e3eea5b63
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-16 20:55:58 $
7 Version: $Revision: 1.118 $
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->GlobalGenerator =
47 static_cast<cmGlobalUnixMakefileGenerator3*>(
48 this->LocalGenerator->GetGlobalGenerator());
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);
57 cmMakefileTargetGenerator *
58 cmMakefileTargetGenerator::New(cmTarget *tgt)
60 cmMakefileTargetGenerator *result = 0;
62 switch (tgt->GetType())
64 case cmTarget::EXECUTABLE:
65 result = new cmMakefileExecutableTargetGenerator(tgt);
66 break;
67 case cmTarget::STATIC_LIBRARY:
68 case cmTarget::SHARED_LIBRARY:
69 case cmTarget::MODULE_LIBRARY:
70 result = new cmMakefileLibraryTargetGenerator(tgt);
71 break;
72 case cmTarget::UTILITY:
73 result = new cmMakefileUtilityTargetGenerator(tgt);
74 break;
75 default:
76 return result;
77 // break; /* unreachable */
79 return result;
82 //----------------------------------------------------------------------------
83 void cmMakefileTargetGenerator::CreateRuleFile()
85 // Create a directory for this target.
86 this->TargetBuildDirectory =
87 this->LocalGenerator->GetTargetDirectory(*this->Target);
88 this->TargetBuildDirectoryFull =
89 this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
90 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
92 // Construct the rule file name.
93 this->BuildFileName = this->TargetBuildDirectory;
94 this->BuildFileName += "/build.make";
95 this->BuildFileNameFull = this->TargetBuildDirectoryFull;
96 this->BuildFileNameFull += "/build.make";
98 // Construct the rule file name.
99 this->ProgressFileName = this->TargetBuildDirectory;
100 this->ProgressFileName += "/progress.make";
101 this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
102 this->ProgressFileNameFull += "/progress.make";
104 // reset the progress count
105 this->NumberOfProgressActions = 0;
107 // Open the rule file. This should be copy-if-different because the
108 // rules may depend on this file itself.
109 this->BuildFileStream =
110 new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
111 this->BuildFileStream->SetCopyIfDifferent(true);
112 if(!this->BuildFileStream)
114 return;
116 this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
117 this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
120 //----------------------------------------------------------------------------
121 void cmMakefileTargetGenerator::WriteTargetBuildRules()
123 // write the custom commands for this target
124 // Look for files registered for cleaning in this directory.
125 if(const char* additional_clean_files =
126 this->Makefile->GetProperty
127 ("ADDITIONAL_MAKE_CLEAN_FILES"))
129 cmSystemTools::ExpandListArgument(additional_clean_files,
130 this->CleanFiles);
133 // add custom commands to the clean rules?
134 const char* clean_no_custom =
135 this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
136 bool clean = cmSystemTools::IsOff(clean_no_custom);
138 // First generate the object rule files. Save a list of all object
139 // files for this target.
140 const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
141 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
142 source != sources.end(); ++source)
144 cmTarget::SourceFileFlags tsFlags =
145 this->Target->GetTargetSourceFileFlags(*source);
146 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
148 this->GenerateCustomRuleFile(*cc);
149 if (clean)
151 const std::vector<std::string>& outputs = cc->GetOutputs();
152 for(std::vector<std::string>::const_iterator o = outputs.begin();
153 o != outputs.end(); ++o)
155 this->CleanFiles.push_back
156 (this->Convert(o->c_str(),
157 cmLocalGenerator::START_OUTPUT,
158 cmLocalGenerator::UNCHANGED));
162 else if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
164 this->WriteMacOSXContentRules(*(*source), tsFlags.MacFolder);
166 else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
168 if(!this->GlobalGenerator->IgnoreFile
169 ((*source)->GetExtension().c_str()))
171 // Generate this object file's rule file.
172 this->WriteObjectRuleFiles(*(*source));
174 else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
176 // This is an external object file. Just add it.
177 this->ExternalObjects.push_back((*source)->GetFullPath());
179 else
181 // We only get here if a source file is not an external object
182 // and has an extension that is listed as an ignored file type
183 // for this language. No message or diagnosis should be
184 // given.
191 //----------------------------------------------------------------------------
192 void cmMakefileTargetGenerator::WriteCommonCodeRules()
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 << " "
200 << this->Convert(dependFileNameFull.c_str(),
201 cmLocalGenerator::HOME_OUTPUT,
202 cmLocalGenerator::MAKEFILE)
203 << "\n\n";
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 << " "
211 << this->Convert(this->ProgressFileNameFull.c_str(),
212 cmLocalGenerator::HOME_OUTPUT,
213 cmLocalGenerator::MAKEFILE)
214 << "\n\n";
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());
222 depFileStream
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)
236 return;
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 << " "
244 << this->Convert(this->FlagFileNameFull.c_str(),
245 cmLocalGenerator::HOME_OUTPUT,
246 cmLocalGenerator::MAKEFILE)
247 << "\n\n";
250 //----------------------------------------------------------------------------
251 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
253 // write language flags for target
254 std::set<cmStdString> languages;
255 this->Target->GetLanguages(languages);
256 // put the compiler in the rules.make file so that if it changes
257 // things rebuild
258 for(std::set<cmStdString>::const_iterator l = languages.begin();
259 l != languages.end(); ++l)
261 cmStdString compiler = "CMAKE_";
262 compiler += *l;
263 compiler += "_COMPILER";
264 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
265 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
268 for(std::set<cmStdString>::const_iterator l = languages.begin();
269 l != languages.end(); ++l)
271 const char *lang = l->c_str();
272 std::string flags;
273 std::string defines;
274 bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
275 (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
277 // Add the export symbol definition for shared library objects.
278 if(const char* exportMacro = this->Target->GetExportMacro())
280 this->LocalGenerator->AppendDefines(defines, exportMacro, lang);
283 // Add preprocessor definitions for this target and configuration.
284 this->LocalGenerator->AppendDefines
285 (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang);
286 this->LocalGenerator->AppendDefines
287 (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang);
288 std::string defPropName = "COMPILE_DEFINITIONS_";
289 defPropName +=
290 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
291 this->LocalGenerator->AppendDefines
292 (defines, this->Makefile->GetProperty(defPropName.c_str()), lang);
293 this->LocalGenerator->AppendDefines
294 (defines, this->Target->GetProperty(defPropName.c_str()), lang);
296 // Add language-specific flags.
297 this->LocalGenerator
298 ->AddLanguageFlags(flags, lang,
299 this->LocalGenerator->ConfigurationName.c_str());
301 // Fortran-specific flags computed for this target.
302 if(*l == "Fortran")
304 this->AddFortranFlags(flags);
307 // Add shared-library flags if needed.
308 this->LocalGenerator->AddSharedFlags(flags, lang, shared);
310 // Add include directory flags.
311 this->LocalGenerator->
312 AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
313 // Add include directory flags.
314 this->LocalGenerator->
315 AppendFlags(flags,this->GetFrameworkFlags().c_str());
317 *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
318 *this->FlagFileStream << lang << "_DEFINES = " << defines << "\n\n";
321 // Add target-specific flags.
322 if(this->Target->GetProperty("COMPILE_FLAGS"))
324 std::string flags;
325 this->LocalGenerator->AppendFlags
326 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
327 *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
331 //----------------------------------------------------------------------------
332 void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source,
333 const char* pkgloc)
335 // Skip OS X content when not building a Framework or Bundle.
336 if(this->MacContentDirectory.empty())
338 return;
341 // Construct the full path to the content subdirectory.
342 std::string macdir = this->MacContentDirectory;
343 macdir += pkgloc;
344 cmSystemTools::MakeDirectory(macdir.c_str());
346 // Record use of this content location. Only the first level
347 // directory is needed.
349 std::string loc = pkgloc;
350 loc = loc.substr(0, loc.find('/'));
351 this->MacContentFolders.insert(loc);
354 // Get the input file location.
355 std::string input = source.GetFullPath();
357 // Get the output file location.
358 std::string output = macdir;
359 output += "/";
360 output += cmSystemTools::GetFilenameName(input);
361 this->CleanFiles.push_back(this->Convert(output.c_str(),
362 cmLocalGenerator::START_OUTPUT));
363 output = this->Convert(output.c_str(), cmLocalGenerator::HOME_OUTPUT);
365 // Create a rule to copy the content into the bundle.
366 std::vector<std::string> depends;
367 std::vector<std::string> commands;
368 depends.push_back(input);
369 std::string copyEcho = "Copying OS X content ";
370 copyEcho += output;
371 this->LocalGenerator->AppendEcho(commands, copyEcho.c_str(),
372 cmLocalUnixMakefileGenerator3::EchoBuild);
373 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
374 copyCommand += this->Convert(input.c_str(),
375 cmLocalGenerator::NONE,
376 cmLocalGenerator::SHELL);
377 copyCommand += " ";
378 copyCommand += this->Convert(output.c_str(),
379 cmLocalGenerator::NONE,
380 cmLocalGenerator::SHELL);
381 commands.push_back(copyCommand);
382 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
383 output.c_str(),
384 depends, commands, false);
385 this->ExtraFiles.insert(output);
388 //----------------------------------------------------------------------------
389 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
391 // Identify the language of the source file.
392 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
393 if(!lang)
395 // don't know anything about this file so skip it
396 return;
399 // Get the full path name of the object file.
400 bool hasSourceExtension;
401 std::string objNoTargetDir;
402 std::string obj =
403 this->LocalGenerator->GetObjectFileName(*this->Target, source,
404 &objNoTargetDir,
405 &hasSourceExtension);
407 // Avoid generating duplicate rules.
408 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
410 this->ObjectFiles.insert(obj);
412 else
414 cmOStringStream err;
415 err << "Warning: Source file \""
416 << source.GetFullPath()
417 << "\" is listed multiple times for target \""
418 << this->Target->GetName()
419 << "\".";
420 cmSystemTools::Message(err.str().c_str(), "Warning");
421 return;
424 // Create the directory containing the object file. This may be a
425 // subdirectory under the target's directory.
426 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
427 cmSystemTools::MakeDirectory
428 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
430 // Save this in the target's list of object files.
431 this->Objects.push_back(obj);
432 this->CleanFiles.push_back(obj);
434 // TODO: Remove
435 //std::string relativeObj
436 //= this->LocalGenerator->GetHomeRelativeOutputPath();
437 //relativeObj += obj;
439 // we compute some depends when writing the depend.make that we will also
440 // use in the build.make, same with depMakeFile
441 std::vector<std::string> depends;
442 std::string depMakeFile;
444 // generate the build rule file
445 this->WriteObjectBuildFile(obj, lang, source, depends);
447 // The object file should be checked for dependency integrity.
448 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
449 objFullPath += "/";
450 objFullPath += obj;
451 objFullPath =
452 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
453 std::string srcFullPath =
454 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
455 this->LocalGenerator->
456 AddImplicitDepends(*this->Target, lang,
457 objFullPath.c_str(),
458 srcFullPath.c_str());
460 // add this to the list of objects for this local generator
461 if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
463 objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
465 cmLocalUnixMakefileGenerator3::LocalObjectInfo& info =
466 this->LocalGenerator->LocalObjectFiles[objNoTargetDir];
467 info.HasSourceExtension = hasSourceExtension;
468 info.push_back(
469 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target, lang)
473 //----------------------------------------------------------------------------
474 void
475 cmMakefileTargetGenerator
476 ::WriteObjectBuildFile(std::string &obj,
477 const char *lang,
478 cmSourceFile& source,
479 std::vector<std::string>& depends)
481 this->LocalGenerator->AppendRuleDepend(depends,
482 this->FlagFileNameFull.c_str());
484 // generate the depend scanning rule
485 this->WriteObjectDependRules(source, depends);
487 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
488 relativeObj += obj;
489 // Write the build rule.
491 // Build the set of compiler flags.
492 std::string flags;
494 // Add language-specific flags.
495 std::string langFlags = "$(";
496 langFlags += lang;
497 langFlags += "_FLAGS)";
498 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
500 // Add target-specific flags.
501 if(this->Target->GetProperty("COMPILE_FLAGS"))
503 std::string langIncludeExpr = "CMAKE_";
504 langIncludeExpr += lang;
505 langIncludeExpr += "_FLAG_REGEX";
506 const char* regex = this->Makefile->
507 GetDefinition(langIncludeExpr.c_str());
508 if(regex)
510 cmsys::RegularExpression r(regex);
511 std::vector<std::string> args;
512 cmSystemTools::ParseWindowsCommandLine(
513 this->Target->GetProperty("COMPILE_FLAGS"),
514 args);
515 for(std::vector<std::string>::iterator i = args.begin();
516 i != args.end(); ++i)
518 if(r.find(i->c_str()))
520 this->LocalGenerator->AppendFlags
521 (flags, i->c_str());
525 else
527 this->LocalGenerator->AppendFlags
528 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
532 // Add flags from source file properties.
533 if (source.GetProperty("COMPILE_FLAGS"))
535 this->LocalGenerator->AppendFlags
536 (flags, source.GetProperty("COMPILE_FLAGS"));
537 *this->FlagFileStream << "# Custom flags: "
538 << relativeObj << "_FLAGS = "
539 << source.GetProperty("COMPILE_FLAGS")
540 << "\n"
541 << "\n";
544 // Add language-specific defines.
545 std::string defines = "$(";
546 defines += lang;
547 defines += "_DEFINES)";
549 // Add source-sepcific preprocessor definitions.
550 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
552 this->LocalGenerator->AppendDefines(defines, compile_defs, lang);
553 *this->FlagFileStream << "# Custom defines: "
554 << relativeObj << "_DEFINES = "
555 << compile_defs << "\n"
556 << "\n";
558 std::string configUpper =
559 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
560 std::string defPropName = "COMPILE_DEFINITIONS_";
561 defPropName += configUpper;
562 if(const char* config_compile_defs =
563 source.GetProperty(defPropName.c_str()))
565 this->LocalGenerator->AppendDefines(defines, config_compile_defs, lang);
566 *this->FlagFileStream
567 << "# Custom defines: "
568 << relativeObj << "_DEFINES_" << configUpper
569 << " = " << config_compile_defs << "\n"
570 << "\n";
573 // Get the output paths for source and object files.
574 std::string sourceFile = source.GetFullPath();
575 if(this->LocalGenerator->UseRelativePaths)
577 sourceFile = this->Convert(sourceFile.c_str(),
578 cmLocalGenerator::START_OUTPUT);
580 sourceFile = this->Convert(sourceFile.c_str(),
581 cmLocalGenerator::NONE,
582 cmLocalGenerator::SHELL);
583 std::string objectFile = this->Convert(obj.c_str(),
584 cmLocalGenerator::START_OUTPUT,
585 cmLocalGenerator::SHELL);
587 // Construct the build message.
588 std::vector<std::string> no_commands;
589 std::vector<std::string> commands;
591 // add in a progress call if needed
592 this->AppendProgress(commands);
594 if(!this->NoRuleMessages)
596 std::string buildEcho = "Building ";
597 buildEcho += lang;
598 buildEcho += " object ";
599 buildEcho += relativeObj;
600 this->LocalGenerator->AppendEcho
601 (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
604 std::string targetOutPathPDB;
606 std::string targetFullPathPDB;
607 const char* configName = this->LocalGenerator->ConfigurationName.c_str();
608 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
609 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
610 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
611 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
613 targetFullPathPDB = this->Target->GetDirectory();
614 targetFullPathPDB += "/";
615 targetFullPathPDB += this->Target->GetPDBName(configName);
617 targetOutPathPDB =
618 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::FULL,
619 cmLocalGenerator::SHELL);
621 cmLocalGenerator::RuleVariables vars;
622 vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
623 vars.CMTarget = this->Target;
624 vars.Language = lang;
625 vars.TargetPDB = targetOutPathPDB.c_str();
626 vars.Source = sourceFile.c_str();
627 std::string shellObj =
628 this->Convert(obj.c_str(),
629 cmLocalGenerator::NONE,
630 cmLocalGenerator::SHELL).c_str();
631 vars.Object = shellObj.c_str();
632 std::string objectDir = cmSystemTools::GetFilenamePath(obj);
633 objectDir = this->Convert(objectDir.c_str(),
634 cmLocalGenerator::START_OUTPUT,
635 cmLocalGenerator::SHELL);
636 vars.ObjectDir = objectDir.c_str();
637 vars.Flags = flags.c_str();
638 vars.Defines = defines.c_str();
640 // Construct the compile rules.
642 std::string compileRuleVar = "CMAKE_";
643 compileRuleVar += lang;
644 compileRuleVar += "_COMPILE_OBJECT";
645 std::string compileRule =
646 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
647 std::vector<std::string> compileCommands;
648 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
650 // Expand placeholders in the commands.
651 for(std::vector<std::string>::iterator i = compileCommands.begin();
652 i != compileCommands.end(); ++i)
654 this->LocalGenerator->ExpandRuleVariables(*i, vars);
657 // Change the command working directory to the local build tree.
658 this->LocalGenerator->CreateCDCommand
659 (compileCommands,
660 this->Makefile->GetStartOutputDirectory(),
661 cmLocalGenerator::HOME_OUTPUT);
662 commands.insert(commands.end(),
663 compileCommands.begin(), compileCommands.end());
666 // Write the rule.
667 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
668 relativeObj.c_str(),
669 depends, commands, false);
671 // Check for extra outputs created by the compilation.
672 if(const char* extra_outputs_str =
673 source.GetProperty("OBJECT_OUTPUTS"))
675 std::vector<std::string> extra_outputs;
676 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
677 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
678 eoi != extra_outputs.end(); ++eoi)
680 // Register this as an extra output for the object file rule.
681 // This will cause the object file to be rebuilt if the extra
682 // output is missing.
683 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
685 // Register this as an extra file to clean.
686 this->CleanFiles.push_back(eoi->c_str());
690 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
691 (strcmp(lang, "CXX") == 0));
692 bool do_preprocess_rules = lang_is_c_or_cxx &&
693 this->LocalGenerator->GetCreatePreprocessedSourceRules();
694 bool do_assembly_rules = lang_is_c_or_cxx &&
695 this->LocalGenerator->GetCreateAssemblySourceRules();
696 if(do_preprocess_rules || do_assembly_rules)
698 std::vector<std::string> force_depends;
699 force_depends.push_back("cmake_force");
700 std::string::size_type dot_pos = relativeObj.rfind(".");
701 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
702 dot_pos = obj.rfind(".");
703 std::string objBase = obj.substr(0, dot_pos);
705 if(do_preprocess_rules)
707 commands.clear();
708 std::string relativeObjI = relativeObjBase + ".i";
709 std::string objI = objBase + ".i";
711 std::string preprocessEcho = "Preprocessing ";
712 preprocessEcho += lang;
713 preprocessEcho += " source to ";
714 preprocessEcho += objI;
715 this->LocalGenerator->AppendEcho(
716 commands, preprocessEcho.c_str(),
717 cmLocalUnixMakefileGenerator3::EchoBuild
720 std::string preprocessRuleVar = "CMAKE_";
721 preprocessRuleVar += lang;
722 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
723 if(const char* preprocessRule =
724 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
726 std::vector<std::string> preprocessCommands;
727 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
729 std::string shellObjI =
730 this->Convert(objI.c_str(),
731 cmLocalGenerator::NONE,
732 cmLocalGenerator::SHELL).c_str();
733 vars.PreprocessedSource = shellObjI.c_str();
735 // Expand placeholders in the commands.
736 for(std::vector<std::string>::iterator i = preprocessCommands.begin();
737 i != preprocessCommands.end(); ++i)
739 this->LocalGenerator->ExpandRuleVariables(*i, vars);
742 this->LocalGenerator->CreateCDCommand
743 (preprocessCommands,
744 this->Makefile->GetStartOutputDirectory(),
745 cmLocalGenerator::HOME_OUTPUT);
746 commands.insert(commands.end(),
747 preprocessCommands.begin(),
748 preprocessCommands.end());
750 else
752 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
753 cmd += preprocessRuleVar;
754 commands.push_back(cmd);
757 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
758 relativeObjI.c_str(),
759 force_depends, commands, false);
762 if(do_assembly_rules)
764 commands.clear();
765 std::string relativeObjS = relativeObjBase + ".s";
766 std::string objS = objBase + ".s";
768 std::string assemblyEcho = "Compiling ";
769 assemblyEcho += lang;
770 assemblyEcho += " source to assembly ";
771 assemblyEcho += objS;
772 this->LocalGenerator->AppendEcho(
773 commands, assemblyEcho.c_str(),
774 cmLocalUnixMakefileGenerator3::EchoBuild
777 std::string assemblyRuleVar = "CMAKE_";
778 assemblyRuleVar += lang;
779 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
780 if(const char* assemblyRule =
781 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
783 std::vector<std::string> assemblyCommands;
784 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
786 std::string shellObjS =
787 this->Convert(objS.c_str(),
788 cmLocalGenerator::NONE,
789 cmLocalGenerator::SHELL).c_str();
790 vars.AssemblySource = shellObjS.c_str();
792 // Expand placeholders in the commands.
793 for(std::vector<std::string>::iterator i = assemblyCommands.begin();
794 i != assemblyCommands.end(); ++i)
796 this->LocalGenerator->ExpandRuleVariables(*i, vars);
799 this->LocalGenerator->CreateCDCommand
800 (assemblyCommands,
801 this->Makefile->GetStartOutputDirectory(),
802 cmLocalGenerator::HOME_OUTPUT);
803 commands.insert(commands.end(),
804 assemblyCommands.begin(),
805 assemblyCommands.end());
807 else
809 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
810 cmd += assemblyRuleVar;
811 commands.push_back(cmd);
814 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
815 relativeObjS.c_str(),
816 force_depends, commands, false);
820 // If the language needs provides-requires mode, create the
821 // corresponding targets.
822 std::string objectRequires = relativeObj;
823 objectRequires += ".requires";
824 std::vector<std::string> p_depends;
825 // always provide an empty requires target
826 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
827 objectRequires.c_str(), p_depends,
828 no_commands, true);
830 // write a build rule to recursively build what this obj provides
831 std::string objectProvides = relativeObj;
832 objectProvides += ".provides";
833 std::string temp = relativeObj;
834 temp += ".provides.build";
835 std::vector<std::string> r_commands;
836 std::string tgtMakefileName =
837 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
838 tgtMakefileName += "/build.make";
839 r_commands.push_back
840 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
841 temp.c_str()));
843 p_depends.clear();
844 p_depends.push_back(objectRequires);
845 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
846 objectProvides.c_str(), p_depends,
847 r_commands, true);
849 // write the provides.build rule dependency on the obj file
850 p_depends.clear();
851 p_depends.push_back(relativeObj);
852 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
853 temp.c_str(), p_depends, no_commands,
854 true);
857 //----------------------------------------------------------------------------
858 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
860 std::vector<std::string> depends;
861 std::vector<std::string> no_commands;
863 // Construct the name of the dependency generation target.
864 std::string depTarget =
865 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
866 depTarget += "/requires";
868 // This target drives dependency generation for all object files.
869 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
870 std::string objTarget;
871 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
872 obj != this->Objects.end(); ++obj)
874 objTarget = relPath;
875 objTarget += *obj;
876 objTarget += ".requires";
877 depends.push_back(objTarget);
880 // Write the rule.
881 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
882 depTarget.c_str(),
883 depends, no_commands, true);
886 //----------------------------------------------------------------------------
887 void cmMakefileTargetGenerator::WriteTargetCleanRules()
889 std::vector<std::string> depends;
890 std::vector<std::string> commands;
892 // Construct the clean target name.
893 std::string cleanTarget =
894 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
895 cleanTarget += "/clean";
897 // Construct the clean command.
898 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
899 *this->Target);
900 this->LocalGenerator->CreateCDCommand
901 (commands,
902 this->Makefile->GetStartOutputDirectory(),
903 cmLocalGenerator::HOME_OUTPUT);
905 // Write the rule.
906 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
907 cleanTarget.c_str(),
908 depends, commands, true);
912 //----------------------------------------------------------------------------
913 void cmMakefileTargetGenerator::WriteTargetDependRules()
915 // must write the targets depend info file
916 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
917 this->InfoFileNameFull = dir;
918 this->InfoFileNameFull += "/DependInfo.cmake";
919 this->InfoFileNameFull =
920 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
921 this->InfoFileStream =
922 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
923 this->InfoFileStream->SetCopyIfDifferent(true);
924 if(!*this->InfoFileStream)
926 return;
928 this->LocalGenerator->
929 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
931 // Store multiple output pairs in the depend info file.
932 if(!this->MultipleOutputPairs.empty())
934 *this->InfoFileStream
935 << "\n"
936 << "# Pairs of files generated by the same build rule.\n"
937 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
938 for(MultipleOutputPairsType::const_iterator pi =
939 this->MultipleOutputPairs.begin();
940 pi != this->MultipleOutputPairs.end(); ++pi)
942 *this->InfoFileStream
943 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
944 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
945 << "\n";
947 *this->InfoFileStream << " )\n\n";
950 // Store list of targets linked directly or transitively.
952 *this->InfoFileStream
953 << "\n"
954 << "# Targets to which this target links.\n"
955 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
956 std::set<cmTarget const*> emitted;
957 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
958 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
960 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
961 for(cmComputeLinkInformation::ItemVector::const_iterator
962 i = items.begin(); i != items.end(); ++i)
964 cmTarget const* linkee = i->Target;
965 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
967 cmMakefile* mf = linkee->GetMakefile();
968 cmLocalGenerator* lg = mf->GetLocalGenerator();
969 std::string di = mf->GetStartOutputDirectory();
970 di += "/";
971 di += lg->GetTargetDirectory(*linkee);
972 di += "/DependInfo.cmake";
973 *this->InfoFileStream << " \"" << di << "\"\n";
977 *this->InfoFileStream
978 << " )\n";
981 // Check for a target-specific module output directory.
982 if(const char* mdir = this->GetFortranModuleDirectory())
984 *this->InfoFileStream
985 << "\n"
986 << "# Fortran module output directory.\n"
987 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
990 // and now write the rule to use it
991 std::vector<std::string> depends;
992 std::vector<std::string> commands;
994 // Construct the name of the dependency generation target.
995 std::string depTarget =
996 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
997 depTarget += "/depend";
999 // Add a command to call CMake to scan dependencies. CMake will
1000 // touch the corresponding depends file after scanning dependencies.
1001 cmOStringStream depCmd;
1002 // TODO: Account for source file properties and directory-level
1003 // definitions when scanning for dependencies.
1004 #if !defined(_WIN32) || defined(__CYGWIN__)
1005 // This platform supports symlinks, so cmSystemTools will translate
1006 // paths. Make sure PWD is set to the original name of the home
1007 // output directory to help cmSystemTools to create the same
1008 // translation table for the dependency scanning process.
1009 depCmd << "cd "
1010 << (this->LocalGenerator->Convert(
1011 this->Makefile->GetHomeOutputDirectory(),
1012 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1013 << " && ";
1014 #endif
1015 // Generate a call this signature:
1017 // cmake -E cmake_depends <generator>
1018 // <home-src-dir> <start-src-dir>
1019 // <home-out-dir> <start-out-dir>
1020 // <dep-info> --color=$(COLOR)
1022 // This gives the dependency scanner enough information to recreate
1023 // the state of our local generator sufficiently for its needs.
1024 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1025 << this->GlobalGenerator->GetName() << "\" "
1026 << this->Convert(this->Makefile->GetHomeDirectory(),
1027 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1028 << " "
1029 << this->Convert(this->Makefile->GetStartDirectory(),
1030 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1031 << " "
1032 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1033 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1034 << " "
1035 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1036 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1037 << " "
1038 << this->Convert(this->InfoFileNameFull.c_str(),
1039 cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1040 if(this->LocalGenerator->GetColorMakefile())
1042 depCmd << " --color=$(COLOR)";
1044 commands.push_back(depCmd.str());
1046 // Make sure all custom command outputs in this target are built.
1047 if(this->CustomCommandDriver == OnDepends)
1049 this->DriveCustomCommands(depends);
1052 // Write the rule.
1053 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1054 depTarget.c_str(),
1055 depends, commands, true);
1058 //----------------------------------------------------------------------------
1059 void
1060 cmMakefileTargetGenerator
1061 ::DriveCustomCommands(std::vector<std::string>& depends)
1063 // Depend on all custom command outputs.
1064 const std::vector<cmSourceFile*>& sources =
1065 this->Target->GetSourceFiles();
1066 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1067 source != sources.end(); ++source)
1069 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1071 const std::vector<std::string>& outputs = cc->GetOutputs();
1072 for(std::vector<std::string>::const_iterator o = outputs.begin();
1073 o != outputs.end(); ++o)
1075 depends.push_back(*o);
1081 //----------------------------------------------------------------------------
1082 void cmMakefileTargetGenerator
1083 ::WriteObjectDependRules(cmSourceFile& source,
1084 std::vector<std::string>& depends)
1086 // Create the list of dependencies known at cmake time. These are
1087 // shared between the object file and dependency scanning rule.
1088 depends.push_back(source.GetFullPath());
1089 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1091 std::vector<std::string> deps;
1092 cmSystemTools::ExpandListArgument(objectDeps, deps);
1093 for(std::vector<std::string>::iterator i = deps.begin();
1094 i != deps.end(); ++i)
1096 depends.push_back(i->c_str());
1101 //----------------------------------------------------------------------------
1102 void cmMakefileTargetGenerator
1103 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1105 // Collect the commands.
1106 std::vector<std::string> commands;
1107 std::string comment = this->LocalGenerator->ConstructComment(cc);
1108 if(!comment.empty())
1110 // add in a progress call if needed
1111 this->AppendProgress(commands);
1112 if(!this->NoRuleMessages)
1114 this->LocalGenerator
1115 ->AppendEcho(commands, comment.c_str(),
1116 cmLocalUnixMakefileGenerator3::EchoGenerate);
1120 // Now append the actual user-specified commands.
1121 cmOStringStream content;
1122 this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1123 cmLocalGenerator::HOME_OUTPUT,
1124 &content);
1126 // Collect the dependencies.
1127 std::vector<std::string> depends;
1128 this->LocalGenerator->AppendCustomDepend(depends, cc);
1130 // Check whether we need to bother checking for a symbolic output.
1131 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1133 // Write the rule.
1134 const std::vector<std::string>& outputs = cc.GetOutputs();
1135 std::vector<std::string>::const_iterator o = outputs.begin();
1137 bool symbolic = false;
1138 if(need_symbolic)
1140 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1142 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1145 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1146 o->c_str(), depends, commands,
1147 symbolic);
1149 // If the rule has changed make sure the output is rebuilt.
1150 if(!symbolic)
1152 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1156 // Write rules to drive building any outputs beyond the first.
1157 const char* in = o->c_str();
1158 for(++o; o != outputs.end(); ++o)
1160 bool symbolic = false;
1161 if(need_symbolic)
1163 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1165 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1168 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1171 // Setup implicit dependency scanning.
1172 for(cmCustomCommand::ImplicitDependsList::const_iterator
1173 idi = cc.GetImplicitDepends().begin();
1174 idi != cc.GetImplicitDepends().end(); ++idi)
1176 std::string objFullPath =
1177 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1178 std::string srcFullPath =
1179 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1180 this->LocalGenerator->
1181 AddImplicitDepends(*this->Target, idi->first.c_str(),
1182 objFullPath.c_str(),
1183 srcFullPath.c_str());
1187 //----------------------------------------------------------------------------
1188 void
1189 cmMakefileTargetGenerator
1190 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1192 // Add a rule to build the primary output if the extra output needs
1193 // to be created.
1194 std::vector<std::string> commands;
1195 std::vector<std::string> depends;
1196 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1197 if(!emptyCommand.empty())
1199 commands.push_back(emptyCommand);
1201 depends.push_back(in);
1202 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1203 out, depends, commands,
1204 symbolic);
1206 // Register the extra output as paired with the first output so that
1207 // the check-build-system step will remove the primary output if any
1208 // extra outputs are missing. This forces the rule to regenerate
1209 // all outputs.
1210 this->AddMultipleOutputPair(out, in);
1213 //----------------------------------------------------------------------------
1214 void
1215 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1217 this->NumberOfProgressActions++;
1218 if(this->NoRuleMessages)
1220 return;
1222 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1223 progressDir += cmake::GetCMakeFilesDirectory();
1224 cmOStringStream progCmd;
1225 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1226 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1227 cmLocalGenerator::FULL,
1228 cmLocalGenerator::SHELL);
1229 progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1230 commands.push_back(progCmd.str());
1233 //----------------------------------------------------------------------------
1234 void
1235 cmMakefileTargetGenerator
1236 ::WriteObjectsVariable(std::string& variableName,
1237 std::string& variableNameExternal)
1239 // Write a make variable assignment that lists all objects for the
1240 // target.
1241 variableName =
1242 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1243 "_OBJECTS");
1244 *this->BuildFileStream
1245 << "# Object files for target " << this->Target->GetName() << "\n"
1246 << variableName.c_str() << " =";
1247 std::string object;
1248 const char* objName =
1249 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1250 const char* lineContinue =
1251 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1252 if(!lineContinue)
1254 lineContinue = "\\";
1256 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1257 i != this->Objects.end(); ++i)
1259 *this->BuildFileStream << " " << lineContinue << "\n";
1260 if(objName)
1262 *this->BuildFileStream <<
1263 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1264 cmLocalGenerator::MAKEFILE);
1266 else
1268 *this->BuildFileStream <<
1269 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1272 *this->BuildFileStream << "\n";
1274 // Write a make variable assignment that lists all external objects
1275 // for the target.
1276 variableNameExternal =
1277 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1278 "_EXTERNAL_OBJECTS");
1279 *this->BuildFileStream
1280 << "\n"
1281 << "# External object files for target "
1282 << this->Target->GetName() << "\n"
1283 << variableNameExternal.c_str() << " =";
1284 for(std::vector<std::string>::const_iterator i =
1285 this->ExternalObjects.begin();
1286 i != this->ExternalObjects.end(); ++i)
1288 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1289 *this->BuildFileStream
1290 << " " << lineContinue << "\n"
1291 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1292 if(objName)
1294 *this->BuildFileStream <<
1295 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1296 cmLocalGenerator::MAKEFILE);
1298 else
1300 *this->BuildFileStream <<
1301 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1304 *this->BuildFileStream << "\n" << "\n";
1307 //----------------------------------------------------------------------------
1308 void
1309 cmMakefileTargetGenerator
1310 ::WriteObjectsString(std::string& buildObjs)
1312 std::vector<std::string> objStrings;
1313 this->WriteObjectsStrings(objStrings);
1314 buildObjs = objStrings[0];
1317 //----------------------------------------------------------------------------
1318 class cmMakefileTargetGeneratorObjectStrings
1320 public:
1321 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1322 cmMakefile* mf,
1323 cmLocalUnixMakefileGenerator3* lg,
1324 std::string::size_type limit):
1325 Strings(strings), Makefile(mf), LocalGenerator(lg), LengthLimit(limit)
1327 this->Space = "";
1329 void Feed(std::string const& obj)
1331 // Construct the name of the next object.
1332 this->NextObject =
1333 this->LocalGenerator->Convert(obj.c_str(),
1334 cmLocalGenerator::START_OUTPUT,
1335 cmLocalGenerator::SHELL);
1337 // Roll over to next string if the limit will be exceeded.
1338 if(this->LengthLimit != std::string::npos &&
1339 (this->CurrentString.length() + 1 + this->NextObject.length()
1340 > this->LengthLimit))
1342 this->Strings.push_back(this->CurrentString);
1343 this->CurrentString = "";
1344 this->Space = "";
1347 // Separate from previous object.
1348 this->CurrentString += this->Space;
1349 this->Space = " ";
1351 // Append this object.
1352 this->CurrentString += this->NextObject;
1354 void Done()
1356 this->Strings.push_back(this->CurrentString);
1358 private:
1359 std::vector<std::string>& Strings;
1360 cmMakefile* Makefile;
1361 cmLocalUnixMakefileGenerator3* LocalGenerator;
1362 std::string::size_type LengthLimit;
1363 std::string CurrentString;
1364 std::string NextObject;
1365 const char* Space;
1368 //----------------------------------------------------------------------------
1369 void
1370 cmMakefileTargetGenerator
1371 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1372 std::string::size_type limit)
1374 cmMakefileTargetGeneratorObjectStrings
1375 helper(objStrings, this->Makefile, this->LocalGenerator, limit);
1376 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1377 i != this->Objects.end(); ++i)
1379 helper.Feed(*i);
1381 for(std::vector<std::string>::const_iterator i =
1382 this->ExternalObjects.begin();
1383 i != this->ExternalObjects.end(); ++i)
1385 helper.Feed(*i);
1387 helper.Done();
1390 //----------------------------------------------------------------------------
1391 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1392 bool relink)
1394 // Compute the name of the driver target.
1395 std::string dir =
1396 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1397 std::string buildTargetRuleName = dir;
1398 buildTargetRuleName += relink?"/preinstall":"/build";
1399 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1400 cmLocalGenerator::HOME_OUTPUT,
1401 cmLocalGenerator::UNCHANGED);
1403 // Build the list of target outputs to drive.
1404 std::vector<std::string> depends;
1405 if(main_output)
1407 depends.push_back(main_output);
1410 const char* comment = 0;
1411 if(relink)
1413 // Setup the comment for the preinstall driver.
1414 comment = "Rule to relink during preinstall.";
1416 else
1418 // Setup the comment for the main build driver.
1419 comment = "Rule to build all files generated by this target.";
1421 // Make sure all custom command outputs in this target are built.
1422 if(this->CustomCommandDriver == OnBuild)
1424 this->DriveCustomCommands(depends);
1427 // Make sure the extra files are built.
1428 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1429 i != this->ExtraFiles.end(); ++i)
1431 depends.push_back(*i);
1435 // Write the driver rule.
1436 std::vector<std::string> no_commands;
1437 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1438 buildTargetRuleName.c_str(),
1439 depends, no_commands, true);
1442 //----------------------------------------------------------------------------
1443 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1445 #ifndef __APPLE__
1446 return std::string();
1447 #else
1448 std::set<cmStdString> emitted;
1449 emitted.insert("/System/Library/Frameworks");
1450 std::vector<std::string> includes;
1451 this->LocalGenerator->GetIncludeDirectories(includes);
1452 std::vector<std::string>::iterator i;
1453 // check all include directories for frameworks as this
1454 // will already have added a -F for the framework
1455 for(i = includes.begin(); i != includes.end(); ++i)
1457 if(this->Target->NameResolvesToFramework(i->c_str()))
1459 std::string frameworkDir = *i;
1460 frameworkDir += "/../";
1461 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1462 emitted.insert(frameworkDir);
1466 std::string flags;
1467 std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1468 for(i = frameworks.begin();
1469 i != frameworks.end(); ++i)
1471 if(emitted.insert(*i).second)
1473 flags += "-F";
1474 flags += this->Convert(i->c_str(),
1475 cmLocalGenerator::START_OUTPUT,
1476 cmLocalGenerator::SHELL, true);
1477 flags += " ";
1480 return flags;
1481 #endif
1484 //----------------------------------------------------------------------------
1485 void cmMakefileTargetGenerator
1486 ::AppendTargetDepends(std::vector<std::string>& depends)
1488 // Static libraries never depend on anything for linking.
1489 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1491 return;
1494 // Loop over all library dependencies.
1495 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1496 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1498 std::vector<std::string> const& libDeps = cli->GetDepends();
1499 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1500 j != libDeps.end(); ++j)
1502 depends.push_back(*j);
1507 //----------------------------------------------------------------------------
1508 void cmMakefileTargetGenerator
1509 ::CloseFileStreams()
1511 delete this->BuildFileStream;
1512 delete this->InfoFileStream;
1513 delete this->FlagFileStream;
1516 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1517 const char* linkLang,
1518 std::string& linkFlags)
1520 // check for language flags that are not allowed at link time, and
1521 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1522 // which fails, there may be more]
1524 std::string removeFlags = "CMAKE_";
1525 removeFlags += linkLang;
1526 removeFlags += flagVar;
1527 std::string removeflags =
1528 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1529 std::vector<std::string> removeList;
1530 cmSystemTools::ExpandListArgument(removeflags, removeList);
1531 for(std::vector<std::string>::iterator i = removeList.begin();
1532 i != removeList.end(); ++i)
1534 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1538 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total,
1539 unsigned long &current)
1541 cmGeneratedFileStream *progressFileStream =
1542 new cmGeneratedFileStream(this->ProgressFileNameFull.c_str());
1543 if(!progressFileStream)
1545 return;
1548 unsigned long num;
1549 unsigned long i;
1550 for (i = 1; i <= this->NumberOfProgressActions; ++i)
1552 *progressFileStream
1553 << "CMAKE_PROGRESS_" << i << " = ";
1554 if (total <= 100)
1556 num = i + current;
1557 *progressFileStream << num;
1558 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1559 .push_back(num);
1561 else if (((i+current)*100)/total > ((i-1+current)*100)/total)
1563 num = ((i+current)*100)/total;
1564 *progressFileStream << num;
1565 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1566 .push_back(num);
1568 *progressFileStream << "\n";
1570 *progressFileStream << "\n";
1571 current += this->NumberOfProgressActions;
1572 delete progressFileStream;
1575 //----------------------------------------------------------------------------
1576 void
1577 cmMakefileTargetGenerator
1578 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1580 MultipleOutputPairsType::value_type p(depender, dependee);
1581 this->MultipleOutputPairs.insert(p);
1584 //----------------------------------------------------------------------------
1585 void
1586 cmMakefileTargetGenerator
1587 ::CreateLinkScript(const char* name,
1588 std::vector<std::string> const& link_commands,
1589 std::vector<std::string>& makefile_commands,
1590 std::vector<std::string>& makefile_depends)
1592 // Create the link script file.
1593 std::string linkScriptName = this->TargetBuildDirectoryFull;
1594 linkScriptName += "/";
1595 linkScriptName += name;
1596 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1597 linkScriptStream.SetCopyIfDifferent(true);
1598 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1599 cmd != link_commands.end(); ++cmd)
1601 // Do not write out empty commands or commands beginning in the
1602 // shell no-op ":".
1603 if(!cmd->empty() && (*cmd)[0] != ':')
1605 linkScriptStream << *cmd << "\n";
1609 // Create the makefile command to invoke the link script.
1610 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1611 link_command += this->Convert(linkScriptName.c_str(),
1612 cmLocalGenerator::START_OUTPUT,
1613 cmLocalGenerator::SHELL);
1614 link_command += " --verbose=$(VERBOSE)";
1615 makefile_commands.push_back(link_command);
1616 makefile_depends.push_back(linkScriptName);
1619 //----------------------------------------------------------------------------
1620 std::string
1621 cmMakefileTargetGenerator
1622 ::CreateResponseFile(const char* name, std::string const& options,
1623 std::vector<std::string>& makefile_depends)
1625 // Create the response file.
1626 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1627 responseFileNameFull += "/";
1628 responseFileNameFull += name;
1629 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1630 responseStream.SetCopyIfDifferent(true);
1631 responseStream << options << "\n";
1633 // Add a dependency so the target will rebuild when the set of
1634 // objects changes.
1635 makefile_depends.push_back(responseFileNameFull);
1637 // Construct the name to be used on the command line.
1638 std::string responseFileName = this->TargetBuildDirectory;
1639 responseFileName += "/";
1640 responseFileName += name;
1641 return responseFileName;
1644 //----------------------------------------------------------------------------
1645 void
1646 cmMakefileTargetGenerator
1647 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1648 bool useResponseFile, std::string& buildObjs,
1649 std::vector<std::string>& makefile_depends)
1651 std::string variableName;
1652 std::string variableNameExternal;
1653 this->WriteObjectsVariable(variableName, variableNameExternal);
1654 if(useResponseFile)
1656 // MSVC response files cannot exceed 128K.
1657 std::string::size_type const responseFileLimit = 131000;
1659 // Construct the individual object list strings.
1660 std::vector<std::string> object_strings;
1661 this->WriteObjectsStrings(object_strings, responseFileLimit);
1663 // Write a response file for each string.
1664 const char* sep = "";
1665 for(unsigned int i = 0; i < object_strings.size(); ++i)
1667 // Number the response files.
1668 char rsp[32];
1669 sprintf(rsp, "objects%u.rsp", i+1);
1671 // Create this response file.
1672 std::string objects_rsp =
1673 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1675 // Separate from previous response file references.
1676 buildObjs += sep;
1677 sep = " ";
1679 // Reference the response file.
1680 buildObjs += "@";
1681 buildObjs += this->Convert(objects_rsp.c_str(),
1682 cmLocalGenerator::NONE,
1683 cmLocalGenerator::SHELL);
1686 else if(useLinkScript)
1688 if(!useArchiveRules)
1690 this->WriteObjectsString(buildObjs);
1693 else
1695 buildObjs = "$(";
1696 buildObjs += variableName;
1697 buildObjs += ") $(";
1698 buildObjs += variableNameExternal;
1699 buildObjs += ")";
1703 //----------------------------------------------------------------------------
1704 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1706 // Compute the module directory.
1707 if(!this->FortranModuleDirectoryComputed)
1709 const char* target_mod_dir =
1710 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1711 const char* moddir_flag =
1712 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1713 if(target_mod_dir && moddir_flag)
1715 // Compute the full path to the module directory.
1716 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1718 // Already a full path.
1719 this->FortranModuleDirectory = target_mod_dir;
1721 else
1723 // Interpret relative to the current output directory.
1724 this->FortranModuleDirectory =
1725 this->Makefile->GetCurrentOutputDirectory();
1726 this->FortranModuleDirectory += "/";
1727 this->FortranModuleDirectory += target_mod_dir;
1730 // Make sure the module output directory exists.
1731 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1733 this->FortranModuleDirectoryComputed = true;
1736 // Return the computed directory.
1737 if(this->FortranModuleDirectory.empty())
1739 return 0;
1741 else
1743 return this->FortranModuleDirectory.c_str();
1747 //----------------------------------------------------------------------------
1748 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1750 // Add a module output directory flag if necessary.
1751 if(const char* mod_dir = this->GetFortranModuleDirectory())
1753 const char* moddir_flag =
1754 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1755 std::string modflag = moddir_flag;
1756 modflag += this->Convert(mod_dir,
1757 cmLocalGenerator::START_OUTPUT,
1758 cmLocalGenerator::SHELL);
1759 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1762 // If there is a separate module path flag then duplicate the
1763 // include path with it. This compiler does not search the include
1764 // path for modules.
1765 if(const char* modpath_flag =
1766 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1768 std::vector<std::string> includes;
1769 this->LocalGenerator->GetIncludeDirectories(includes);
1770 for(std::vector<std::string>::const_iterator idi = includes.begin();
1771 idi != includes.end(); ++idi)
1773 std::string flg = modpath_flag;
1774 flg += this->Convert(idi->c_str(),
1775 cmLocalGenerator::NONE,
1776 cmLocalGenerator::SHELL);
1777 this->LocalGenerator->AppendFlags(flags, flg.c_str());