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