1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
6 Date: $Date: 2008-10-09 19:30:07 $
7 Version: $Revision: 1.106 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmMakefileTargetGenerator.h"
19 #include "cmGeneratedFileStream.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmGlobalUnixMakefileGenerator3.h"
22 #include "cmLocalUnixMakefileGenerator3.h"
23 #include "cmMakefile.h"
24 #include "cmSourceFile.h"
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
);
61 case cmTarget::STATIC_LIBRARY
:
62 case cmTarget::SHARED_LIBRARY
:
63 case cmTarget::MODULE_LIBRARY
:
64 result
= new cmMakefileLibraryTargetGenerator(tgt
);
66 case cmTarget::UTILITY
:
67 result
= new cmMakefileUtilityTargetGenerator(tgt
);
71 // break; /* unreachable */
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
)
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
,
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
);
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());
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
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
)
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
)
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());
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
)
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
)
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
249 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
250 l
!= languages
.end(); ++l
)
252 cmStdString compiler
= "CMAKE_";
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();
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())
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_";
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.
290 ->AddLanguageFlags(flags
, lang
,
291 this->LocalGenerator
->ConfigurationName
.c_str());
293 // Fortran-specific flags computed for this target.
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"))
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
,
327 // Skip OS X content when not building a Framework or Bundle.
328 if(this->MacContentDirectory
.empty())
333 // Construct the full path to the content subdirectory.
334 std::string macdir
= this->MacContentDirectory
;
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
;
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 ";
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
);
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,
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
);
387 // don't know anything about this file so skip it
391 // Get the full path name of the object file.
392 bool hasSourceExtension
;
393 std::string objNoTargetDir
;
395 this->LocalGenerator
->GetObjectFileName(*this->Target
, source
,
397 &hasSourceExtension
);
399 // Avoid generating duplicate rules.
400 if(this->ObjectFiles
.find(obj
) == this->ObjectFiles
.end())
402 this->ObjectFiles
.insert(obj
);
407 err
<< "Warning: Source file \""
408 << source
.GetFullPath()
409 << "\" is listed multiple times for target \""
410 << this->Target
->GetName()
412 cmSystemTools::Message(err
.str().c_str(), "Warning");
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
);
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();
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
,
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
;
461 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target
, lang
)
465 //----------------------------------------------------------------------------
467 cmMakefileTargetGenerator
468 ::WriteObjectBuildFile(std::string
&obj
,
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();
481 // Write the build rule.
483 // Build the set of compiler flags.
486 // Add language-specific flags.
487 std::string langFlags
= "$(";
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());
502 cmsys::RegularExpression
r(regex
);
503 std::vector
<std::string
> args
;
504 cmSystemTools::ParseWindowsCommandLine(
505 this->Target
->GetProperty("COMPILE_FLAGS"),
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
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")
536 // Add language-specific defines.
537 std::string defines
= "$(";
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"
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"
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
595 commands
.push_back(progCmd
.str());
597 std::string buildEcho
= "Building ";
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
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
);
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
);
664 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
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
)
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
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
);
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
)
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
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
);
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
,
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";
835 (this->LocalGenerator
->GetRecursiveMakeCall(tgtMakefileName
.c_str(),
839 p_depends
.push_back(objectRequires
);
840 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
841 objectProvides
.c_str(), p_depends
,
844 // write the provides.build rule dependency on the obj file
846 p_depends
.push_back(relativeObj
);
847 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
848 temp
.c_str(), p_depends
, no_commands
,
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
)
871 objTarget
+= ".requires";
872 depends
.push_back(objTarget
);
876 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
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
,
895 this->LocalGenerator
->CreateCDCommand
897 this->Makefile
->GetStartOutputDirectory(),
898 cmLocalGenerator::HOME_OUTPUT
);
901 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
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
)
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
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())
942 *this->InfoFileStream
<< " )\n\n";
945 // Store list of targets linked directly or transitively.
947 *this->InfoFileStream
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();
966 di
+= lg
->GetTargetDirectory(*linkee
);
967 di
+= "/DependInfo.cmake";
968 *this->InfoFileStream
<< " \"" << di
<< "\"\n";
972 *this->InfoFileStream
976 // Check for a target-specific module output directory.
977 if(const char* mdir
= this->GetFortranModuleDirectory())
979 *this->InfoFileStream
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.
1005 << (this->LocalGenerator
->Convert(
1006 this->Makefile
->GetHomeOutputDirectory(),
1007 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
))
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
)
1024 << this->Convert(this->Makefile
->GetStartDirectory(),
1025 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1027 << this->Convert(this->Makefile
->GetHomeOutputDirectory(),
1028 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1030 << this->Convert(this->Makefile
->GetStartOutputDirectory(),
1031 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1033 << this->Convert(this->InfoFileNameFull
.c_str(),
1034 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1035 << " --color=$(COLOR)";
1036 commands
.push_back(depCmd
.str());
1038 // Make sure all custom command outputs in this target are built.
1039 if(this->CustomCommandDriver
== OnDepends
)
1041 this->DriveCustomCommands(depends
);
1045 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1047 depends
, commands
, true);
1050 //----------------------------------------------------------------------------
1052 cmMakefileTargetGenerator
1053 ::DriveCustomCommands(std::vector
<std::string
>& depends
)
1055 // Depend on all custom command outputs.
1056 const std::vector
<cmSourceFile
*>& sources
=
1057 this->Target
->GetSourceFiles();
1058 for(std::vector
<cmSourceFile
*>::const_iterator source
= sources
.begin();
1059 source
!= sources
.end(); ++source
)
1061 if(cmCustomCommand
* cc
= (*source
)->GetCustomCommand())
1063 const std::vector
<std::string
>& outputs
= cc
->GetOutputs();
1064 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1065 o
!= outputs
.end(); ++o
)
1067 depends
.push_back(*o
);
1073 //----------------------------------------------------------------------------
1074 void cmMakefileTargetGenerator
1075 ::WriteObjectDependRules(cmSourceFile
& source
,
1076 std::vector
<std::string
>& depends
)
1078 // Create the list of dependencies known at cmake time. These are
1079 // shared between the object file and dependency scanning rule.
1080 depends
.push_back(source
.GetFullPath());
1081 if(const char* objectDeps
= source
.GetProperty("OBJECT_DEPENDS"))
1083 std::vector
<std::string
> deps
;
1084 cmSystemTools::ExpandListArgument(objectDeps
, deps
);
1085 for(std::vector
<std::string
>::iterator i
= deps
.begin();
1086 i
!= deps
.end(); ++i
)
1088 depends
.push_back(i
->c_str());
1093 //----------------------------------------------------------------------------
1094 void cmMakefileTargetGenerator
1095 ::GenerateCustomRuleFile(const cmCustomCommand
& cc
)
1097 // Collect the commands.
1098 std::vector
<std::string
> commands
;
1099 std::string comment
= this->LocalGenerator
->ConstructComment(cc
);
1100 if(!comment
.empty())
1102 // add in a progress call if needed
1103 std::string progressDir
= this->Makefile
->GetHomeOutputDirectory();
1104 progressDir
+= cmake::GetCMakeFilesDirectory();
1105 cmOStringStream progCmd
;
1106 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
1107 progCmd
<< this->LocalGenerator
->Convert(progressDir
.c_str(),
1108 cmLocalGenerator::FULL
,
1109 cmLocalGenerator::SHELL
);
1110 this->NumberOfProgressActions
++;
1111 progCmd
<< " $(CMAKE_PROGRESS_"
1112 << this->NumberOfProgressActions
1114 commands
.push_back(progCmd
.str());
1115 this->LocalGenerator
1116 ->AppendEcho(commands
, comment
.c_str(),
1117 cmLocalUnixMakefileGenerator3::EchoGenerate
);
1119 // Below we need to skip over the echo and progress commands.
1120 unsigned int skip
= static_cast<unsigned int>(commands
.size());
1122 // Now append the actual user-specified commands.
1123 this->LocalGenerator
->AppendCustomCommand(commands
, cc
);
1125 // Collect the dependencies.
1126 std::vector
<std::string
> depends
;
1127 this->LocalGenerator
->AppendCustomDepend(depends
, cc
);
1129 // Check whether we need to bother checking for a symbolic output.
1130 bool need_symbolic
= this->GlobalGenerator
->GetNeedSymbolicMark();
1133 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1134 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1136 bool symbolic
= false;
1139 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1141 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1144 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1145 o
->c_str(), depends
, commands
,
1148 // If the rule has changed make sure the output is rebuilt.
1151 this->GlobalGenerator
->AddRuleHash(cc
.GetOutputs(),
1152 commands
.begin()+skip
,
1157 // Write rules to drive building any outputs beyond the first.
1158 const char* in
= o
->c_str();
1159 for(++o
; o
!= outputs
.end(); ++o
)
1161 bool symbolic
= false;
1164 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1166 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1169 this->GenerateExtraOutput(o
->c_str(), in
, symbolic
);
1172 // Setup implicit dependency scanning.
1173 for(cmCustomCommand::ImplicitDependsList::const_iterator
1174 idi
= cc
.GetImplicitDepends().begin();
1175 idi
!= cc
.GetImplicitDepends().end(); ++idi
)
1177 std::string objFullPath
=
1178 this->Convert(outputs
[0].c_str(), cmLocalGenerator::FULL
);
1179 std::string srcFullPath
=
1180 this->Convert(idi
->second
.c_str(), cmLocalGenerator::FULL
);
1181 this->LocalGenerator
->
1182 AddImplicitDepends(*this->Target
, idi
->first
.c_str(),
1183 objFullPath
.c_str(),
1184 srcFullPath
.c_str());
1188 //----------------------------------------------------------------------------
1190 cmMakefileTargetGenerator
1191 ::GenerateExtraOutput(const char* out
, const char* in
, bool symbolic
)
1193 // Add a rule to build the primary output if the extra output needs
1195 std::vector
<std::string
> commands
;
1196 std::vector
<std::string
> depends
;
1197 std::string emptyCommand
= this->GlobalGenerator
->GetEmptyRuleHackCommand();
1198 if(!emptyCommand
.empty())
1200 commands
.push_back(emptyCommand
);
1202 depends
.push_back(in
);
1203 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1204 out
, depends
, commands
,
1207 // Register the extra output as paired with the first output so that
1208 // the check-build-system step will remove the primary output if any
1209 // extra outputs are missing. This forces the rule to regenerate
1211 this->AddMultipleOutputPair(out
, in
);
1214 //----------------------------------------------------------------------------
1216 cmMakefileTargetGenerator
1217 ::WriteObjectsVariable(std::string
& variableName
,
1218 std::string
& variableNameExternal
)
1220 // Write a make variable assignment that lists all objects for the
1223 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1225 *this->BuildFileStream
1226 << "# Object files for target " << this->Target
->GetName() << "\n"
1227 << variableName
.c_str() << " =";
1229 const char* objName
=
1230 this->Makefile
->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1231 const char* lineContinue
=
1232 this->Makefile
->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1235 lineContinue
= "\\";
1237 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1238 i
!= this->Objects
.end(); ++i
)
1240 *this->BuildFileStream
<< " " << lineContinue
<< "\n";
1243 *this->BuildFileStream
<<
1244 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1245 cmLocalGenerator::MAKEFILE
);
1249 *this->BuildFileStream
<<
1250 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1253 *this->BuildFileStream
<< "\n";
1255 // Write a make variable assignment that lists all external objects
1257 variableNameExternal
=
1258 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1259 "_EXTERNAL_OBJECTS");
1260 *this->BuildFileStream
1262 << "# External object files for target "
1263 << this->Target
->GetName() << "\n"
1264 << variableNameExternal
.c_str() << " =";
1265 for(std::vector
<std::string
>::const_iterator i
=
1266 this->ExternalObjects
.begin();
1267 i
!= this->ExternalObjects
.end(); ++i
)
1269 object
= this->Convert(i
->c_str(),cmLocalGenerator::START_OUTPUT
);
1270 *this->BuildFileStream
1271 << " " << lineContinue
<< "\n"
1272 << this->Makefile
->GetSafeDefinition("CMAKE_OBJECT_NAME");
1275 *this->BuildFileStream
<<
1276 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1277 cmLocalGenerator::MAKEFILE
);
1281 *this->BuildFileStream
<<
1282 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1285 *this->BuildFileStream
<< "\n" << "\n";
1288 //----------------------------------------------------------------------------
1290 cmMakefileTargetGenerator
1291 ::WriteObjectsString(std::string
& buildObjs
)
1293 std::vector
<std::string
> objStrings
;
1294 this->WriteObjectsStrings(objStrings
);
1295 buildObjs
= objStrings
[0];
1298 //----------------------------------------------------------------------------
1299 class cmMakefileTargetGeneratorObjectStrings
1302 cmMakefileTargetGeneratorObjectStrings(std::vector
<std::string
>& strings
,
1304 cmLocalUnixMakefileGenerator3
* lg
,
1305 std::string::size_type limit
):
1306 Strings(strings
), Makefile(mf
), LocalGenerator(lg
), LengthLimit(limit
)
1310 void Feed(std::string
const& obj
)
1312 // Construct the name of the next object.
1314 this->LocalGenerator
->Convert(obj
.c_str(),
1315 cmLocalGenerator::START_OUTPUT
,
1316 cmLocalGenerator::SHELL
);
1318 // Roll over to next string if the limit will be exceeded.
1319 if(this->LengthLimit
!= std::string::npos
&&
1320 (this->CurrentString
.length() + 1 + this->NextObject
.length()
1321 > this->LengthLimit
))
1323 this->Strings
.push_back(this->CurrentString
);
1324 this->CurrentString
= "";
1328 // Separate from previous object.
1329 this->CurrentString
+= this->Space
;
1332 // Append this object.
1333 this->CurrentString
+= this->NextObject
;
1337 this->Strings
.push_back(this->CurrentString
);
1340 std::vector
<std::string
>& Strings
;
1341 cmMakefile
* Makefile
;
1342 cmLocalUnixMakefileGenerator3
* LocalGenerator
;
1343 std::string::size_type LengthLimit
;
1344 std::string CurrentString
;
1345 std::string NextObject
;
1349 //----------------------------------------------------------------------------
1351 cmMakefileTargetGenerator
1352 ::WriteObjectsStrings(std::vector
<std::string
>& objStrings
,
1353 std::string::size_type limit
)
1355 cmMakefileTargetGeneratorObjectStrings
1356 helper(objStrings
, this->Makefile
, this->LocalGenerator
, limit
);
1357 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1358 i
!= this->Objects
.end(); ++i
)
1362 for(std::vector
<std::string
>::const_iterator i
=
1363 this->ExternalObjects
.begin();
1364 i
!= this->ExternalObjects
.end(); ++i
)
1371 //----------------------------------------------------------------------------
1372 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output
,
1375 // Compute the name of the driver target.
1377 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
1378 std::string buildTargetRuleName
= dir
;
1379 buildTargetRuleName
+= relink
?"/preinstall":"/build";
1380 buildTargetRuleName
= this->Convert(buildTargetRuleName
.c_str(),
1381 cmLocalGenerator::HOME_OUTPUT
,
1382 cmLocalGenerator::UNCHANGED
);
1384 // Build the list of target outputs to drive.
1385 std::vector
<std::string
> depends
;
1388 depends
.push_back(main_output
);
1391 const char* comment
= 0;
1394 // Setup the comment for the preinstall driver.
1395 comment
= "Rule to relink during preinstall.";
1399 // Setup the comment for the main build driver.
1400 comment
= "Rule to build all files generated by this target.";
1402 // Make sure all custom command outputs in this target are built.
1403 if(this->CustomCommandDriver
== OnBuild
)
1405 this->DriveCustomCommands(depends
);
1408 // Make sure the extra files are built.
1409 for(std::set
<cmStdString
>::const_iterator i
= this->ExtraFiles
.begin();
1410 i
!= this->ExtraFiles
.end(); ++i
)
1412 depends
.push_back(*i
);
1416 // Write the driver rule.
1417 std::vector
<std::string
> no_commands
;
1418 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, comment
,
1419 buildTargetRuleName
.c_str(),
1420 depends
, no_commands
, true);
1423 //----------------------------------------------------------------------------
1424 std::string
cmMakefileTargetGenerator::GetFrameworkFlags()
1427 return std::string();
1429 std::set
<cmStdString
> emitted
;
1430 emitted
.insert("/System/Library/Frameworks");
1431 std::vector
<std::string
> includes
;
1432 this->LocalGenerator
->GetIncludeDirectories(includes
);
1433 std::vector
<std::string
>::iterator i
;
1434 // check all include directories for frameworks as this
1435 // will already have added a -F for the framework
1436 for(i
= includes
.begin(); i
!= includes
.end(); ++i
)
1438 if(this->Target
->NameResolvesToFramework(i
->c_str()))
1440 std::string frameworkDir
= *i
;
1441 frameworkDir
+= "/../";
1442 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1443 emitted
.insert(frameworkDir
);
1448 std::vector
<std::string
>& frameworks
= this->Target
->GetFrameworks();
1449 for(i
= frameworks
.begin();
1450 i
!= frameworks
.end(); ++i
)
1452 if(emitted
.insert(*i
).second
)
1455 flags
+= this->Convert(i
->c_str(),
1456 cmLocalGenerator::START_OUTPUT
,
1457 cmLocalGenerator::SHELL
, true);
1465 //----------------------------------------------------------------------------
1466 void cmMakefileTargetGenerator
1467 ::AppendTargetDepends(std::vector
<std::string
>& depends
)
1469 // Static libraries never depend on anything for linking.
1470 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
1475 // Loop over all library dependencies.
1476 const char* cfg
= this->LocalGenerator
->ConfigurationName
.c_str();
1477 if(cmComputeLinkInformation
* cli
= this->Target
->GetLinkInformation(cfg
))
1479 std::vector
<std::string
> const& libDeps
= cli
->GetDepends();
1480 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
1481 j
!= libDeps
.end(); ++j
)
1483 depends
.push_back(*j
);
1488 //----------------------------------------------------------------------------
1489 void cmMakefileTargetGenerator
1490 ::CloseFileStreams()
1492 delete this->BuildFileStream
;
1493 delete this->InfoFileStream
;
1494 delete this->FlagFileStream
;
1497 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar
,
1498 const char* linkLang
,
1499 std::string
& linkFlags
)
1501 // check for language flags that are not allowed at link time, and
1502 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1503 // which fails, there may be more]
1505 std::string removeFlags
= "CMAKE_";
1506 removeFlags
+= linkLang
;
1507 removeFlags
+= flagVar
;
1508 std::string removeflags
=
1509 this->Makefile
->GetSafeDefinition(removeFlags
.c_str());
1510 std::vector
<std::string
> removeList
;
1511 cmSystemTools::ExpandListArgument(removeflags
, removeList
);
1512 for(std::vector
<std::string
>::iterator i
= removeList
.begin();
1513 i
!= removeList
.end(); ++i
)
1515 cmSystemTools::ReplaceString(linkFlags
, i
->c_str(), "");
1519 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total
,
1520 unsigned long ¤t
)
1522 cmGeneratedFileStream
*progressFileStream
=
1523 new cmGeneratedFileStream(this->ProgressFileNameFull
.c_str());
1524 if(!progressFileStream
)
1531 for (i
= 1; i
<= this->NumberOfProgressActions
; ++i
)
1534 << "CMAKE_PROGRESS_" << i
<< " = ";
1538 *progressFileStream
<< num
;
1539 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1542 else if (((i
+current
)*100)/total
> ((i
-1+current
)*100)/total
)
1544 num
= ((i
+current
)*100)/total
;
1545 *progressFileStream
<< num
;
1546 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1549 *progressFileStream
<< "\n";
1551 *progressFileStream
<< "\n";
1552 current
+= this->NumberOfProgressActions
;
1553 delete progressFileStream
;
1556 //----------------------------------------------------------------------------
1558 cmMakefileTargetGenerator
1559 ::AddMultipleOutputPair(const char* depender
, const char* dependee
)
1561 MultipleOutputPairsType::value_type
p(depender
, dependee
);
1562 this->MultipleOutputPairs
.insert(p
);
1565 //----------------------------------------------------------------------------
1567 cmMakefileTargetGenerator
1568 ::CreateLinkScript(const char* name
,
1569 std::vector
<std::string
> const& link_commands
,
1570 std::vector
<std::string
>& makefile_commands
,
1571 std::vector
<std::string
>& makefile_depends
)
1573 // Create the link script file.
1574 std::string linkScriptName
= this->TargetBuildDirectoryFull
;
1575 linkScriptName
+= "/";
1576 linkScriptName
+= name
;
1577 cmGeneratedFileStream
linkScriptStream(linkScriptName
.c_str());
1578 linkScriptStream
.SetCopyIfDifferent(true);
1579 for(std::vector
<std::string
>::const_iterator cmd
= link_commands
.begin();
1580 cmd
!= link_commands
.end(); ++cmd
)
1582 // Do not write out empty commands or commands beginning in the
1584 if(!cmd
->empty() && (*cmd
)[0] != ':')
1586 linkScriptStream
<< *cmd
<< "\n";
1590 // Create the makefile command to invoke the link script.
1591 std::string link_command
= "$(CMAKE_COMMAND) -E cmake_link_script ";
1592 link_command
+= this->Convert(linkScriptName
.c_str(),
1593 cmLocalGenerator::START_OUTPUT
,
1594 cmLocalGenerator::SHELL
);
1595 link_command
+= " --verbose=$(VERBOSE)";
1596 makefile_commands
.push_back(link_command
);
1597 makefile_depends
.push_back(linkScriptName
);
1600 //----------------------------------------------------------------------------
1602 cmMakefileTargetGenerator
1603 ::CreateResponseFile(const char* name
, std::string
const& options
,
1604 std::vector
<std::string
>& makefile_depends
)
1606 // Create the response file.
1607 std::string responseFileNameFull
= this->TargetBuildDirectoryFull
;
1608 responseFileNameFull
+= "/";
1609 responseFileNameFull
+= name
;
1610 cmGeneratedFileStream
responseStream(responseFileNameFull
.c_str());
1611 responseStream
.SetCopyIfDifferent(true);
1612 responseStream
<< options
<< "\n";
1614 // Add a dependency so the target will rebuild when the set of
1616 makefile_depends
.push_back(responseFileNameFull
);
1618 // Construct the name to be used on the command line.
1619 std::string responseFileName
= this->TargetBuildDirectory
;
1620 responseFileName
+= "/";
1621 responseFileName
+= name
;
1622 return responseFileName
;
1625 //----------------------------------------------------------------------------
1626 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1628 // Compute the module directory.
1629 if(!this->FortranModuleDirectoryComputed
)
1631 const char* target_mod_dir
=
1632 this->Target
->GetProperty("Fortran_MODULE_DIRECTORY");
1633 const char* moddir_flag
=
1634 this->Makefile
->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1635 if(target_mod_dir
&& moddir_flag
)
1637 // Compute the full path to the module directory.
1638 if(cmSystemTools::FileIsFullPath(target_mod_dir
))
1640 // Already a full path.
1641 this->FortranModuleDirectory
= target_mod_dir
;
1645 // Interpret relative to the current output directory.
1646 this->FortranModuleDirectory
=
1647 this->Makefile
->GetCurrentOutputDirectory();
1648 this->FortranModuleDirectory
+= "/";
1649 this->FortranModuleDirectory
+= target_mod_dir
;
1652 // Make sure the module output directory exists.
1653 cmSystemTools::MakeDirectory(this->FortranModuleDirectory
.c_str());
1655 this->FortranModuleDirectoryComputed
= true;
1658 // Return the computed directory.
1659 if(this->FortranModuleDirectory
.empty())
1665 return this->FortranModuleDirectory
.c_str();
1669 //----------------------------------------------------------------------------
1670 void cmMakefileTargetGenerator::AddFortranFlags(std::string
& flags
)
1672 // Add a module output directory flag if necessary.
1673 if(const char* mod_dir
= this->GetFortranModuleDirectory())
1675 const char* moddir_flag
=
1676 this->Makefile
->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1677 std::string modflag
= moddir_flag
;
1678 modflag
+= this->Convert(mod_dir
,
1679 cmLocalGenerator::START_OUTPUT
,
1680 cmLocalGenerator::SHELL
);
1681 this->LocalGenerator
->AppendFlags(flags
, modflag
.c_str());
1684 // If there is a separate module path flag then duplicate the
1685 // include path with it. This compiler does not search the include
1686 // path for modules.
1687 if(const char* modpath_flag
=
1688 this->Makefile
->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1690 std::vector
<std::string
> includes
;
1691 this->LocalGenerator
->GetIncludeDirectories(includes
);
1692 for(std::vector
<std::string
>::const_iterator idi
= includes
.begin();
1693 idi
!= includes
.end(); ++idi
)
1695 std::string flg
= modpath_flag
;
1696 flg
+= this->Convert(idi
->c_str(),
1697 cmLocalGenerator::NONE
,
1698 cmLocalGenerator::SHELL
);
1699 this->LocalGenerator
->AppendFlags(flags
, flg
.c_str());