BUG: Fix find_* search order with path suffixes
[cmake.git] / Source / cmMakefileTargetGenerator.cxx
blobb8f4e4721d1ec90bce5b9dce244832b329bd4cf9
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-10-09 19:30:07 $
7 Version: $Revision: 1.106 $
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());
51 cmMakefileTargetGenerator *
52 cmMakefileTargetGenerator::New(cmTarget *tgt)
54 cmMakefileTargetGenerator *result = 0;
56 switch (tgt->GetType())
58 case cmTarget::EXECUTABLE:
59 result = new cmMakefileExecutableTargetGenerator(tgt);
60 break;
61 case cmTarget::STATIC_LIBRARY:
62 case cmTarget::SHARED_LIBRARY:
63 case cmTarget::MODULE_LIBRARY:
64 result = new cmMakefileLibraryTargetGenerator(tgt);
65 break;
66 case cmTarget::UTILITY:
67 result = new cmMakefileUtilityTargetGenerator(tgt);
68 break;
69 default:
70 return result;
71 // break; /* unreachable */
73 return result;
76 //----------------------------------------------------------------------------
77 void cmMakefileTargetGenerator::CreateRuleFile()
79 // Create a directory for this target.
80 this->TargetBuildDirectory =
81 this->LocalGenerator->GetTargetDirectory(*this->Target);
82 this->TargetBuildDirectoryFull =
83 this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
84 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
86 // Construct the rule file name.
87 this->BuildFileName = this->TargetBuildDirectory;
88 this->BuildFileName += "/build.make";
89 this->BuildFileNameFull = this->TargetBuildDirectoryFull;
90 this->BuildFileNameFull += "/build.make";
92 // Construct the rule file name.
93 this->ProgressFileName = this->TargetBuildDirectory;
94 this->ProgressFileName += "/progress.make";
95 this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
96 this->ProgressFileNameFull += "/progress.make";
98 // reset the progress count
99 this->NumberOfProgressActions = 0;
101 // Open the rule file. This should be copy-if-different because the
102 // rules may depend on this file itself.
103 this->BuildFileStream =
104 new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
105 this->BuildFileStream->SetCopyIfDifferent(true);
106 if(!this->BuildFileStream)
108 return;
110 this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
111 this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
114 //----------------------------------------------------------------------------
115 void cmMakefileTargetGenerator::WriteTargetBuildRules()
117 // write the custom commands for this target
118 // Look for files registered for cleaning in this directory.
119 if(const char* additional_clean_files =
120 this->Makefile->GetProperty
121 ("ADDITIONAL_MAKE_CLEAN_FILES"))
123 cmSystemTools::ExpandListArgument(additional_clean_files,
124 this->CleanFiles);
127 // add custom commands to the clean rules?
128 const char* clean_no_custom =
129 this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
130 bool clean = cmSystemTools::IsOff(clean_no_custom);
132 // First generate the object rule files. Save a list of all object
133 // files for this target.
134 const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
135 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
136 source != sources.end(); ++source)
138 cmTarget::SourceFileFlags tsFlags =
139 this->Target->GetTargetSourceFileFlags(*source);
140 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
142 this->GenerateCustomRuleFile(*cc);
143 if (clean)
145 const std::vector<std::string>& outputs = cc->GetOutputs();
146 for(std::vector<std::string>::const_iterator o = outputs.begin();
147 o != outputs.end(); ++o)
149 this->CleanFiles.push_back
150 (this->Convert(o->c_str(),
151 cmLocalGenerator::START_OUTPUT,
152 cmLocalGenerator::UNCHANGED));
156 else if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
158 this->WriteMacOSXContentRules(*(*source), tsFlags.MacFolder);
160 else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
162 if(!this->GlobalGenerator->IgnoreFile
163 ((*source)->GetExtension().c_str()))
165 // Generate this object file's rule file.
166 this->WriteObjectRuleFiles(*(*source));
168 else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
170 // This is an external object file. Just add it.
171 this->ExternalObjects.push_back((*source)->GetFullPath());
173 else
175 // We only get here if a source file is not an external object
176 // and has an extension that is listed as an ignored file type
177 // for this language. No message or diagnosis should be
178 // given.
185 //----------------------------------------------------------------------------
186 void cmMakefileTargetGenerator::WriteCommonCodeRules()
188 // Include the dependencies for the target.
189 std::string dependFileNameFull = this->TargetBuildDirectoryFull;
190 dependFileNameFull += "/depend.make";
191 *this->BuildFileStream
192 << "# Include any dependencies generated for this target.\n"
193 << this->LocalGenerator->IncludeDirective << " "
194 << this->Convert(dependFileNameFull.c_str(),
195 cmLocalGenerator::HOME_OUTPUT,
196 cmLocalGenerator::MAKEFILE)
197 << "\n\n";
199 // Include the progress variables for the target.
200 *this->BuildFileStream
201 << "# Include the progress variables for this target.\n"
202 << this->LocalGenerator->IncludeDirective << " "
203 << this->Convert(this->ProgressFileNameFull.c_str(),
204 cmLocalGenerator::HOME_OUTPUT,
205 cmLocalGenerator::MAKEFILE)
206 << "\n\n";
208 // make sure the depend file exists
209 if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
211 // Write an empty dependency file.
212 cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
213 depFileStream
214 << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
215 << "# This may be replaced when dependencies are built." << std::endl;
218 // Open the flags file. This should be copy-if-different because the
219 // rules may depend on this file itself.
220 this->FlagFileNameFull = this->TargetBuildDirectoryFull;
221 this->FlagFileNameFull += "/flags.make";
222 this->FlagFileStream =
223 new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
224 this->FlagFileStream->SetCopyIfDifferent(true);
225 if(!this->FlagFileStream)
227 return;
229 this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
231 // Include the flags for the target.
232 *this->BuildFileStream
233 << "# Include the compile flags for this target's objects.\n"
234 << this->LocalGenerator->IncludeDirective << " "
235 << this->Convert(this->FlagFileNameFull.c_str(),
236 cmLocalGenerator::HOME_OUTPUT,
237 cmLocalGenerator::MAKEFILE)
238 << "\n\n";
241 //----------------------------------------------------------------------------
242 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
244 // write language flags for target
245 std::set<cmStdString> languages;
246 this->Target->GetLanguages(languages);
247 // put the compiler in the rules.make file so that if it changes
248 // things rebuild
249 for(std::set<cmStdString>::const_iterator l = languages.begin();
250 l != languages.end(); ++l)
252 cmStdString compiler = "CMAKE_";
253 compiler += *l;
254 compiler += "_COMPILER";
255 *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
256 this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
259 for(std::set<cmStdString>::const_iterator l = languages.begin();
260 l != languages.end(); ++l)
262 const char *lang = l->c_str();
263 std::string flags;
264 std::string defines;
265 bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
266 (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
268 // Add the export symbol definition for shared library objects.
269 if(const char* exportMacro = this->Target->GetExportMacro())
271 flags += "-D";
272 flags += exportMacro;
275 // Add preprocessor definitions for this target and configuration.
276 this->LocalGenerator->AppendDefines
277 (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang);
278 this->LocalGenerator->AppendDefines
279 (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang);
280 std::string defPropName = "COMPILE_DEFINITIONS_";
281 defPropName +=
282 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
283 this->LocalGenerator->AppendDefines
284 (defines, this->Makefile->GetProperty(defPropName.c_str()), lang);
285 this->LocalGenerator->AppendDefines
286 (defines, this->Target->GetProperty(defPropName.c_str()), lang);
288 // Add language-specific flags.
289 this->LocalGenerator
290 ->AddLanguageFlags(flags, lang,
291 this->LocalGenerator->ConfigurationName.c_str());
293 // Fortran-specific flags computed for this target.
294 if(*l == "Fortran")
296 this->AddFortranFlags(flags);
299 // Add shared-library flags if needed.
300 this->LocalGenerator->AddSharedFlags(flags, lang, shared);
302 // Add include directory flags.
303 this->LocalGenerator->
304 AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
305 // Add include directory flags.
306 this->LocalGenerator->
307 AppendFlags(flags,this->GetFrameworkFlags().c_str());
309 *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
310 *this->FlagFileStream << lang << "_DEFINES = " << defines << "\n\n";
313 // Add target-specific flags.
314 if(this->Target->GetProperty("COMPILE_FLAGS"))
316 std::string flags;
317 this->LocalGenerator->AppendFlags
318 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
319 *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
323 //----------------------------------------------------------------------------
324 void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source,
325 const char* pkgloc)
327 // Skip OS X content when not building a Framework or Bundle.
328 if(this->MacContentDirectory.empty())
330 return;
333 // Construct the full path to the content subdirectory.
334 std::string macdir = this->MacContentDirectory;
335 macdir += pkgloc;
336 cmSystemTools::MakeDirectory(macdir.c_str());
338 // Record use of this content location. Only the first level
339 // directory is needed.
341 std::string loc = pkgloc;
342 loc = loc.substr(0, loc.find('/'));
343 this->MacContentFolders.insert(loc);
346 // Get the input file location.
347 std::string input = source.GetFullPath();
349 // Get the output file location.
350 std::string output = macdir;
351 output += "/";
352 output += cmSystemTools::GetFilenameName(input);
353 this->CleanFiles.push_back(this->Convert(output.c_str(),
354 cmLocalGenerator::START_OUTPUT));
355 output = this->Convert(output.c_str(), cmLocalGenerator::HOME_OUTPUT);
357 // Create a rule to copy the content into the bundle.
358 std::vector<std::string> depends;
359 std::vector<std::string> commands;
360 depends.push_back(input);
361 std::string copyEcho = "Copying OS X content ";
362 copyEcho += output;
363 this->LocalGenerator->AppendEcho(commands, copyEcho.c_str(),
364 cmLocalUnixMakefileGenerator3::EchoBuild);
365 std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
366 copyCommand += this->Convert(input.c_str(),
367 cmLocalGenerator::NONE,
368 cmLocalGenerator::SHELL);
369 copyCommand += " ";
370 copyCommand += this->Convert(output.c_str(),
371 cmLocalGenerator::NONE,
372 cmLocalGenerator::SHELL);
373 commands.push_back(copyCommand);
374 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
375 output.c_str(),
376 depends, commands, false);
377 this->ExtraFiles.insert(output);
380 //----------------------------------------------------------------------------
381 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
383 // Identify the language of the source file.
384 const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
385 if(!lang)
387 // don't know anything about this file so skip it
388 return;
391 // Get the full path name of the object file.
392 bool hasSourceExtension;
393 std::string objNoTargetDir;
394 std::string obj =
395 this->LocalGenerator->GetObjectFileName(*this->Target, source,
396 &objNoTargetDir,
397 &hasSourceExtension);
399 // Avoid generating duplicate rules.
400 if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
402 this->ObjectFiles.insert(obj);
404 else
406 cmOStringStream err;
407 err << "Warning: Source file \""
408 << source.GetFullPath()
409 << "\" is listed multiple times for target \""
410 << this->Target->GetName()
411 << "\".";
412 cmSystemTools::Message(err.str().c_str(), "Warning");
413 return;
416 // Create the directory containing the object file. This may be a
417 // subdirectory under the target's directory.
418 std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
419 cmSystemTools::MakeDirectory
420 (this->LocalGenerator->ConvertToFullPath(dir).c_str());
422 // Save this in the target's list of object files.
423 this->Objects.push_back(obj);
424 this->CleanFiles.push_back(obj);
426 // TODO: Remove
427 //std::string relativeObj
428 //= this->LocalGenerator->GetHomeRelativeOutputPath();
429 //relativeObj += obj;
431 // we compute some depends when writing the depend.make that we will also
432 // use in the build.make, same with depMakeFile
433 std::vector<std::string> depends;
434 std::string depMakeFile;
436 // generate the build rule file
437 this->WriteObjectBuildFile(obj, lang, source, depends);
439 // The object file should be checked for dependency integrity.
440 std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
441 objFullPath += "/";
442 objFullPath += obj;
443 objFullPath =
444 this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
445 std::string srcFullPath =
446 this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
447 this->LocalGenerator->
448 AddImplicitDepends(*this->Target, lang,
449 objFullPath.c_str(),
450 srcFullPath.c_str());
452 // add this to the list of objects for this local generator
453 if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
455 objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
457 cmLocalUnixMakefileGenerator3::LocalObjectInfo& info =
458 this->LocalGenerator->LocalObjectFiles[objNoTargetDir];
459 info.HasSourceExtension = hasSourceExtension;
460 info.push_back(
461 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target, lang)
465 //----------------------------------------------------------------------------
466 void
467 cmMakefileTargetGenerator
468 ::WriteObjectBuildFile(std::string &obj,
469 const char *lang,
470 cmSourceFile& source,
471 std::vector<std::string>& depends)
473 this->LocalGenerator->AppendRuleDepend(depends,
474 this->FlagFileNameFull.c_str());
476 // generate the depend scanning rule
477 this->WriteObjectDependRules(source, depends);
479 std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
480 relativeObj += obj;
481 // Write the build rule.
483 // Build the set of compiler flags.
484 std::string flags;
486 // Add language-specific flags.
487 std::string langFlags = "$(";
488 langFlags += lang;
489 langFlags += "_FLAGS)";
490 this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
492 // Add target-specific flags.
493 if(this->Target->GetProperty("COMPILE_FLAGS"))
495 std::string langIncludeExpr = "CMAKE_";
496 langIncludeExpr += lang;
497 langIncludeExpr += "_FLAG_REGEX";
498 const char* regex = this->Makefile->
499 GetDefinition(langIncludeExpr.c_str());
500 if(regex)
502 cmsys::RegularExpression r(regex);
503 std::vector<std::string> args;
504 cmSystemTools::ParseWindowsCommandLine(
505 this->Target->GetProperty("COMPILE_FLAGS"),
506 args);
507 for(std::vector<std::string>::iterator i = args.begin();
508 i != args.end(); ++i)
510 if(r.find(i->c_str()))
512 this->LocalGenerator->AppendFlags
513 (flags, i->c_str());
517 else
519 this->LocalGenerator->AppendFlags
520 (flags, this->Target->GetProperty("COMPILE_FLAGS"));
524 // Add flags from source file properties.
525 if (source.GetProperty("COMPILE_FLAGS"))
527 this->LocalGenerator->AppendFlags
528 (flags, source.GetProperty("COMPILE_FLAGS"));
529 *this->FlagFileStream << "# Custom flags: "
530 << relativeObj << "_FLAGS = "
531 << source.GetProperty("COMPILE_FLAGS")
532 << "\n"
533 << "\n";
536 // Add language-specific defines.
537 std::string defines = "$(";
538 defines += lang;
539 defines += "_DEFINES)";
541 // Add source-sepcific preprocessor definitions.
542 if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
544 this->LocalGenerator->AppendDefines(defines, compile_defs, lang);
545 *this->FlagFileStream << "# Custom defines: "
546 << relativeObj << "_DEFINES = "
547 << compile_defs << "\n"
548 << "\n";
550 std::string configUpper =
551 cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
552 std::string defPropName = "COMPILE_DEFINITIONS_";
553 defPropName += configUpper;
554 if(const char* config_compile_defs =
555 source.GetProperty(defPropName.c_str()))
557 this->LocalGenerator->AppendDefines(defines, config_compile_defs, lang);
558 *this->FlagFileStream
559 << "# Custom defines: "
560 << relativeObj << "_DEFINES_" << configUpper
561 << " = " << config_compile_defs << "\n"
562 << "\n";
565 // Get the output paths for source and object files.
566 std::string sourceFile = source.GetFullPath();
567 if(this->LocalGenerator->UseRelativePaths)
569 sourceFile = this->Convert(sourceFile.c_str(),
570 cmLocalGenerator::START_OUTPUT);
572 sourceFile = this->Convert(sourceFile.c_str(),
573 cmLocalGenerator::NONE,
574 cmLocalGenerator::SHELL);
575 std::string objectFile = this->Convert(obj.c_str(),
576 cmLocalGenerator::START_OUTPUT,
577 cmLocalGenerator::SHELL);
579 // Construct the build message.
580 std::vector<std::string> no_commands;
581 std::vector<std::string> commands;
583 // add in a progress call if needed
584 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
585 progressDir += cmake::GetCMakeFilesDirectory();
586 cmOStringStream progCmd;
587 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
588 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
589 cmLocalGenerator::FULL,
590 cmLocalGenerator::SHELL);
591 this->NumberOfProgressActions++;
592 progCmd << " $(CMAKE_PROGRESS_"
593 << this->NumberOfProgressActions
594 << ")";
595 commands.push_back(progCmd.str());
597 std::string buildEcho = "Building ";
598 buildEcho += lang;
599 buildEcho += " object ";
600 buildEcho += relativeObj;
601 this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
602 cmLocalUnixMakefileGenerator3::EchoBuild);
604 // Construct the compile rules.
605 std::string compileRuleVar = "CMAKE_";
606 compileRuleVar += lang;
607 compileRuleVar += "_COMPILE_OBJECT";
608 std::string compileRule =
609 this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
610 std::vector<std::string> compileCommands;
611 cmSystemTools::ExpandListArgument(compileRule, compileCommands);
613 // Change the command working directory to the local build tree.
614 this->LocalGenerator->CreateCDCommand
615 (compileCommands,
616 this->Makefile->GetStartOutputDirectory(),
617 cmLocalGenerator::HOME_OUTPUT);
618 commands.insert(commands.end(),
619 compileCommands.begin(), compileCommands.end());
621 std::string targetOutPathPDB;
623 std::string targetFullPathPDB;
624 const char* configName = this->LocalGenerator->ConfigurationName.c_str();
625 if(this->Target->GetType() == cmTarget::EXECUTABLE ||
626 this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
627 this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
628 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
630 targetFullPathPDB = this->Target->GetDirectory();
631 targetFullPathPDB += "/";
632 targetFullPathPDB += this->Target->GetPDBName(configName);
634 targetOutPathPDB =
635 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::FULL,
636 cmLocalGenerator::SHELL);
638 cmLocalGenerator::RuleVariables vars;
639 vars.Language = lang;
640 vars.TargetPDB = targetOutPathPDB.c_str();
641 vars.Source = sourceFile.c_str();
642 std::string shellObj =
643 this->Convert(obj.c_str(),
644 cmLocalGenerator::NONE,
645 cmLocalGenerator::SHELL).c_str();
646 vars.Object = shellObj.c_str();
647 std::string objectDir = cmSystemTools::GetFilenamePath(obj);
648 objectDir = this->Convert(objectDir.c_str(),
649 cmLocalGenerator::START_OUTPUT,
650 cmLocalGenerator::SHELL);
651 vars.ObjectDir = objectDir.c_str();
652 vars.Flags = flags.c_str();
653 vars.Defines = defines.c_str();
655 // Expand placeholders in the commands.
656 for(std::vector<std::string>::iterator i = commands.begin();
657 i != commands.end(); ++i)
659 this->LocalGenerator->ExpandRuleVariables(*i, vars);
663 // Write the rule.
664 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
665 relativeObj.c_str(),
666 depends, commands, false);
668 // Check for extra outputs created by the compilation.
669 if(const char* extra_outputs_str =
670 source.GetProperty("OBJECT_OUTPUTS"))
672 std::vector<std::string> extra_outputs;
673 cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
674 for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
675 eoi != extra_outputs.end(); ++eoi)
677 // Register this as an extra output for the object file rule.
678 // This will cause the object file to be rebuilt if the extra
679 // output is missing.
680 this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
682 // Register this as an extra file to clean.
683 this->CleanFiles.push_back(eoi->c_str());
687 bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
688 (strcmp(lang, "CXX") == 0));
689 bool do_preprocess_rules = lang_is_c_or_cxx &&
690 this->LocalGenerator->GetCreatePreprocessedSourceRules();
691 bool do_assembly_rules = lang_is_c_or_cxx &&
692 this->LocalGenerator->GetCreateAssemblySourceRules();
693 if(do_preprocess_rules || do_assembly_rules)
695 std::vector<std::string> force_depends;
696 force_depends.push_back("cmake_force");
697 std::string::size_type dot_pos = relativeObj.rfind(".");
698 std::string relativeObjBase = relativeObj.substr(0, dot_pos);
699 dot_pos = obj.rfind(".");
700 std::string objBase = obj.substr(0, dot_pos);
702 if(do_preprocess_rules)
704 commands.clear();
705 std::string relativeObjI = relativeObjBase + ".i";
706 std::string objI = objBase + ".i";
708 std::string preprocessEcho = "Preprocessing ";
709 preprocessEcho += lang;
710 preprocessEcho += " source to ";
711 preprocessEcho += objI;
712 this->LocalGenerator->AppendEcho(
713 commands, preprocessEcho.c_str(),
714 cmLocalUnixMakefileGenerator3::EchoBuild
717 std::string preprocessRuleVar = "CMAKE_";
718 preprocessRuleVar += lang;
719 preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
720 if(const char* preprocessRule =
721 this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
723 std::vector<std::string> preprocessCommands;
724 cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
725 this->LocalGenerator->CreateCDCommand
726 (preprocessCommands,
727 this->Makefile->GetStartOutputDirectory(),
728 cmLocalGenerator::HOME_OUTPUT);
729 commands.insert(commands.end(),
730 preprocessCommands.begin(),
731 preprocessCommands.end());
733 std::string shellObjI =
734 this->Convert(objI.c_str(),
735 cmLocalGenerator::NONE,
736 cmLocalGenerator::SHELL).c_str();
737 vars.PreprocessedSource = shellObjI.c_str();
739 // Expand placeholders in the commands.
740 for(std::vector<std::string>::iterator i = commands.begin();
741 i != commands.end(); ++i)
743 this->LocalGenerator->ExpandRuleVariables(*i, vars);
746 else
748 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
749 cmd += preprocessRuleVar;
750 commands.push_back(cmd);
753 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
754 relativeObjI.c_str(),
755 force_depends, commands, false);
758 if(do_assembly_rules)
760 commands.clear();
761 std::string relativeObjS = relativeObjBase + ".s";
762 std::string objS = objBase + ".s";
764 std::string assemblyEcho = "Compiling ";
765 assemblyEcho += lang;
766 assemblyEcho += " source to assembly ";
767 assemblyEcho += objS;
768 this->LocalGenerator->AppendEcho(
769 commands, assemblyEcho.c_str(),
770 cmLocalUnixMakefileGenerator3::EchoBuild
773 std::string assemblyRuleVar = "CMAKE_";
774 assemblyRuleVar += lang;
775 assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
776 if(const char* assemblyRule =
777 this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
779 std::vector<std::string> assemblyCommands;
780 cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
781 this->LocalGenerator->CreateCDCommand
782 (assemblyCommands,
783 this->Makefile->GetStartOutputDirectory(),
784 cmLocalGenerator::HOME_OUTPUT);
785 commands.insert(commands.end(),
786 assemblyCommands.begin(),
787 assemblyCommands.end());
789 std::string shellObjS =
790 this->Convert(objS.c_str(),
791 cmLocalGenerator::NONE,
792 cmLocalGenerator::SHELL).c_str();
793 vars.AssemblySource = shellObjS.c_str();
795 // Expand placeholders in the commands.
796 for(std::vector<std::string>::iterator i = commands.begin();
797 i != commands.end(); ++i)
799 this->LocalGenerator->ExpandRuleVariables(*i, vars);
802 else
804 std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
805 cmd += assemblyRuleVar;
806 commands.push_back(cmd);
809 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
810 relativeObjS.c_str(),
811 force_depends, commands, false);
815 // If the language needs provides-requires mode, create the
816 // corresponding targets.
817 std::string objectRequires = relativeObj;
818 objectRequires += ".requires";
819 std::vector<std::string> p_depends;
820 // always provide an empty requires target
821 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
822 objectRequires.c_str(), p_depends,
823 no_commands, true);
825 // write a build rule to recursively build what this obj provides
826 std::string objectProvides = relativeObj;
827 objectProvides += ".provides";
828 std::string temp = relativeObj;
829 temp += ".provides.build";
830 std::vector<std::string> r_commands;
831 std::string tgtMakefileName =
832 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
833 tgtMakefileName += "/build.make";
834 r_commands.push_back
835 (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
836 temp.c_str()));
838 p_depends.clear();
839 p_depends.push_back(objectRequires);
840 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
841 objectProvides.c_str(), p_depends,
842 r_commands, true);
844 // write the provides.build rule dependency on the obj file
845 p_depends.clear();
846 p_depends.push_back(relativeObj);
847 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
848 temp.c_str(), p_depends, no_commands,
849 true);
852 //----------------------------------------------------------------------------
853 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
855 std::vector<std::string> depends;
856 std::vector<std::string> no_commands;
858 // Construct the name of the dependency generation target.
859 std::string depTarget =
860 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
861 depTarget += "/requires";
863 // This target drives dependency generation for all object files.
864 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
865 std::string objTarget;
866 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
867 obj != this->Objects.end(); ++obj)
869 objTarget = relPath;
870 objTarget += *obj;
871 objTarget += ".requires";
872 depends.push_back(objTarget);
875 // Write the rule.
876 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
877 depTarget.c_str(),
878 depends, no_commands, true);
881 //----------------------------------------------------------------------------
882 void cmMakefileTargetGenerator::WriteTargetCleanRules()
884 std::vector<std::string> depends;
885 std::vector<std::string> commands;
887 // Construct the clean target name.
888 std::string cleanTarget =
889 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
890 cleanTarget += "/clean";
892 // Construct the clean command.
893 this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
894 *this->Target);
895 this->LocalGenerator->CreateCDCommand
896 (commands,
897 this->Makefile->GetStartOutputDirectory(),
898 cmLocalGenerator::HOME_OUTPUT);
900 // Write the rule.
901 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
902 cleanTarget.c_str(),
903 depends, commands, true);
907 //----------------------------------------------------------------------------
908 void cmMakefileTargetGenerator::WriteTargetDependRules()
910 // must write the targets depend info file
911 std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
912 this->InfoFileNameFull = dir;
913 this->InfoFileNameFull += "/DependInfo.cmake";
914 this->InfoFileNameFull =
915 this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
916 this->InfoFileStream =
917 new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
918 this->InfoFileStream->SetCopyIfDifferent(true);
919 if(!*this->InfoFileStream)
921 return;
923 this->LocalGenerator->
924 WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
926 // Store multiple output pairs in the depend info file.
927 if(!this->MultipleOutputPairs.empty())
929 *this->InfoFileStream
930 << "\n"
931 << "# Pairs of files generated by the same build rule.\n"
932 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
933 for(MultipleOutputPairsType::const_iterator pi =
934 this->MultipleOutputPairs.begin();
935 pi != this->MultipleOutputPairs.end(); ++pi)
937 *this->InfoFileStream
938 << " " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
939 << " " << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
940 << "\n";
942 *this->InfoFileStream << " )\n\n";
945 // Store list of targets linked directly or transitively.
947 *this->InfoFileStream
948 << "\n"
949 << "# Targets to which this target links.\n"
950 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
951 std::set<cmTarget const*> emitted;
952 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
953 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
955 cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
956 for(cmComputeLinkInformation::ItemVector::const_iterator
957 i = items.begin(); i != items.end(); ++i)
959 cmTarget const* linkee = i->Target;
960 if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
962 cmMakefile* mf = linkee->GetMakefile();
963 cmLocalGenerator* lg = mf->GetLocalGenerator();
964 std::string di = mf->GetStartOutputDirectory();
965 di += "/";
966 di += lg->GetTargetDirectory(*linkee);
967 di += "/DependInfo.cmake";
968 *this->InfoFileStream << " \"" << di << "\"\n";
972 *this->InfoFileStream
973 << " )\n";
976 // Check for a target-specific module output directory.
977 if(const char* mdir = this->GetFortranModuleDirectory())
979 *this->InfoFileStream
980 << "\n"
981 << "# Fortran module output directory.\n"
982 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
985 // and now write the rule to use it
986 std::vector<std::string> depends;
987 std::vector<std::string> commands;
989 // Construct the name of the dependency generation target.
990 std::string depTarget =
991 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
992 depTarget += "/depend";
994 // Add a command to call CMake to scan dependencies. CMake will
995 // touch the corresponding depends file after scanning dependencies.
996 cmOStringStream depCmd;
997 // TODO: Account for source file properties and directory-level
998 // definitions when scanning for dependencies.
999 #if !defined(_WIN32) || defined(__CYGWIN__)
1000 // This platform supports symlinks, so cmSystemTools will translate
1001 // paths. Make sure PWD is set to the original name of the home
1002 // output directory to help cmSystemTools to create the same
1003 // translation table for the dependency scanning process.
1004 depCmd << "cd "
1005 << (this->LocalGenerator->Convert(
1006 this->Makefile->GetHomeOutputDirectory(),
1007 cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1008 << " && ";
1009 #endif
1010 // Generate a call this signature:
1012 // cmake -E cmake_depends <generator>
1013 // <home-src-dir> <start-src-dir>
1014 // <home-out-dir> <start-out-dir>
1015 // <dep-info> --color=$(COLOR)
1017 // This gives the dependency scanner enough information to recreate
1018 // the state of our local generator sufficiently for its needs.
1019 depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1020 << this->GlobalGenerator->GetName() << "\" "
1021 << this->Convert(this->Makefile->GetHomeDirectory(),
1022 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1023 << " "
1024 << this->Convert(this->Makefile->GetStartDirectory(),
1025 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1026 << " "
1027 << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1028 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1029 << " "
1030 << this->Convert(this->Makefile->GetStartOutputDirectory(),
1031 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1032 << " "
1033 << this->Convert(this->InfoFileNameFull.c_str(),
1034 cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1035 << " --color=$(COLOR)";
1036 commands.push_back(depCmd.str());
1038 // Make sure all custom command outputs in this target are built.
1039 if(this->CustomCommandDriver == OnDepends)
1041 this->DriveCustomCommands(depends);
1044 // Write the rule.
1045 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1046 depTarget.c_str(),
1047 depends, commands, true);
1050 //----------------------------------------------------------------------------
1051 void
1052 cmMakefileTargetGenerator
1053 ::DriveCustomCommands(std::vector<std::string>& depends)
1055 // Depend on all custom command outputs.
1056 const std::vector<cmSourceFile*>& sources =
1057 this->Target->GetSourceFiles();
1058 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1059 source != sources.end(); ++source)
1061 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1063 const std::vector<std::string>& outputs = cc->GetOutputs();
1064 for(std::vector<std::string>::const_iterator o = outputs.begin();
1065 o != outputs.end(); ++o)
1067 depends.push_back(*o);
1073 //----------------------------------------------------------------------------
1074 void cmMakefileTargetGenerator
1075 ::WriteObjectDependRules(cmSourceFile& source,
1076 std::vector<std::string>& depends)
1078 // Create the list of dependencies known at cmake time. These are
1079 // shared between the object file and dependency scanning rule.
1080 depends.push_back(source.GetFullPath());
1081 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1083 std::vector<std::string> deps;
1084 cmSystemTools::ExpandListArgument(objectDeps, deps);
1085 for(std::vector<std::string>::iterator i = deps.begin();
1086 i != deps.end(); ++i)
1088 depends.push_back(i->c_str());
1093 //----------------------------------------------------------------------------
1094 void cmMakefileTargetGenerator
1095 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1097 // Collect the commands.
1098 std::vector<std::string> commands;
1099 std::string comment = this->LocalGenerator->ConstructComment(cc);
1100 if(!comment.empty())
1102 // add in a progress call if needed
1103 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1104 progressDir += cmake::GetCMakeFilesDirectory();
1105 cmOStringStream progCmd;
1106 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1107 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1108 cmLocalGenerator::FULL,
1109 cmLocalGenerator::SHELL);
1110 this->NumberOfProgressActions++;
1111 progCmd << " $(CMAKE_PROGRESS_"
1112 << this->NumberOfProgressActions
1113 << ")";
1114 commands.push_back(progCmd.str());
1115 this->LocalGenerator
1116 ->AppendEcho(commands, comment.c_str(),
1117 cmLocalUnixMakefileGenerator3::EchoGenerate);
1119 // Below we need to skip over the echo and progress commands.
1120 unsigned int skip = static_cast<unsigned int>(commands.size());
1122 // Now append the actual user-specified commands.
1123 this->LocalGenerator->AppendCustomCommand(commands, cc);
1125 // Collect the dependencies.
1126 std::vector<std::string> depends;
1127 this->LocalGenerator->AppendCustomDepend(depends, cc);
1129 // Check whether we need to bother checking for a symbolic output.
1130 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1132 // Write the rule.
1133 const std::vector<std::string>& outputs = cc.GetOutputs();
1134 std::vector<std::string>::const_iterator o = outputs.begin();
1136 bool symbolic = false;
1137 if(need_symbolic)
1139 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1141 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1144 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1145 o->c_str(), depends, commands,
1146 symbolic);
1148 // If the rule has changed make sure the output is rebuilt.
1149 if(!symbolic)
1151 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(),
1152 commands.begin()+skip,
1153 commands.end());
1157 // Write rules to drive building any outputs beyond the first.
1158 const char* in = o->c_str();
1159 for(++o; o != outputs.end(); ++o)
1161 bool symbolic = false;
1162 if(need_symbolic)
1164 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1166 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1169 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1172 // Setup implicit dependency scanning.
1173 for(cmCustomCommand::ImplicitDependsList::const_iterator
1174 idi = cc.GetImplicitDepends().begin();
1175 idi != cc.GetImplicitDepends().end(); ++idi)
1177 std::string objFullPath =
1178 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1179 std::string srcFullPath =
1180 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1181 this->LocalGenerator->
1182 AddImplicitDepends(*this->Target, idi->first.c_str(),
1183 objFullPath.c_str(),
1184 srcFullPath.c_str());
1188 //----------------------------------------------------------------------------
1189 void
1190 cmMakefileTargetGenerator
1191 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1193 // Add a rule to build the primary output if the extra output needs
1194 // to be created.
1195 std::vector<std::string> commands;
1196 std::vector<std::string> depends;
1197 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1198 if(!emptyCommand.empty())
1200 commands.push_back(emptyCommand);
1202 depends.push_back(in);
1203 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1204 out, depends, commands,
1205 symbolic);
1207 // Register the extra output as paired with the first output so that
1208 // the check-build-system step will remove the primary output if any
1209 // extra outputs are missing. This forces the rule to regenerate
1210 // all outputs.
1211 this->AddMultipleOutputPair(out, in);
1214 //----------------------------------------------------------------------------
1215 void
1216 cmMakefileTargetGenerator
1217 ::WriteObjectsVariable(std::string& variableName,
1218 std::string& variableNameExternal)
1220 // Write a make variable assignment that lists all objects for the
1221 // target.
1222 variableName =
1223 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1224 "_OBJECTS");
1225 *this->BuildFileStream
1226 << "# Object files for target " << this->Target->GetName() << "\n"
1227 << variableName.c_str() << " =";
1228 std::string object;
1229 const char* objName =
1230 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1231 const char* lineContinue =
1232 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1233 if(!lineContinue)
1235 lineContinue = "\\";
1237 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1238 i != this->Objects.end(); ++i)
1240 *this->BuildFileStream << " " << lineContinue << "\n";
1241 if(objName)
1243 *this->BuildFileStream <<
1244 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1245 cmLocalGenerator::MAKEFILE);
1247 else
1249 *this->BuildFileStream <<
1250 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1253 *this->BuildFileStream << "\n";
1255 // Write a make variable assignment that lists all external objects
1256 // for the target.
1257 variableNameExternal =
1258 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1259 "_EXTERNAL_OBJECTS");
1260 *this->BuildFileStream
1261 << "\n"
1262 << "# External object files for target "
1263 << this->Target->GetName() << "\n"
1264 << variableNameExternal.c_str() << " =";
1265 for(std::vector<std::string>::const_iterator i =
1266 this->ExternalObjects.begin();
1267 i != this->ExternalObjects.end(); ++i)
1269 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1270 *this->BuildFileStream
1271 << " " << lineContinue << "\n"
1272 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1273 if(objName)
1275 *this->BuildFileStream <<
1276 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1277 cmLocalGenerator::MAKEFILE);
1279 else
1281 *this->BuildFileStream <<
1282 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1285 *this->BuildFileStream << "\n" << "\n";
1288 //----------------------------------------------------------------------------
1289 void
1290 cmMakefileTargetGenerator
1291 ::WriteObjectsString(std::string& buildObjs)
1293 std::vector<std::string> objStrings;
1294 this->WriteObjectsStrings(objStrings);
1295 buildObjs = objStrings[0];
1298 //----------------------------------------------------------------------------
1299 class cmMakefileTargetGeneratorObjectStrings
1301 public:
1302 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1303 cmMakefile* mf,
1304 cmLocalUnixMakefileGenerator3* lg,
1305 std::string::size_type limit):
1306 Strings(strings), Makefile(mf), LocalGenerator(lg), LengthLimit(limit)
1308 this->Space = "";
1310 void Feed(std::string const& obj)
1312 // Construct the name of the next object.
1313 this->NextObject =
1314 this->LocalGenerator->Convert(obj.c_str(),
1315 cmLocalGenerator::START_OUTPUT,
1316 cmLocalGenerator::SHELL);
1318 // Roll over to next string if the limit will be exceeded.
1319 if(this->LengthLimit != std::string::npos &&
1320 (this->CurrentString.length() + 1 + this->NextObject.length()
1321 > this->LengthLimit))
1323 this->Strings.push_back(this->CurrentString);
1324 this->CurrentString = "";
1325 this->Space = "";
1328 // Separate from previous object.
1329 this->CurrentString += this->Space;
1330 this->Space = " ";
1332 // Append this object.
1333 this->CurrentString += this->NextObject;
1335 void Done()
1337 this->Strings.push_back(this->CurrentString);
1339 private:
1340 std::vector<std::string>& Strings;
1341 cmMakefile* Makefile;
1342 cmLocalUnixMakefileGenerator3* LocalGenerator;
1343 std::string::size_type LengthLimit;
1344 std::string CurrentString;
1345 std::string NextObject;
1346 const char* Space;
1349 //----------------------------------------------------------------------------
1350 void
1351 cmMakefileTargetGenerator
1352 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1353 std::string::size_type limit)
1355 cmMakefileTargetGeneratorObjectStrings
1356 helper(objStrings, this->Makefile, this->LocalGenerator, limit);
1357 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1358 i != this->Objects.end(); ++i)
1360 helper.Feed(*i);
1362 for(std::vector<std::string>::const_iterator i =
1363 this->ExternalObjects.begin();
1364 i != this->ExternalObjects.end(); ++i)
1366 helper.Feed(*i);
1368 helper.Done();
1371 //----------------------------------------------------------------------------
1372 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1373 bool relink)
1375 // Compute the name of the driver target.
1376 std::string dir =
1377 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1378 std::string buildTargetRuleName = dir;
1379 buildTargetRuleName += relink?"/preinstall":"/build";
1380 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1381 cmLocalGenerator::HOME_OUTPUT,
1382 cmLocalGenerator::UNCHANGED);
1384 // Build the list of target outputs to drive.
1385 std::vector<std::string> depends;
1386 if(main_output)
1388 depends.push_back(main_output);
1391 const char* comment = 0;
1392 if(relink)
1394 // Setup the comment for the preinstall driver.
1395 comment = "Rule to relink during preinstall.";
1397 else
1399 // Setup the comment for the main build driver.
1400 comment = "Rule to build all files generated by this target.";
1402 // Make sure all custom command outputs in this target are built.
1403 if(this->CustomCommandDriver == OnBuild)
1405 this->DriveCustomCommands(depends);
1408 // Make sure the extra files are built.
1409 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1410 i != this->ExtraFiles.end(); ++i)
1412 depends.push_back(*i);
1416 // Write the driver rule.
1417 std::vector<std::string> no_commands;
1418 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1419 buildTargetRuleName.c_str(),
1420 depends, no_commands, true);
1423 //----------------------------------------------------------------------------
1424 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1426 #ifndef __APPLE__
1427 return std::string();
1428 #else
1429 std::set<cmStdString> emitted;
1430 emitted.insert("/System/Library/Frameworks");
1431 std::vector<std::string> includes;
1432 this->LocalGenerator->GetIncludeDirectories(includes);
1433 std::vector<std::string>::iterator i;
1434 // check all include directories for frameworks as this
1435 // will already have added a -F for the framework
1436 for(i = includes.begin(); i != includes.end(); ++i)
1438 if(this->Target->NameResolvesToFramework(i->c_str()))
1440 std::string frameworkDir = *i;
1441 frameworkDir += "/../";
1442 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1443 emitted.insert(frameworkDir);
1447 std::string flags;
1448 std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1449 for(i = frameworks.begin();
1450 i != frameworks.end(); ++i)
1452 if(emitted.insert(*i).second)
1454 flags += "-F";
1455 flags += this->Convert(i->c_str(),
1456 cmLocalGenerator::START_OUTPUT,
1457 cmLocalGenerator::SHELL, true);
1458 flags += " ";
1461 return flags;
1462 #endif
1465 //----------------------------------------------------------------------------
1466 void cmMakefileTargetGenerator
1467 ::AppendTargetDepends(std::vector<std::string>& depends)
1469 // Static libraries never depend on anything for linking.
1470 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1472 return;
1475 // Loop over all library dependencies.
1476 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1477 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1479 std::vector<std::string> const& libDeps = cli->GetDepends();
1480 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1481 j != libDeps.end(); ++j)
1483 depends.push_back(*j);
1488 //----------------------------------------------------------------------------
1489 void cmMakefileTargetGenerator
1490 ::CloseFileStreams()
1492 delete this->BuildFileStream;
1493 delete this->InfoFileStream;
1494 delete this->FlagFileStream;
1497 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1498 const char* linkLang,
1499 std::string& linkFlags)
1501 // check for language flags that are not allowed at link time, and
1502 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1503 // which fails, there may be more]
1505 std::string removeFlags = "CMAKE_";
1506 removeFlags += linkLang;
1507 removeFlags += flagVar;
1508 std::string removeflags =
1509 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1510 std::vector<std::string> removeList;
1511 cmSystemTools::ExpandListArgument(removeflags, removeList);
1512 for(std::vector<std::string>::iterator i = removeList.begin();
1513 i != removeList.end(); ++i)
1515 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1519 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total,
1520 unsigned long &current)
1522 cmGeneratedFileStream *progressFileStream =
1523 new cmGeneratedFileStream(this->ProgressFileNameFull.c_str());
1524 if(!progressFileStream)
1526 return;
1529 unsigned long num;
1530 unsigned long i;
1531 for (i = 1; i <= this->NumberOfProgressActions; ++i)
1533 *progressFileStream
1534 << "CMAKE_PROGRESS_" << i << " = ";
1535 if (total <= 100)
1537 num = i + current;
1538 *progressFileStream << num;
1539 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1540 .push_back(num);
1542 else if (((i+current)*100)/total > ((i-1+current)*100)/total)
1544 num = ((i+current)*100)/total;
1545 *progressFileStream << num;
1546 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1547 .push_back(num);
1549 *progressFileStream << "\n";
1551 *progressFileStream << "\n";
1552 current += this->NumberOfProgressActions;
1553 delete progressFileStream;
1556 //----------------------------------------------------------------------------
1557 void
1558 cmMakefileTargetGenerator
1559 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1561 MultipleOutputPairsType::value_type p(depender, dependee);
1562 this->MultipleOutputPairs.insert(p);
1565 //----------------------------------------------------------------------------
1566 void
1567 cmMakefileTargetGenerator
1568 ::CreateLinkScript(const char* name,
1569 std::vector<std::string> const& link_commands,
1570 std::vector<std::string>& makefile_commands,
1571 std::vector<std::string>& makefile_depends)
1573 // Create the link script file.
1574 std::string linkScriptName = this->TargetBuildDirectoryFull;
1575 linkScriptName += "/";
1576 linkScriptName += name;
1577 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1578 linkScriptStream.SetCopyIfDifferent(true);
1579 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1580 cmd != link_commands.end(); ++cmd)
1582 // Do not write out empty commands or commands beginning in the
1583 // shell no-op ":".
1584 if(!cmd->empty() && (*cmd)[0] != ':')
1586 linkScriptStream << *cmd << "\n";
1590 // Create the makefile command to invoke the link script.
1591 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1592 link_command += this->Convert(linkScriptName.c_str(),
1593 cmLocalGenerator::START_OUTPUT,
1594 cmLocalGenerator::SHELL);
1595 link_command += " --verbose=$(VERBOSE)";
1596 makefile_commands.push_back(link_command);
1597 makefile_depends.push_back(linkScriptName);
1600 //----------------------------------------------------------------------------
1601 std::string
1602 cmMakefileTargetGenerator
1603 ::CreateResponseFile(const char* name, std::string const& options,
1604 std::vector<std::string>& makefile_depends)
1606 // Create the response file.
1607 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1608 responseFileNameFull += "/";
1609 responseFileNameFull += name;
1610 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1611 responseStream.SetCopyIfDifferent(true);
1612 responseStream << options << "\n";
1614 // Add a dependency so the target will rebuild when the set of
1615 // objects changes.
1616 makefile_depends.push_back(responseFileNameFull);
1618 // Construct the name to be used on the command line.
1619 std::string responseFileName = this->TargetBuildDirectory;
1620 responseFileName += "/";
1621 responseFileName += name;
1622 return responseFileName;
1625 //----------------------------------------------------------------------------
1626 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1628 // Compute the module directory.
1629 if(!this->FortranModuleDirectoryComputed)
1631 const char* target_mod_dir =
1632 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1633 const char* moddir_flag =
1634 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1635 if(target_mod_dir && moddir_flag)
1637 // Compute the full path to the module directory.
1638 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1640 // Already a full path.
1641 this->FortranModuleDirectory = target_mod_dir;
1643 else
1645 // Interpret relative to the current output directory.
1646 this->FortranModuleDirectory =
1647 this->Makefile->GetCurrentOutputDirectory();
1648 this->FortranModuleDirectory += "/";
1649 this->FortranModuleDirectory += target_mod_dir;
1652 // Make sure the module output directory exists.
1653 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1655 this->FortranModuleDirectoryComputed = true;
1658 // Return the computed directory.
1659 if(this->FortranModuleDirectory.empty())
1661 return 0;
1663 else
1665 return this->FortranModuleDirectory.c_str();
1669 //----------------------------------------------------------------------------
1670 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1672 // Add a module output directory flag if necessary.
1673 if(const char* mod_dir = this->GetFortranModuleDirectory())
1675 const char* moddir_flag =
1676 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1677 std::string modflag = moddir_flag;
1678 modflag += this->Convert(mod_dir,
1679 cmLocalGenerator::START_OUTPUT,
1680 cmLocalGenerator::SHELL);
1681 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1684 // If there is a separate module path flag then duplicate the
1685 // include path with it. This compiler does not search the include
1686 // path for modules.
1687 if(const char* modpath_flag =
1688 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1690 std::vector<std::string> includes;
1691 this->LocalGenerator->GetIncludeDirectories(includes);
1692 for(std::vector<std::string>::const_iterator idi = includes.begin();
1693 idi != includes.end(); ++idi)
1695 std::string flg = modpath_flag;
1696 flg += this->Convert(idi->c_str(),
1697 cmLocalGenerator::NONE,
1698 cmLocalGenerator::SHELL);
1699 this->LocalGenerator->AppendFlags(flags, flg.c_str());