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