ENH: fix uppercase version so defines are not upper as well
[cmake.git] / Source / cmMakefileTargetGenerator.cxx
blob95219fb59d409def51392f038d582912554225af
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-10-15 14:40:57 $
7 Version: $Revision: 1.109 $
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 if(this->LocalGenerator->GetColorMakefile())
1037 depCmd << " --color=$(COLOR)";
1039 commands.push_back(depCmd.str());
1041 // Make sure all custom command outputs in this target are built.
1042 if(this->CustomCommandDriver == OnDepends)
1044 this->DriveCustomCommands(depends);
1047 // Write the rule.
1048 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1049 depTarget.c_str(),
1050 depends, commands, true);
1053 //----------------------------------------------------------------------------
1054 void
1055 cmMakefileTargetGenerator
1056 ::DriveCustomCommands(std::vector<std::string>& depends)
1058 // Depend on all custom command outputs.
1059 const std::vector<cmSourceFile*>& sources =
1060 this->Target->GetSourceFiles();
1061 for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1062 source != sources.end(); ++source)
1064 if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1066 const std::vector<std::string>& outputs = cc->GetOutputs();
1067 for(std::vector<std::string>::const_iterator o = outputs.begin();
1068 o != outputs.end(); ++o)
1070 depends.push_back(*o);
1076 //----------------------------------------------------------------------------
1077 void cmMakefileTargetGenerator
1078 ::WriteObjectDependRules(cmSourceFile& source,
1079 std::vector<std::string>& depends)
1081 // Create the list of dependencies known at cmake time. These are
1082 // shared between the object file and dependency scanning rule.
1083 depends.push_back(source.GetFullPath());
1084 if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1086 std::vector<std::string> deps;
1087 cmSystemTools::ExpandListArgument(objectDeps, deps);
1088 for(std::vector<std::string>::iterator i = deps.begin();
1089 i != deps.end(); ++i)
1091 depends.push_back(i->c_str());
1096 //----------------------------------------------------------------------------
1097 void cmMakefileTargetGenerator
1098 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1100 // Collect the commands.
1101 std::vector<std::string> commands;
1102 std::string comment = this->LocalGenerator->ConstructComment(cc);
1103 if(!comment.empty())
1105 // add in a progress call if needed
1106 std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1107 progressDir += cmake::GetCMakeFilesDirectory();
1108 cmOStringStream progCmd;
1109 progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1110 progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1111 cmLocalGenerator::FULL,
1112 cmLocalGenerator::SHELL);
1113 this->NumberOfProgressActions++;
1114 progCmd << " $(CMAKE_PROGRESS_"
1115 << this->NumberOfProgressActions
1116 << ")";
1117 commands.push_back(progCmd.str());
1118 this->LocalGenerator
1119 ->AppendEcho(commands, comment.c_str(),
1120 cmLocalUnixMakefileGenerator3::EchoGenerate);
1122 // Below we need to skip over the echo and progress commands.
1123 unsigned int skip = static_cast<unsigned int>(commands.size());
1125 // Now append the actual user-specified commands.
1126 this->LocalGenerator->AppendCustomCommand(commands, cc);
1128 // Collect the dependencies.
1129 std::vector<std::string> depends;
1130 this->LocalGenerator->AppendCustomDepend(depends, cc);
1132 // Check whether we need to bother checking for a symbolic output.
1133 bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1135 // Write the rule.
1136 const std::vector<std::string>& outputs = cc.GetOutputs();
1137 std::vector<std::string>::const_iterator o = outputs.begin();
1139 bool symbolic = false;
1140 if(need_symbolic)
1142 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1144 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1147 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1148 o->c_str(), depends, commands,
1149 symbolic);
1151 // If the rule has changed make sure the output is rebuilt.
1152 if(!symbolic)
1154 this->GlobalGenerator->AddRuleHash(cc.GetOutputs(),
1155 commands.begin()+skip,
1156 commands.end());
1160 // Write rules to drive building any outputs beyond the first.
1161 const char* in = o->c_str();
1162 for(++o; o != outputs.end(); ++o)
1164 bool symbolic = false;
1165 if(need_symbolic)
1167 if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1169 symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1172 this->GenerateExtraOutput(o->c_str(), in, symbolic);
1175 // Setup implicit dependency scanning.
1176 for(cmCustomCommand::ImplicitDependsList::const_iterator
1177 idi = cc.GetImplicitDepends().begin();
1178 idi != cc.GetImplicitDepends().end(); ++idi)
1180 std::string objFullPath =
1181 this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1182 std::string srcFullPath =
1183 this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1184 this->LocalGenerator->
1185 AddImplicitDepends(*this->Target, idi->first.c_str(),
1186 objFullPath.c_str(),
1187 srcFullPath.c_str());
1191 //----------------------------------------------------------------------------
1192 void
1193 cmMakefileTargetGenerator
1194 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1196 // Add a rule to build the primary output if the extra output needs
1197 // to be created.
1198 std::vector<std::string> commands;
1199 std::vector<std::string> depends;
1200 std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1201 if(!emptyCommand.empty())
1203 commands.push_back(emptyCommand);
1205 depends.push_back(in);
1206 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1207 out, depends, commands,
1208 symbolic);
1210 // Register the extra output as paired with the first output so that
1211 // the check-build-system step will remove the primary output if any
1212 // extra outputs are missing. This forces the rule to regenerate
1213 // all outputs.
1214 this->AddMultipleOutputPair(out, in);
1217 //----------------------------------------------------------------------------
1218 void
1219 cmMakefileTargetGenerator
1220 ::WriteObjectsVariable(std::string& variableName,
1221 std::string& variableNameExternal)
1223 // Write a make variable assignment that lists all objects for the
1224 // target.
1225 variableName =
1226 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1227 "_OBJECTS");
1228 *this->BuildFileStream
1229 << "# Object files for target " << this->Target->GetName() << "\n"
1230 << variableName.c_str() << " =";
1231 std::string object;
1232 const char* objName =
1233 this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1234 const char* lineContinue =
1235 this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1236 if(!lineContinue)
1238 lineContinue = "\\";
1240 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1241 i != this->Objects.end(); ++i)
1243 *this->BuildFileStream << " " << lineContinue << "\n";
1244 if(objName)
1246 *this->BuildFileStream <<
1247 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1248 cmLocalGenerator::MAKEFILE);
1250 else
1252 *this->BuildFileStream <<
1253 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1256 *this->BuildFileStream << "\n";
1258 // Write a make variable assignment that lists all external objects
1259 // for the target.
1260 variableNameExternal =
1261 this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1262 "_EXTERNAL_OBJECTS");
1263 *this->BuildFileStream
1264 << "\n"
1265 << "# External object files for target "
1266 << this->Target->GetName() << "\n"
1267 << variableNameExternal.c_str() << " =";
1268 for(std::vector<std::string>::const_iterator i =
1269 this->ExternalObjects.begin();
1270 i != this->ExternalObjects.end(); ++i)
1272 object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1273 *this->BuildFileStream
1274 << " " << lineContinue << "\n"
1275 << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1276 if(objName)
1278 *this->BuildFileStream <<
1279 this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1280 cmLocalGenerator::MAKEFILE);
1282 else
1284 *this->BuildFileStream <<
1285 this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1288 *this->BuildFileStream << "\n" << "\n";
1291 //----------------------------------------------------------------------------
1292 void
1293 cmMakefileTargetGenerator
1294 ::WriteObjectsString(std::string& buildObjs)
1296 std::vector<std::string> objStrings;
1297 this->WriteObjectsStrings(objStrings);
1298 buildObjs = objStrings[0];
1301 //----------------------------------------------------------------------------
1302 class cmMakefileTargetGeneratorObjectStrings
1304 public:
1305 cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1306 cmMakefile* mf,
1307 cmLocalUnixMakefileGenerator3* lg,
1308 std::string::size_type limit):
1309 Strings(strings), Makefile(mf), LocalGenerator(lg), LengthLimit(limit)
1311 this->Space = "";
1313 void Feed(std::string const& obj)
1315 // Construct the name of the next object.
1316 this->NextObject =
1317 this->LocalGenerator->Convert(obj.c_str(),
1318 cmLocalGenerator::START_OUTPUT,
1319 cmLocalGenerator::SHELL);
1321 // Roll over to next string if the limit will be exceeded.
1322 if(this->LengthLimit != std::string::npos &&
1323 (this->CurrentString.length() + 1 + this->NextObject.length()
1324 > this->LengthLimit))
1326 this->Strings.push_back(this->CurrentString);
1327 this->CurrentString = "";
1328 this->Space = "";
1331 // Separate from previous object.
1332 this->CurrentString += this->Space;
1333 this->Space = " ";
1335 // Append this object.
1336 this->CurrentString += this->NextObject;
1338 void Done()
1340 this->Strings.push_back(this->CurrentString);
1342 private:
1343 std::vector<std::string>& Strings;
1344 cmMakefile* Makefile;
1345 cmLocalUnixMakefileGenerator3* LocalGenerator;
1346 std::string::size_type LengthLimit;
1347 std::string CurrentString;
1348 std::string NextObject;
1349 const char* Space;
1352 //----------------------------------------------------------------------------
1353 void
1354 cmMakefileTargetGenerator
1355 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1356 std::string::size_type limit)
1358 cmMakefileTargetGeneratorObjectStrings
1359 helper(objStrings, this->Makefile, this->LocalGenerator, limit);
1360 for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1361 i != this->Objects.end(); ++i)
1363 helper.Feed(*i);
1365 for(std::vector<std::string>::const_iterator i =
1366 this->ExternalObjects.begin();
1367 i != this->ExternalObjects.end(); ++i)
1369 helper.Feed(*i);
1371 helper.Done();
1374 //----------------------------------------------------------------------------
1375 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1376 bool relink)
1378 // Compute the name of the driver target.
1379 std::string dir =
1380 this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1381 std::string buildTargetRuleName = dir;
1382 buildTargetRuleName += relink?"/preinstall":"/build";
1383 buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1384 cmLocalGenerator::HOME_OUTPUT,
1385 cmLocalGenerator::UNCHANGED);
1387 // Build the list of target outputs to drive.
1388 std::vector<std::string> depends;
1389 if(main_output)
1391 depends.push_back(main_output);
1394 const char* comment = 0;
1395 if(relink)
1397 // Setup the comment for the preinstall driver.
1398 comment = "Rule to relink during preinstall.";
1400 else
1402 // Setup the comment for the main build driver.
1403 comment = "Rule to build all files generated by this target.";
1405 // Make sure all custom command outputs in this target are built.
1406 if(this->CustomCommandDriver == OnBuild)
1408 this->DriveCustomCommands(depends);
1411 // Make sure the extra files are built.
1412 for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1413 i != this->ExtraFiles.end(); ++i)
1415 depends.push_back(*i);
1419 // Write the driver rule.
1420 std::vector<std::string> no_commands;
1421 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1422 buildTargetRuleName.c_str(),
1423 depends, no_commands, true);
1426 //----------------------------------------------------------------------------
1427 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1429 #ifndef __APPLE__
1430 return std::string();
1431 #else
1432 std::set<cmStdString> emitted;
1433 emitted.insert("/System/Library/Frameworks");
1434 std::vector<std::string> includes;
1435 this->LocalGenerator->GetIncludeDirectories(includes);
1436 std::vector<std::string>::iterator i;
1437 // check all include directories for frameworks as this
1438 // will already have added a -F for the framework
1439 for(i = includes.begin(); i != includes.end(); ++i)
1441 if(this->Target->NameResolvesToFramework(i->c_str()))
1443 std::string frameworkDir = *i;
1444 frameworkDir += "/../";
1445 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1446 emitted.insert(frameworkDir);
1450 std::string flags;
1451 std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1452 for(i = frameworks.begin();
1453 i != frameworks.end(); ++i)
1455 if(emitted.insert(*i).second)
1457 flags += "-F";
1458 flags += this->Convert(i->c_str(),
1459 cmLocalGenerator::START_OUTPUT,
1460 cmLocalGenerator::SHELL, true);
1461 flags += " ";
1464 return flags;
1465 #endif
1468 //----------------------------------------------------------------------------
1469 void cmMakefileTargetGenerator
1470 ::AppendTargetDepends(std::vector<std::string>& depends)
1472 // Static libraries never depend on anything for linking.
1473 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1475 return;
1478 // Loop over all library dependencies.
1479 const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1480 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1482 std::vector<std::string> const& libDeps = cli->GetDepends();
1483 for(std::vector<std::string>::const_iterator j = libDeps.begin();
1484 j != libDeps.end(); ++j)
1486 depends.push_back(*j);
1491 //----------------------------------------------------------------------------
1492 void cmMakefileTargetGenerator
1493 ::CloseFileStreams()
1495 delete this->BuildFileStream;
1496 delete this->InfoFileStream;
1497 delete this->FlagFileStream;
1500 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1501 const char* linkLang,
1502 std::string& linkFlags)
1504 // check for language flags that are not allowed at link time, and
1505 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1506 // which fails, there may be more]
1508 std::string removeFlags = "CMAKE_";
1509 removeFlags += linkLang;
1510 removeFlags += flagVar;
1511 std::string removeflags =
1512 this->Makefile->GetSafeDefinition(removeFlags.c_str());
1513 std::vector<std::string> removeList;
1514 cmSystemTools::ExpandListArgument(removeflags, removeList);
1515 for(std::vector<std::string>::iterator i = removeList.begin();
1516 i != removeList.end(); ++i)
1518 cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1522 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total,
1523 unsigned long &current)
1525 cmGeneratedFileStream *progressFileStream =
1526 new cmGeneratedFileStream(this->ProgressFileNameFull.c_str());
1527 if(!progressFileStream)
1529 return;
1532 unsigned long num;
1533 unsigned long i;
1534 for (i = 1; i <= this->NumberOfProgressActions; ++i)
1536 *progressFileStream
1537 << "CMAKE_PROGRESS_" << i << " = ";
1538 if (total <= 100)
1540 num = i + current;
1541 *progressFileStream << num;
1542 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1543 .push_back(num);
1545 else if (((i+current)*100)/total > ((i-1+current)*100)/total)
1547 num = ((i+current)*100)/total;
1548 *progressFileStream << num;
1549 this->LocalGenerator->ProgressFiles[this->Target->GetName()]
1550 .push_back(num);
1552 *progressFileStream << "\n";
1554 *progressFileStream << "\n";
1555 current += this->NumberOfProgressActions;
1556 delete progressFileStream;
1559 //----------------------------------------------------------------------------
1560 void
1561 cmMakefileTargetGenerator
1562 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1564 MultipleOutputPairsType::value_type p(depender, dependee);
1565 this->MultipleOutputPairs.insert(p);
1568 //----------------------------------------------------------------------------
1569 void
1570 cmMakefileTargetGenerator
1571 ::CreateLinkScript(const char* name,
1572 std::vector<std::string> const& link_commands,
1573 std::vector<std::string>& makefile_commands,
1574 std::vector<std::string>& makefile_depends)
1576 // Create the link script file.
1577 std::string linkScriptName = this->TargetBuildDirectoryFull;
1578 linkScriptName += "/";
1579 linkScriptName += name;
1580 cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1581 linkScriptStream.SetCopyIfDifferent(true);
1582 for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1583 cmd != link_commands.end(); ++cmd)
1585 // Do not write out empty commands or commands beginning in the
1586 // shell no-op ":".
1587 if(!cmd->empty() && (*cmd)[0] != ':')
1589 linkScriptStream << *cmd << "\n";
1593 // Create the makefile command to invoke the link script.
1594 std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1595 link_command += this->Convert(linkScriptName.c_str(),
1596 cmLocalGenerator::START_OUTPUT,
1597 cmLocalGenerator::SHELL);
1598 link_command += " --verbose=$(VERBOSE)";
1599 makefile_commands.push_back(link_command);
1600 makefile_depends.push_back(linkScriptName);
1603 //----------------------------------------------------------------------------
1604 std::string
1605 cmMakefileTargetGenerator
1606 ::CreateResponseFile(const char* name, std::string const& options,
1607 std::vector<std::string>& makefile_depends)
1609 // Create the response file.
1610 std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1611 responseFileNameFull += "/";
1612 responseFileNameFull += name;
1613 cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1614 responseStream.SetCopyIfDifferent(true);
1615 responseStream << options << "\n";
1617 // Add a dependency so the target will rebuild when the set of
1618 // objects changes.
1619 makefile_depends.push_back(responseFileNameFull);
1621 // Construct the name to be used on the command line.
1622 std::string responseFileName = this->TargetBuildDirectory;
1623 responseFileName += "/";
1624 responseFileName += name;
1625 return responseFileName;
1628 //----------------------------------------------------------------------------
1629 void
1630 cmMakefileTargetGenerator
1631 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1632 bool useResponseFile, std::string& buildObjs,
1633 std::vector<std::string>& makefile_depends)
1635 std::string variableName;
1636 std::string variableNameExternal;
1637 this->WriteObjectsVariable(variableName, variableNameExternal);
1638 if(useResponseFile)
1640 // MSVC response files cannot exceed 128K.
1641 std::string::size_type const responseFileLimit = 131000;
1643 // Construct the individual object list strings.
1644 std::vector<std::string> object_strings;
1645 this->WriteObjectsStrings(object_strings, responseFileLimit);
1647 // Write a response file for each string.
1648 const char* sep = "";
1649 for(unsigned int i = 0; i < object_strings.size(); ++i)
1651 // Number the response files.
1652 char rsp[32];
1653 sprintf(rsp, "objects%u.rsp", i+1);
1655 // Create this response file.
1656 std::string objects_rsp =
1657 this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1659 // Separate from previous response file references.
1660 buildObjs += sep;
1661 sep = " ";
1663 // Reference the response file.
1664 buildObjs += "@";
1665 buildObjs += this->Convert(objects_rsp.c_str(),
1666 cmLocalGenerator::NONE,
1667 cmLocalGenerator::SHELL);
1670 else if(useLinkScript)
1672 if(!useArchiveRules)
1674 this->WriteObjectsString(buildObjs);
1677 else
1679 buildObjs = "$(";
1680 buildObjs += variableName;
1681 buildObjs += ") $(";
1682 buildObjs += variableNameExternal;
1683 buildObjs += ")";
1687 //----------------------------------------------------------------------------
1688 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1690 // Compute the module directory.
1691 if(!this->FortranModuleDirectoryComputed)
1693 const char* target_mod_dir =
1694 this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1695 const char* moddir_flag =
1696 this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1697 if(target_mod_dir && moddir_flag)
1699 // Compute the full path to the module directory.
1700 if(cmSystemTools::FileIsFullPath(target_mod_dir))
1702 // Already a full path.
1703 this->FortranModuleDirectory = target_mod_dir;
1705 else
1707 // Interpret relative to the current output directory.
1708 this->FortranModuleDirectory =
1709 this->Makefile->GetCurrentOutputDirectory();
1710 this->FortranModuleDirectory += "/";
1711 this->FortranModuleDirectory += target_mod_dir;
1714 // Make sure the module output directory exists.
1715 cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1717 this->FortranModuleDirectoryComputed = true;
1720 // Return the computed directory.
1721 if(this->FortranModuleDirectory.empty())
1723 return 0;
1725 else
1727 return this->FortranModuleDirectory.c_str();
1731 //----------------------------------------------------------------------------
1732 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1734 // Add a module output directory flag if necessary.
1735 if(const char* mod_dir = this->GetFortranModuleDirectory())
1737 const char* moddir_flag =
1738 this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1739 std::string modflag = moddir_flag;
1740 modflag += this->Convert(mod_dir,
1741 cmLocalGenerator::START_OUTPUT,
1742 cmLocalGenerator::SHELL);
1743 this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1746 // If there is a separate module path flag then duplicate the
1747 // include path with it. This compiler does not search the include
1748 // path for modules.
1749 if(const char* modpath_flag =
1750 this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1752 std::vector<std::string> includes;
1753 this->LocalGenerator->GetIncludeDirectories(includes);
1754 for(std::vector<std::string>::const_iterator idi = includes.begin();
1755 idi != includes.end(); ++idi)
1757 std::string flg = modpath_flag;
1758 flg += this->Convert(idi->c_str(),
1759 cmLocalGenerator::NONE,
1760 cmLocalGenerator::SHELL);
1761 this->LocalGenerator->AppendFlags(flags, flg.c_str());