1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
6 Date: $Date: 2009-03-16 20:55:58 $
7 Version: $Revision: 1.118 $
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());
49 cmake
* cm
= this->GlobalGenerator
->GetCMakeInstance();
50 this->NoRuleMessages
= false;
51 if(const char* ruleStatus
= cm
->GetProperty("RULE_MESSAGES"))
53 this->NoRuleMessages
= cmSystemTools::IsOff(ruleStatus
);
57 cmMakefileTargetGenerator
*
58 cmMakefileTargetGenerator::New(cmTarget
*tgt
)
60 cmMakefileTargetGenerator
*result
= 0;
62 switch (tgt
->GetType())
64 case cmTarget::EXECUTABLE
:
65 result
= new cmMakefileExecutableTargetGenerator(tgt
);
67 case cmTarget::STATIC_LIBRARY
:
68 case cmTarget::SHARED_LIBRARY
:
69 case cmTarget::MODULE_LIBRARY
:
70 result
= new cmMakefileLibraryTargetGenerator(tgt
);
72 case cmTarget::UTILITY
:
73 result
= new cmMakefileUtilityTargetGenerator(tgt
);
77 // break; /* unreachable */
82 //----------------------------------------------------------------------------
83 void cmMakefileTargetGenerator::CreateRuleFile()
85 // Create a directory for this target.
86 this->TargetBuildDirectory
=
87 this->LocalGenerator
->GetTargetDirectory(*this->Target
);
88 this->TargetBuildDirectoryFull
=
89 this->LocalGenerator
->ConvertToFullPath(this->TargetBuildDirectory
);
90 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull
.c_str());
92 // Construct the rule file name.
93 this->BuildFileName
= this->TargetBuildDirectory
;
94 this->BuildFileName
+= "/build.make";
95 this->BuildFileNameFull
= this->TargetBuildDirectoryFull
;
96 this->BuildFileNameFull
+= "/build.make";
98 // Construct the rule file name.
99 this->ProgressFileName
= this->TargetBuildDirectory
;
100 this->ProgressFileName
+= "/progress.make";
101 this->ProgressFileNameFull
= this->TargetBuildDirectoryFull
;
102 this->ProgressFileNameFull
+= "/progress.make";
104 // reset the progress count
105 this->NumberOfProgressActions
= 0;
107 // Open the rule file. This should be copy-if-different because the
108 // rules may depend on this file itself.
109 this->BuildFileStream
=
110 new cmGeneratedFileStream(this->BuildFileNameFull
.c_str());
111 this->BuildFileStream
->SetCopyIfDifferent(true);
112 if(!this->BuildFileStream
)
116 this->LocalGenerator
->WriteDisclaimer(*this->BuildFileStream
);
117 this->LocalGenerator
->WriteSpecialTargetsTop(*this->BuildFileStream
);
120 //----------------------------------------------------------------------------
121 void cmMakefileTargetGenerator::WriteTargetBuildRules()
123 // write the custom commands for this target
124 // Look for files registered for cleaning in this directory.
125 if(const char* additional_clean_files
=
126 this->Makefile
->GetProperty
127 ("ADDITIONAL_MAKE_CLEAN_FILES"))
129 cmSystemTools::ExpandListArgument(additional_clean_files
,
133 // add custom commands to the clean rules?
134 const char* clean_no_custom
=
135 this->Makefile
->GetProperty("CLEAN_NO_CUSTOM");
136 bool clean
= cmSystemTools::IsOff(clean_no_custom
);
138 // First generate the object rule files. Save a list of all object
139 // files for this target.
140 const std::vector
<cmSourceFile
*>& sources
= this->Target
->GetSourceFiles();
141 for(std::vector
<cmSourceFile
*>::const_iterator source
= sources
.begin();
142 source
!= sources
.end(); ++source
)
144 cmTarget::SourceFileFlags tsFlags
=
145 this->Target
->GetTargetSourceFileFlags(*source
);
146 if(cmCustomCommand
* cc
= (*source
)->GetCustomCommand())
148 this->GenerateCustomRuleFile(*cc
);
151 const std::vector
<std::string
>& outputs
= cc
->GetOutputs();
152 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
153 o
!= outputs
.end(); ++o
)
155 this->CleanFiles
.push_back
156 (this->Convert(o
->c_str(),
157 cmLocalGenerator::START_OUTPUT
,
158 cmLocalGenerator::UNCHANGED
));
162 else if(tsFlags
.Type
!= cmTarget::SourceFileTypeNormal
)
164 this->WriteMacOSXContentRules(*(*source
), tsFlags
.MacFolder
);
166 else if(!(*source
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
168 if(!this->GlobalGenerator
->IgnoreFile
169 ((*source
)->GetExtension().c_str()))
171 // Generate this object file's rule file.
172 this->WriteObjectRuleFiles(*(*source
));
174 else if((*source
)->GetPropertyAsBool("EXTERNAL_OBJECT"))
176 // This is an external object file. Just add it.
177 this->ExternalObjects
.push_back((*source
)->GetFullPath());
181 // We only get here if a source file is not an external object
182 // and has an extension that is listed as an ignored file type
183 // for this language. No message or diagnosis should be
191 //----------------------------------------------------------------------------
192 void cmMakefileTargetGenerator::WriteCommonCodeRules()
194 // Include the dependencies for the target.
195 std::string dependFileNameFull
= this->TargetBuildDirectoryFull
;
196 dependFileNameFull
+= "/depend.make";
197 *this->BuildFileStream
198 << "# Include any dependencies generated for this target.\n"
199 << this->LocalGenerator
->IncludeDirective
<< " "
200 << this->Convert(dependFileNameFull
.c_str(),
201 cmLocalGenerator::HOME_OUTPUT
,
202 cmLocalGenerator::MAKEFILE
)
205 if(!this->NoRuleMessages
)
207 // Include the progress variables for the target.
208 *this->BuildFileStream
209 << "# Include the progress variables for this target.\n"
210 << this->LocalGenerator
->IncludeDirective
<< " "
211 << this->Convert(this->ProgressFileNameFull
.c_str(),
212 cmLocalGenerator::HOME_OUTPUT
,
213 cmLocalGenerator::MAKEFILE
)
217 // make sure the depend file exists
218 if (!cmSystemTools::FileExists(dependFileNameFull
.c_str()))
220 // Write an empty dependency file.
221 cmGeneratedFileStream
depFileStream(dependFileNameFull
.c_str());
223 << "# Empty dependencies file for " << this->Target
->GetName() << ".\n"
224 << "# This may be replaced when dependencies are built." << std::endl
;
227 // Open the flags file. This should be copy-if-different because the
228 // rules may depend on this file itself.
229 this->FlagFileNameFull
= this->TargetBuildDirectoryFull
;
230 this->FlagFileNameFull
+= "/flags.make";
231 this->FlagFileStream
=
232 new cmGeneratedFileStream(this->FlagFileNameFull
.c_str());
233 this->FlagFileStream
->SetCopyIfDifferent(true);
234 if(!this->FlagFileStream
)
238 this->LocalGenerator
->WriteDisclaimer(*this->FlagFileStream
);
240 // Include the flags for the target.
241 *this->BuildFileStream
242 << "# Include the compile flags for this target's objects.\n"
243 << this->LocalGenerator
->IncludeDirective
<< " "
244 << this->Convert(this->FlagFileNameFull
.c_str(),
245 cmLocalGenerator::HOME_OUTPUT
,
246 cmLocalGenerator::MAKEFILE
)
250 //----------------------------------------------------------------------------
251 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
253 // write language flags for target
254 std::set
<cmStdString
> languages
;
255 this->Target
->GetLanguages(languages
);
256 // put the compiler in the rules.make file so that if it changes
258 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
259 l
!= languages
.end(); ++l
)
261 cmStdString compiler
= "CMAKE_";
263 compiler
+= "_COMPILER";
264 *this->FlagFileStream
<< "# compile " << l
->c_str() << " with " <<
265 this->Makefile
->GetSafeDefinition(compiler
.c_str()) << "\n";
268 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
269 l
!= languages
.end(); ++l
)
271 const char *lang
= l
->c_str();
274 bool shared
= ((this->Target
->GetType() == cmTarget::SHARED_LIBRARY
) ||
275 (this->Target
->GetType() == cmTarget::MODULE_LIBRARY
));
277 // Add the export symbol definition for shared library objects.
278 if(const char* exportMacro
= this->Target
->GetExportMacro())
280 this->LocalGenerator
->AppendDefines(defines
, exportMacro
, lang
);
283 // Add preprocessor definitions for this target and configuration.
284 this->LocalGenerator
->AppendDefines
285 (defines
, this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), lang
);
286 this->LocalGenerator
->AppendDefines
287 (defines
, this->Target
->GetProperty("COMPILE_DEFINITIONS"), lang
);
288 std::string defPropName
= "COMPILE_DEFINITIONS_";
290 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
);
291 this->LocalGenerator
->AppendDefines
292 (defines
, this->Makefile
->GetProperty(defPropName
.c_str()), lang
);
293 this->LocalGenerator
->AppendDefines
294 (defines
, this->Target
->GetProperty(defPropName
.c_str()), lang
);
296 // Add language-specific flags.
298 ->AddLanguageFlags(flags
, lang
,
299 this->LocalGenerator
->ConfigurationName
.c_str());
301 // Fortran-specific flags computed for this target.
304 this->AddFortranFlags(flags
);
307 // Add shared-library flags if needed.
308 this->LocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
310 // Add include directory flags.
311 this->LocalGenerator
->
312 AppendFlags(flags
, this->LocalGenerator
->GetIncludeFlags(lang
));
313 // Add include directory flags.
314 this->LocalGenerator
->
315 AppendFlags(flags
,this->GetFrameworkFlags().c_str());
317 *this->FlagFileStream
<< lang
<< "_FLAGS = " << flags
<< "\n\n";
318 *this->FlagFileStream
<< lang
<< "_DEFINES = " << defines
<< "\n\n";
321 // Add target-specific flags.
322 if(this->Target
->GetProperty("COMPILE_FLAGS"))
325 this->LocalGenerator
->AppendFlags
326 (flags
, this->Target
->GetProperty("COMPILE_FLAGS"));
327 *this->FlagFileStream
<< "# TARGET_FLAGS = " << flags
<< "\n\n";
331 //----------------------------------------------------------------------------
332 void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile
& source
,
335 // Skip OS X content when not building a Framework or Bundle.
336 if(this->MacContentDirectory
.empty())
341 // Construct the full path to the content subdirectory.
342 std::string macdir
= this->MacContentDirectory
;
344 cmSystemTools::MakeDirectory(macdir
.c_str());
346 // Record use of this content location. Only the first level
347 // directory is needed.
349 std::string loc
= pkgloc
;
350 loc
= loc
.substr(0, loc
.find('/'));
351 this->MacContentFolders
.insert(loc
);
354 // Get the input file location.
355 std::string input
= source
.GetFullPath();
357 // Get the output file location.
358 std::string output
= macdir
;
360 output
+= cmSystemTools::GetFilenameName(input
);
361 this->CleanFiles
.push_back(this->Convert(output
.c_str(),
362 cmLocalGenerator::START_OUTPUT
));
363 output
= this->Convert(output
.c_str(), cmLocalGenerator::HOME_OUTPUT
);
365 // Create a rule to copy the content into the bundle.
366 std::vector
<std::string
> depends
;
367 std::vector
<std::string
> commands
;
368 depends
.push_back(input
);
369 std::string copyEcho
= "Copying OS X content ";
371 this->LocalGenerator
->AppendEcho(commands
, copyEcho
.c_str(),
372 cmLocalUnixMakefileGenerator3::EchoBuild
);
373 std::string copyCommand
= "$(CMAKE_COMMAND) -E copy ";
374 copyCommand
+= this->Convert(input
.c_str(),
375 cmLocalGenerator::NONE
,
376 cmLocalGenerator::SHELL
);
378 copyCommand
+= this->Convert(output
.c_str(),
379 cmLocalGenerator::NONE
,
380 cmLocalGenerator::SHELL
);
381 commands
.push_back(copyCommand
);
382 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
384 depends
, commands
, false);
385 this->ExtraFiles
.insert(output
);
388 //----------------------------------------------------------------------------
389 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile
& source
)
391 // Identify the language of the source file.
392 const char* lang
= this->LocalGenerator
->GetSourceFileLanguage(source
);
395 // don't know anything about this file so skip it
399 // Get the full path name of the object file.
400 bool hasSourceExtension
;
401 std::string objNoTargetDir
;
403 this->LocalGenerator
->GetObjectFileName(*this->Target
, source
,
405 &hasSourceExtension
);
407 // Avoid generating duplicate rules.
408 if(this->ObjectFiles
.find(obj
) == this->ObjectFiles
.end())
410 this->ObjectFiles
.insert(obj
);
415 err
<< "Warning: Source file \""
416 << source
.GetFullPath()
417 << "\" is listed multiple times for target \""
418 << this->Target
->GetName()
420 cmSystemTools::Message(err
.str().c_str(), "Warning");
424 // Create the directory containing the object file. This may be a
425 // subdirectory under the target's directory.
426 std::string dir
= cmSystemTools::GetFilenamePath(obj
.c_str());
427 cmSystemTools::MakeDirectory
428 (this->LocalGenerator
->ConvertToFullPath(dir
).c_str());
430 // Save this in the target's list of object files.
431 this->Objects
.push_back(obj
);
432 this->CleanFiles
.push_back(obj
);
435 //std::string relativeObj
436 //= this->LocalGenerator->GetHomeRelativeOutputPath();
437 //relativeObj += obj;
439 // we compute some depends when writing the depend.make that we will also
440 // use in the build.make, same with depMakeFile
441 std::vector
<std::string
> depends
;
442 std::string depMakeFile
;
444 // generate the build rule file
445 this->WriteObjectBuildFile(obj
, lang
, source
, depends
);
447 // The object file should be checked for dependency integrity.
448 std::string objFullPath
= this->Makefile
->GetCurrentOutputDirectory();
452 this->Convert(objFullPath
.c_str(), cmLocalGenerator::FULL
);
453 std::string srcFullPath
=
454 this->Convert(source
.GetFullPath().c_str(), cmLocalGenerator::FULL
);
455 this->LocalGenerator
->
456 AddImplicitDepends(*this->Target
, lang
,
458 srcFullPath
.c_str());
460 // add this to the list of objects for this local generator
461 if(cmSystemTools::FileIsFullPath(objNoTargetDir
.c_str()))
463 objNoTargetDir
= cmSystemTools::GetFilenameName(objNoTargetDir
);
465 cmLocalUnixMakefileGenerator3::LocalObjectInfo
& info
=
466 this->LocalGenerator
->LocalObjectFiles
[objNoTargetDir
];
467 info
.HasSourceExtension
= hasSourceExtension
;
469 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target
, lang
)
473 //----------------------------------------------------------------------------
475 cmMakefileTargetGenerator
476 ::WriteObjectBuildFile(std::string
&obj
,
478 cmSourceFile
& source
,
479 std::vector
<std::string
>& depends
)
481 this->LocalGenerator
->AppendRuleDepend(depends
,
482 this->FlagFileNameFull
.c_str());
484 // generate the depend scanning rule
485 this->WriteObjectDependRules(source
, depends
);
487 std::string relativeObj
= this->LocalGenerator
->GetHomeRelativeOutputPath();
489 // Write the build rule.
491 // Build the set of compiler flags.
494 // Add language-specific flags.
495 std::string langFlags
= "$(";
497 langFlags
+= "_FLAGS)";
498 this->LocalGenerator
->AppendFlags(flags
, langFlags
.c_str());
500 // Add target-specific flags.
501 if(this->Target
->GetProperty("COMPILE_FLAGS"))
503 std::string langIncludeExpr
= "CMAKE_";
504 langIncludeExpr
+= lang
;
505 langIncludeExpr
+= "_FLAG_REGEX";
506 const char* regex
= this->Makefile
->
507 GetDefinition(langIncludeExpr
.c_str());
510 cmsys::RegularExpression
r(regex
);
511 std::vector
<std::string
> args
;
512 cmSystemTools::ParseWindowsCommandLine(
513 this->Target
->GetProperty("COMPILE_FLAGS"),
515 for(std::vector
<std::string
>::iterator i
= args
.begin();
516 i
!= args
.end(); ++i
)
518 if(r
.find(i
->c_str()))
520 this->LocalGenerator
->AppendFlags
527 this->LocalGenerator
->AppendFlags
528 (flags
, this->Target
->GetProperty("COMPILE_FLAGS"));
532 // Add flags from source file properties.
533 if (source
.GetProperty("COMPILE_FLAGS"))
535 this->LocalGenerator
->AppendFlags
536 (flags
, source
.GetProperty("COMPILE_FLAGS"));
537 *this->FlagFileStream
<< "# Custom flags: "
538 << relativeObj
<< "_FLAGS = "
539 << source
.GetProperty("COMPILE_FLAGS")
544 // Add language-specific defines.
545 std::string defines
= "$(";
547 defines
+= "_DEFINES)";
549 // Add source-sepcific preprocessor definitions.
550 if(const char* compile_defs
= source
.GetProperty("COMPILE_DEFINITIONS"))
552 this->LocalGenerator
->AppendDefines(defines
, compile_defs
, lang
);
553 *this->FlagFileStream
<< "# Custom defines: "
554 << relativeObj
<< "_DEFINES = "
555 << compile_defs
<< "\n"
558 std::string configUpper
=
559 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
);
560 std::string defPropName
= "COMPILE_DEFINITIONS_";
561 defPropName
+= configUpper
;
562 if(const char* config_compile_defs
=
563 source
.GetProperty(defPropName
.c_str()))
565 this->LocalGenerator
->AppendDefines(defines
, config_compile_defs
, lang
);
566 *this->FlagFileStream
567 << "# Custom defines: "
568 << relativeObj
<< "_DEFINES_" << configUpper
569 << " = " << config_compile_defs
<< "\n"
573 // Get the output paths for source and object files.
574 std::string sourceFile
= source
.GetFullPath();
575 if(this->LocalGenerator
->UseRelativePaths
)
577 sourceFile
= this->Convert(sourceFile
.c_str(),
578 cmLocalGenerator::START_OUTPUT
);
580 sourceFile
= this->Convert(sourceFile
.c_str(),
581 cmLocalGenerator::NONE
,
582 cmLocalGenerator::SHELL
);
583 std::string objectFile
= this->Convert(obj
.c_str(),
584 cmLocalGenerator::START_OUTPUT
,
585 cmLocalGenerator::SHELL
);
587 // Construct the build message.
588 std::vector
<std::string
> no_commands
;
589 std::vector
<std::string
> commands
;
591 // add in a progress call if needed
592 this->AppendProgress(commands
);
594 if(!this->NoRuleMessages
)
596 std::string buildEcho
= "Building ";
598 buildEcho
+= " object ";
599 buildEcho
+= relativeObj
;
600 this->LocalGenerator
->AppendEcho
601 (commands
, buildEcho
.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild
);
604 std::string targetOutPathPDB
;
606 std::string targetFullPathPDB
;
607 const char* configName
= this->LocalGenerator
->ConfigurationName
.c_str();
608 if(this->Target
->GetType() == cmTarget::EXECUTABLE
||
609 this->Target
->GetType() == cmTarget::STATIC_LIBRARY
||
610 this->Target
->GetType() == cmTarget::SHARED_LIBRARY
||
611 this->Target
->GetType() == cmTarget::MODULE_LIBRARY
)
613 targetFullPathPDB
= this->Target
->GetDirectory();
614 targetFullPathPDB
+= "/";
615 targetFullPathPDB
+= this->Target
->GetPDBName(configName
);
618 this->Convert(targetFullPathPDB
.c_str(),cmLocalGenerator::FULL
,
619 cmLocalGenerator::SHELL
);
621 cmLocalGenerator::RuleVariables vars
;
622 vars
.RuleLauncher
= "RULE_LAUNCH_COMPILE";
623 vars
.CMTarget
= this->Target
;
624 vars
.Language
= lang
;
625 vars
.TargetPDB
= targetOutPathPDB
.c_str();
626 vars
.Source
= sourceFile
.c_str();
627 std::string shellObj
=
628 this->Convert(obj
.c_str(),
629 cmLocalGenerator::NONE
,
630 cmLocalGenerator::SHELL
).c_str();
631 vars
.Object
= shellObj
.c_str();
632 std::string objectDir
= cmSystemTools::GetFilenamePath(obj
);
633 objectDir
= this->Convert(objectDir
.c_str(),
634 cmLocalGenerator::START_OUTPUT
,
635 cmLocalGenerator::SHELL
);
636 vars
.ObjectDir
= objectDir
.c_str();
637 vars
.Flags
= flags
.c_str();
638 vars
.Defines
= defines
.c_str();
640 // Construct the compile rules.
642 std::string compileRuleVar
= "CMAKE_";
643 compileRuleVar
+= lang
;
644 compileRuleVar
+= "_COMPILE_OBJECT";
645 std::string compileRule
=
646 this->Makefile
->GetRequiredDefinition(compileRuleVar
.c_str());
647 std::vector
<std::string
> compileCommands
;
648 cmSystemTools::ExpandListArgument(compileRule
, compileCommands
);
650 // Expand placeholders in the commands.
651 for(std::vector
<std::string
>::iterator i
= compileCommands
.begin();
652 i
!= compileCommands
.end(); ++i
)
654 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
657 // Change the command working directory to the local build tree.
658 this->LocalGenerator
->CreateCDCommand
660 this->Makefile
->GetStartOutputDirectory(),
661 cmLocalGenerator::HOME_OUTPUT
);
662 commands
.insert(commands
.end(),
663 compileCommands
.begin(), compileCommands
.end());
667 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
669 depends
, commands
, false);
671 // Check for extra outputs created by the compilation.
672 if(const char* extra_outputs_str
=
673 source
.GetProperty("OBJECT_OUTPUTS"))
675 std::vector
<std::string
> extra_outputs
;
676 cmSystemTools::ExpandListArgument(extra_outputs_str
, extra_outputs
);
677 for(std::vector
<std::string
>::const_iterator eoi
= extra_outputs
.begin();
678 eoi
!= extra_outputs
.end(); ++eoi
)
680 // Register this as an extra output for the object file rule.
681 // This will cause the object file to be rebuilt if the extra
682 // output is missing.
683 this->GenerateExtraOutput(eoi
->c_str(), relativeObj
.c_str(), false);
685 // Register this as an extra file to clean.
686 this->CleanFiles
.push_back(eoi
->c_str());
690 bool lang_is_c_or_cxx
= ((strcmp(lang
, "C") == 0) ||
691 (strcmp(lang
, "CXX") == 0));
692 bool do_preprocess_rules
= lang_is_c_or_cxx
&&
693 this->LocalGenerator
->GetCreatePreprocessedSourceRules();
694 bool do_assembly_rules
= lang_is_c_or_cxx
&&
695 this->LocalGenerator
->GetCreateAssemblySourceRules();
696 if(do_preprocess_rules
|| do_assembly_rules
)
698 std::vector
<std::string
> force_depends
;
699 force_depends
.push_back("cmake_force");
700 std::string::size_type dot_pos
= relativeObj
.rfind(".");
701 std::string relativeObjBase
= relativeObj
.substr(0, dot_pos
);
702 dot_pos
= obj
.rfind(".");
703 std::string objBase
= obj
.substr(0, dot_pos
);
705 if(do_preprocess_rules
)
708 std::string relativeObjI
= relativeObjBase
+ ".i";
709 std::string objI
= objBase
+ ".i";
711 std::string preprocessEcho
= "Preprocessing ";
712 preprocessEcho
+= lang
;
713 preprocessEcho
+= " source to ";
714 preprocessEcho
+= objI
;
715 this->LocalGenerator
->AppendEcho(
716 commands
, preprocessEcho
.c_str(),
717 cmLocalUnixMakefileGenerator3::EchoBuild
720 std::string preprocessRuleVar
= "CMAKE_";
721 preprocessRuleVar
+= lang
;
722 preprocessRuleVar
+= "_CREATE_PREPROCESSED_SOURCE";
723 if(const char* preprocessRule
=
724 this->Makefile
->GetDefinition(preprocessRuleVar
.c_str()))
726 std::vector
<std::string
> preprocessCommands
;
727 cmSystemTools::ExpandListArgument(preprocessRule
, preprocessCommands
);
729 std::string shellObjI
=
730 this->Convert(objI
.c_str(),
731 cmLocalGenerator::NONE
,
732 cmLocalGenerator::SHELL
).c_str();
733 vars
.PreprocessedSource
= shellObjI
.c_str();
735 // Expand placeholders in the commands.
736 for(std::vector
<std::string
>::iterator i
= preprocessCommands
.begin();
737 i
!= preprocessCommands
.end(); ++i
)
739 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
742 this->LocalGenerator
->CreateCDCommand
744 this->Makefile
->GetStartOutputDirectory(),
745 cmLocalGenerator::HOME_OUTPUT
);
746 commands
.insert(commands
.end(),
747 preprocessCommands
.begin(),
748 preprocessCommands
.end());
752 std::string cmd
= "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
753 cmd
+= preprocessRuleVar
;
754 commands
.push_back(cmd
);
757 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
758 relativeObjI
.c_str(),
759 force_depends
, commands
, false);
762 if(do_assembly_rules
)
765 std::string relativeObjS
= relativeObjBase
+ ".s";
766 std::string objS
= objBase
+ ".s";
768 std::string assemblyEcho
= "Compiling ";
769 assemblyEcho
+= lang
;
770 assemblyEcho
+= " source to assembly ";
771 assemblyEcho
+= objS
;
772 this->LocalGenerator
->AppendEcho(
773 commands
, assemblyEcho
.c_str(),
774 cmLocalUnixMakefileGenerator3::EchoBuild
777 std::string assemblyRuleVar
= "CMAKE_";
778 assemblyRuleVar
+= lang
;
779 assemblyRuleVar
+= "_CREATE_ASSEMBLY_SOURCE";
780 if(const char* assemblyRule
=
781 this->Makefile
->GetDefinition(assemblyRuleVar
.c_str()))
783 std::vector
<std::string
> assemblyCommands
;
784 cmSystemTools::ExpandListArgument(assemblyRule
, assemblyCommands
);
786 std::string shellObjS
=
787 this->Convert(objS
.c_str(),
788 cmLocalGenerator::NONE
,
789 cmLocalGenerator::SHELL
).c_str();
790 vars
.AssemblySource
= shellObjS
.c_str();
792 // Expand placeholders in the commands.
793 for(std::vector
<std::string
>::iterator i
= assemblyCommands
.begin();
794 i
!= assemblyCommands
.end(); ++i
)
796 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
799 this->LocalGenerator
->CreateCDCommand
801 this->Makefile
->GetStartOutputDirectory(),
802 cmLocalGenerator::HOME_OUTPUT
);
803 commands
.insert(commands
.end(),
804 assemblyCommands
.begin(),
805 assemblyCommands
.end());
809 std::string cmd
= "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
810 cmd
+= assemblyRuleVar
;
811 commands
.push_back(cmd
);
814 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
815 relativeObjS
.c_str(),
816 force_depends
, commands
, false);
820 // If the language needs provides-requires mode, create the
821 // corresponding targets.
822 std::string objectRequires
= relativeObj
;
823 objectRequires
+= ".requires";
824 std::vector
<std::string
> p_depends
;
825 // always provide an empty requires target
826 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
827 objectRequires
.c_str(), p_depends
,
830 // write a build rule to recursively build what this obj provides
831 std::string objectProvides
= relativeObj
;
832 objectProvides
+= ".provides";
833 std::string temp
= relativeObj
;
834 temp
+= ".provides.build";
835 std::vector
<std::string
> r_commands
;
836 std::string tgtMakefileName
=
837 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
838 tgtMakefileName
+= "/build.make";
840 (this->LocalGenerator
->GetRecursiveMakeCall(tgtMakefileName
.c_str(),
844 p_depends
.push_back(objectRequires
);
845 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
846 objectProvides
.c_str(), p_depends
,
849 // write the provides.build rule dependency on the obj file
851 p_depends
.push_back(relativeObj
);
852 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
853 temp
.c_str(), p_depends
, no_commands
,
857 //----------------------------------------------------------------------------
858 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
860 std::vector
<std::string
> depends
;
861 std::vector
<std::string
> no_commands
;
863 // Construct the name of the dependency generation target.
864 std::string depTarget
=
865 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
866 depTarget
+= "/requires";
868 // This target drives dependency generation for all object files.
869 std::string relPath
= this->LocalGenerator
->GetHomeRelativeOutputPath();
870 std::string objTarget
;
871 for(std::vector
<std::string
>::const_iterator obj
= this->Objects
.begin();
872 obj
!= this->Objects
.end(); ++obj
)
876 objTarget
+= ".requires";
877 depends
.push_back(objTarget
);
881 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
883 depends
, no_commands
, true);
886 //----------------------------------------------------------------------------
887 void cmMakefileTargetGenerator::WriteTargetCleanRules()
889 std::vector
<std::string
> depends
;
890 std::vector
<std::string
> commands
;
892 // Construct the clean target name.
893 std::string cleanTarget
=
894 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
895 cleanTarget
+= "/clean";
897 // Construct the clean command.
898 this->LocalGenerator
->AppendCleanCommand(commands
, this->CleanFiles
,
900 this->LocalGenerator
->CreateCDCommand
902 this->Makefile
->GetStartOutputDirectory(),
903 cmLocalGenerator::HOME_OUTPUT
);
906 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
908 depends
, commands
, true);
912 //----------------------------------------------------------------------------
913 void cmMakefileTargetGenerator::WriteTargetDependRules()
915 // must write the targets depend info file
916 std::string dir
= this->LocalGenerator
->GetTargetDirectory(*this->Target
);
917 this->InfoFileNameFull
= dir
;
918 this->InfoFileNameFull
+= "/DependInfo.cmake";
919 this->InfoFileNameFull
=
920 this->LocalGenerator
->ConvertToFullPath(this->InfoFileNameFull
);
921 this->InfoFileStream
=
922 new cmGeneratedFileStream(this->InfoFileNameFull
.c_str());
923 this->InfoFileStream
->SetCopyIfDifferent(true);
924 if(!*this->InfoFileStream
)
928 this->LocalGenerator
->
929 WriteDependLanguageInfo(*this->InfoFileStream
,*this->Target
);
931 // Store multiple output pairs in the depend info file.
932 if(!this->MultipleOutputPairs
.empty())
934 *this->InfoFileStream
936 << "# Pairs of files generated by the same build rule.\n"
937 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
938 for(MultipleOutputPairsType::const_iterator pi
=
939 this->MultipleOutputPairs
.begin();
940 pi
!= this->MultipleOutputPairs
.end(); ++pi
)
942 *this->InfoFileStream
943 << " " << this->LocalGenerator
->EscapeForCMake(pi
->first
.c_str())
944 << " " << this->LocalGenerator
->EscapeForCMake(pi
->second
.c_str())
947 *this->InfoFileStream
<< " )\n\n";
950 // Store list of targets linked directly or transitively.
952 *this->InfoFileStream
954 << "# Targets to which this target links.\n"
955 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
956 std::set
<cmTarget
const*> emitted
;
957 const char* cfg
= this->LocalGenerator
->ConfigurationName
.c_str();
958 if(cmComputeLinkInformation
* cli
= this->Target
->GetLinkInformation(cfg
))
960 cmComputeLinkInformation::ItemVector
const& items
= cli
->GetItems();
961 for(cmComputeLinkInformation::ItemVector::const_iterator
962 i
= items
.begin(); i
!= items
.end(); ++i
)
964 cmTarget
const* linkee
= i
->Target
;
965 if(linkee
&& !linkee
->IsImported() && emitted
.insert(linkee
).second
)
967 cmMakefile
* mf
= linkee
->GetMakefile();
968 cmLocalGenerator
* lg
= mf
->GetLocalGenerator();
969 std::string di
= mf
->GetStartOutputDirectory();
971 di
+= lg
->GetTargetDirectory(*linkee
);
972 di
+= "/DependInfo.cmake";
973 *this->InfoFileStream
<< " \"" << di
<< "\"\n";
977 *this->InfoFileStream
981 // Check for a target-specific module output directory.
982 if(const char* mdir
= this->GetFortranModuleDirectory())
984 *this->InfoFileStream
986 << "# Fortran module output directory.\n"
987 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir
<< "\")\n";
990 // and now write the rule to use it
991 std::vector
<std::string
> depends
;
992 std::vector
<std::string
> commands
;
994 // Construct the name of the dependency generation target.
995 std::string depTarget
=
996 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
997 depTarget
+= "/depend";
999 // Add a command to call CMake to scan dependencies. CMake will
1000 // touch the corresponding depends file after scanning dependencies.
1001 cmOStringStream depCmd
;
1002 // TODO: Account for source file properties and directory-level
1003 // definitions when scanning for dependencies.
1004 #if !defined(_WIN32) || defined(__CYGWIN__)
1005 // This platform supports symlinks, so cmSystemTools will translate
1006 // paths. Make sure PWD is set to the original name of the home
1007 // output directory to help cmSystemTools to create the same
1008 // translation table for the dependency scanning process.
1010 << (this->LocalGenerator
->Convert(
1011 this->Makefile
->GetHomeOutputDirectory(),
1012 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
))
1015 // Generate a call this signature:
1017 // cmake -E cmake_depends <generator>
1018 // <home-src-dir> <start-src-dir>
1019 // <home-out-dir> <start-out-dir>
1020 // <dep-info> --color=$(COLOR)
1022 // This gives the dependency scanner enough information to recreate
1023 // the state of our local generator sufficiently for its needs.
1024 depCmd
<< "$(CMAKE_COMMAND) -E cmake_depends \""
1025 << this->GlobalGenerator
->GetName() << "\" "
1026 << this->Convert(this->Makefile
->GetHomeDirectory(),
1027 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1029 << this->Convert(this->Makefile
->GetStartDirectory(),
1030 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1032 << this->Convert(this->Makefile
->GetHomeOutputDirectory(),
1033 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1035 << this->Convert(this->Makefile
->GetStartOutputDirectory(),
1036 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
1038 << this->Convert(this->InfoFileNameFull
.c_str(),
1039 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
);
1040 if(this->LocalGenerator
->GetColorMakefile())
1042 depCmd
<< " --color=$(COLOR)";
1044 commands
.push_back(depCmd
.str());
1046 // Make sure all custom command outputs in this target are built.
1047 if(this->CustomCommandDriver
== OnDepends
)
1049 this->DriveCustomCommands(depends
);
1053 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1055 depends
, commands
, true);
1058 //----------------------------------------------------------------------------
1060 cmMakefileTargetGenerator
1061 ::DriveCustomCommands(std::vector
<std::string
>& depends
)
1063 // Depend on all custom command outputs.
1064 const std::vector
<cmSourceFile
*>& sources
=
1065 this->Target
->GetSourceFiles();
1066 for(std::vector
<cmSourceFile
*>::const_iterator source
= sources
.begin();
1067 source
!= sources
.end(); ++source
)
1069 if(cmCustomCommand
* cc
= (*source
)->GetCustomCommand())
1071 const std::vector
<std::string
>& outputs
= cc
->GetOutputs();
1072 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1073 o
!= outputs
.end(); ++o
)
1075 depends
.push_back(*o
);
1081 //----------------------------------------------------------------------------
1082 void cmMakefileTargetGenerator
1083 ::WriteObjectDependRules(cmSourceFile
& source
,
1084 std::vector
<std::string
>& depends
)
1086 // Create the list of dependencies known at cmake time. These are
1087 // shared between the object file and dependency scanning rule.
1088 depends
.push_back(source
.GetFullPath());
1089 if(const char* objectDeps
= source
.GetProperty("OBJECT_DEPENDS"))
1091 std::vector
<std::string
> deps
;
1092 cmSystemTools::ExpandListArgument(objectDeps
, deps
);
1093 for(std::vector
<std::string
>::iterator i
= deps
.begin();
1094 i
!= deps
.end(); ++i
)
1096 depends
.push_back(i
->c_str());
1101 //----------------------------------------------------------------------------
1102 void cmMakefileTargetGenerator
1103 ::GenerateCustomRuleFile(const cmCustomCommand
& cc
)
1105 // Collect the commands.
1106 std::vector
<std::string
> commands
;
1107 std::string comment
= this->LocalGenerator
->ConstructComment(cc
);
1108 if(!comment
.empty())
1110 // add in a progress call if needed
1111 this->AppendProgress(commands
);
1112 if(!this->NoRuleMessages
)
1114 this->LocalGenerator
1115 ->AppendEcho(commands
, comment
.c_str(),
1116 cmLocalUnixMakefileGenerator3::EchoGenerate
);
1120 // Now append the actual user-specified commands.
1121 cmOStringStream content
;
1122 this->LocalGenerator
->AppendCustomCommand(commands
, cc
, this->Target
, false,
1123 cmLocalGenerator::HOME_OUTPUT
,
1126 // Collect the dependencies.
1127 std::vector
<std::string
> depends
;
1128 this->LocalGenerator
->AppendCustomDepend(depends
, cc
);
1130 // Check whether we need to bother checking for a symbolic output.
1131 bool need_symbolic
= this->GlobalGenerator
->GetNeedSymbolicMark();
1134 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1135 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1137 bool symbolic
= false;
1140 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1142 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1145 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1146 o
->c_str(), depends
, commands
,
1149 // If the rule has changed make sure the output is rebuilt.
1152 this->GlobalGenerator
->AddRuleHash(cc
.GetOutputs(), content
.str());
1156 // Write rules to drive building any outputs beyond the first.
1157 const char* in
= o
->c_str();
1158 for(++o
; o
!= outputs
.end(); ++o
)
1160 bool symbolic
= false;
1163 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1165 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1168 this->GenerateExtraOutput(o
->c_str(), in
, symbolic
);
1171 // Setup implicit dependency scanning.
1172 for(cmCustomCommand::ImplicitDependsList::const_iterator
1173 idi
= cc
.GetImplicitDepends().begin();
1174 idi
!= cc
.GetImplicitDepends().end(); ++idi
)
1176 std::string objFullPath
=
1177 this->Convert(outputs
[0].c_str(), cmLocalGenerator::FULL
);
1178 std::string srcFullPath
=
1179 this->Convert(idi
->second
.c_str(), cmLocalGenerator::FULL
);
1180 this->LocalGenerator
->
1181 AddImplicitDepends(*this->Target
, idi
->first
.c_str(),
1182 objFullPath
.c_str(),
1183 srcFullPath
.c_str());
1187 //----------------------------------------------------------------------------
1189 cmMakefileTargetGenerator
1190 ::GenerateExtraOutput(const char* out
, const char* in
, bool symbolic
)
1192 // Add a rule to build the primary output if the extra output needs
1194 std::vector
<std::string
> commands
;
1195 std::vector
<std::string
> depends
;
1196 std::string emptyCommand
= this->GlobalGenerator
->GetEmptyRuleHackCommand();
1197 if(!emptyCommand
.empty())
1199 commands
.push_back(emptyCommand
);
1201 depends
.push_back(in
);
1202 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1203 out
, depends
, commands
,
1206 // Register the extra output as paired with the first output so that
1207 // the check-build-system step will remove the primary output if any
1208 // extra outputs are missing. This forces the rule to regenerate
1210 this->AddMultipleOutputPair(out
, in
);
1213 //----------------------------------------------------------------------------
1215 cmMakefileTargetGenerator::AppendProgress(std::vector
<std::string
>& commands
)
1217 this->NumberOfProgressActions
++;
1218 if(this->NoRuleMessages
)
1222 std::string progressDir
= this->Makefile
->GetHomeOutputDirectory();
1223 progressDir
+= cmake::GetCMakeFilesDirectory();
1224 cmOStringStream progCmd
;
1225 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
1226 progCmd
<< this->LocalGenerator
->Convert(progressDir
.c_str(),
1227 cmLocalGenerator::FULL
,
1228 cmLocalGenerator::SHELL
);
1229 progCmd
<< " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions
<< ")";
1230 commands
.push_back(progCmd
.str());
1233 //----------------------------------------------------------------------------
1235 cmMakefileTargetGenerator
1236 ::WriteObjectsVariable(std::string
& variableName
,
1237 std::string
& variableNameExternal
)
1239 // Write a make variable assignment that lists all objects for the
1242 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1244 *this->BuildFileStream
1245 << "# Object files for target " << this->Target
->GetName() << "\n"
1246 << variableName
.c_str() << " =";
1248 const char* objName
=
1249 this->Makefile
->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1250 const char* lineContinue
=
1251 this->Makefile
->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1254 lineContinue
= "\\";
1256 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1257 i
!= this->Objects
.end(); ++i
)
1259 *this->BuildFileStream
<< " " << lineContinue
<< "\n";
1262 *this->BuildFileStream
<<
1263 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1264 cmLocalGenerator::MAKEFILE
);
1268 *this->BuildFileStream
<<
1269 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1272 *this->BuildFileStream
<< "\n";
1274 // Write a make variable assignment that lists all external objects
1276 variableNameExternal
=
1277 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1278 "_EXTERNAL_OBJECTS");
1279 *this->BuildFileStream
1281 << "# External object files for target "
1282 << this->Target
->GetName() << "\n"
1283 << variableNameExternal
.c_str() << " =";
1284 for(std::vector
<std::string
>::const_iterator i
=
1285 this->ExternalObjects
.begin();
1286 i
!= this->ExternalObjects
.end(); ++i
)
1288 object
= this->Convert(i
->c_str(),cmLocalGenerator::START_OUTPUT
);
1289 *this->BuildFileStream
1290 << " " << lineContinue
<< "\n"
1291 << this->Makefile
->GetSafeDefinition("CMAKE_OBJECT_NAME");
1294 *this->BuildFileStream
<<
1295 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1296 cmLocalGenerator::MAKEFILE
);
1300 *this->BuildFileStream
<<
1301 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1304 *this->BuildFileStream
<< "\n" << "\n";
1307 //----------------------------------------------------------------------------
1309 cmMakefileTargetGenerator
1310 ::WriteObjectsString(std::string
& buildObjs
)
1312 std::vector
<std::string
> objStrings
;
1313 this->WriteObjectsStrings(objStrings
);
1314 buildObjs
= objStrings
[0];
1317 //----------------------------------------------------------------------------
1318 class cmMakefileTargetGeneratorObjectStrings
1321 cmMakefileTargetGeneratorObjectStrings(std::vector
<std::string
>& strings
,
1323 cmLocalUnixMakefileGenerator3
* lg
,
1324 std::string::size_type limit
):
1325 Strings(strings
), Makefile(mf
), LocalGenerator(lg
), LengthLimit(limit
)
1329 void Feed(std::string
const& obj
)
1331 // Construct the name of the next object.
1333 this->LocalGenerator
->Convert(obj
.c_str(),
1334 cmLocalGenerator::START_OUTPUT
,
1335 cmLocalGenerator::SHELL
);
1337 // Roll over to next string if the limit will be exceeded.
1338 if(this->LengthLimit
!= std::string::npos
&&
1339 (this->CurrentString
.length() + 1 + this->NextObject
.length()
1340 > this->LengthLimit
))
1342 this->Strings
.push_back(this->CurrentString
);
1343 this->CurrentString
= "";
1347 // Separate from previous object.
1348 this->CurrentString
+= this->Space
;
1351 // Append this object.
1352 this->CurrentString
+= this->NextObject
;
1356 this->Strings
.push_back(this->CurrentString
);
1359 std::vector
<std::string
>& Strings
;
1360 cmMakefile
* Makefile
;
1361 cmLocalUnixMakefileGenerator3
* LocalGenerator
;
1362 std::string::size_type LengthLimit
;
1363 std::string CurrentString
;
1364 std::string NextObject
;
1368 //----------------------------------------------------------------------------
1370 cmMakefileTargetGenerator
1371 ::WriteObjectsStrings(std::vector
<std::string
>& objStrings
,
1372 std::string::size_type limit
)
1374 cmMakefileTargetGeneratorObjectStrings
1375 helper(objStrings
, this->Makefile
, this->LocalGenerator
, limit
);
1376 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1377 i
!= this->Objects
.end(); ++i
)
1381 for(std::vector
<std::string
>::const_iterator i
=
1382 this->ExternalObjects
.begin();
1383 i
!= this->ExternalObjects
.end(); ++i
)
1390 //----------------------------------------------------------------------------
1391 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output
,
1394 // Compute the name of the driver target.
1396 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
1397 std::string buildTargetRuleName
= dir
;
1398 buildTargetRuleName
+= relink
?"/preinstall":"/build";
1399 buildTargetRuleName
= this->Convert(buildTargetRuleName
.c_str(),
1400 cmLocalGenerator::HOME_OUTPUT
,
1401 cmLocalGenerator::UNCHANGED
);
1403 // Build the list of target outputs to drive.
1404 std::vector
<std::string
> depends
;
1407 depends
.push_back(main_output
);
1410 const char* comment
= 0;
1413 // Setup the comment for the preinstall driver.
1414 comment
= "Rule to relink during preinstall.";
1418 // Setup the comment for the main build driver.
1419 comment
= "Rule to build all files generated by this target.";
1421 // Make sure all custom command outputs in this target are built.
1422 if(this->CustomCommandDriver
== OnBuild
)
1424 this->DriveCustomCommands(depends
);
1427 // Make sure the extra files are built.
1428 for(std::set
<cmStdString
>::const_iterator i
= this->ExtraFiles
.begin();
1429 i
!= this->ExtraFiles
.end(); ++i
)
1431 depends
.push_back(*i
);
1435 // Write the driver rule.
1436 std::vector
<std::string
> no_commands
;
1437 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, comment
,
1438 buildTargetRuleName
.c_str(),
1439 depends
, no_commands
, true);
1442 //----------------------------------------------------------------------------
1443 std::string
cmMakefileTargetGenerator::GetFrameworkFlags()
1446 return std::string();
1448 std::set
<cmStdString
> emitted
;
1449 emitted
.insert("/System/Library/Frameworks");
1450 std::vector
<std::string
> includes
;
1451 this->LocalGenerator
->GetIncludeDirectories(includes
);
1452 std::vector
<std::string
>::iterator i
;
1453 // check all include directories for frameworks as this
1454 // will already have added a -F for the framework
1455 for(i
= includes
.begin(); i
!= includes
.end(); ++i
)
1457 if(this->Target
->NameResolvesToFramework(i
->c_str()))
1459 std::string frameworkDir
= *i
;
1460 frameworkDir
+= "/../";
1461 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1462 emitted
.insert(frameworkDir
);
1467 std::vector
<std::string
>& frameworks
= this->Target
->GetFrameworks();
1468 for(i
= frameworks
.begin();
1469 i
!= frameworks
.end(); ++i
)
1471 if(emitted
.insert(*i
).second
)
1474 flags
+= this->Convert(i
->c_str(),
1475 cmLocalGenerator::START_OUTPUT
,
1476 cmLocalGenerator::SHELL
, true);
1484 //----------------------------------------------------------------------------
1485 void cmMakefileTargetGenerator
1486 ::AppendTargetDepends(std::vector
<std::string
>& depends
)
1488 // Static libraries never depend on anything for linking.
1489 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
1494 // Loop over all library dependencies.
1495 const char* cfg
= this->LocalGenerator
->ConfigurationName
.c_str();
1496 if(cmComputeLinkInformation
* cli
= this->Target
->GetLinkInformation(cfg
))
1498 std::vector
<std::string
> const& libDeps
= cli
->GetDepends();
1499 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
1500 j
!= libDeps
.end(); ++j
)
1502 depends
.push_back(*j
);
1507 //----------------------------------------------------------------------------
1508 void cmMakefileTargetGenerator
1509 ::CloseFileStreams()
1511 delete this->BuildFileStream
;
1512 delete this->InfoFileStream
;
1513 delete this->FlagFileStream
;
1516 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar
,
1517 const char* linkLang
,
1518 std::string
& linkFlags
)
1520 // check for language flags that are not allowed at link time, and
1521 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1522 // which fails, there may be more]
1524 std::string removeFlags
= "CMAKE_";
1525 removeFlags
+= linkLang
;
1526 removeFlags
+= flagVar
;
1527 std::string removeflags
=
1528 this->Makefile
->GetSafeDefinition(removeFlags
.c_str());
1529 std::vector
<std::string
> removeList
;
1530 cmSystemTools::ExpandListArgument(removeflags
, removeList
);
1531 for(std::vector
<std::string
>::iterator i
= removeList
.begin();
1532 i
!= removeList
.end(); ++i
)
1534 cmSystemTools::ReplaceString(linkFlags
, i
->c_str(), "");
1538 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total
,
1539 unsigned long ¤t
)
1541 cmGeneratedFileStream
*progressFileStream
=
1542 new cmGeneratedFileStream(this->ProgressFileNameFull
.c_str());
1543 if(!progressFileStream
)
1550 for (i
= 1; i
<= this->NumberOfProgressActions
; ++i
)
1553 << "CMAKE_PROGRESS_" << i
<< " = ";
1557 *progressFileStream
<< num
;
1558 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1561 else if (((i
+current
)*100)/total
> ((i
-1+current
)*100)/total
)
1563 num
= ((i
+current
)*100)/total
;
1564 *progressFileStream
<< num
;
1565 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1568 *progressFileStream
<< "\n";
1570 *progressFileStream
<< "\n";
1571 current
+= this->NumberOfProgressActions
;
1572 delete progressFileStream
;
1575 //----------------------------------------------------------------------------
1577 cmMakefileTargetGenerator
1578 ::AddMultipleOutputPair(const char* depender
, const char* dependee
)
1580 MultipleOutputPairsType::value_type
p(depender
, dependee
);
1581 this->MultipleOutputPairs
.insert(p
);
1584 //----------------------------------------------------------------------------
1586 cmMakefileTargetGenerator
1587 ::CreateLinkScript(const char* name
,
1588 std::vector
<std::string
> const& link_commands
,
1589 std::vector
<std::string
>& makefile_commands
,
1590 std::vector
<std::string
>& makefile_depends
)
1592 // Create the link script file.
1593 std::string linkScriptName
= this->TargetBuildDirectoryFull
;
1594 linkScriptName
+= "/";
1595 linkScriptName
+= name
;
1596 cmGeneratedFileStream
linkScriptStream(linkScriptName
.c_str());
1597 linkScriptStream
.SetCopyIfDifferent(true);
1598 for(std::vector
<std::string
>::const_iterator cmd
= link_commands
.begin();
1599 cmd
!= link_commands
.end(); ++cmd
)
1601 // Do not write out empty commands or commands beginning in the
1603 if(!cmd
->empty() && (*cmd
)[0] != ':')
1605 linkScriptStream
<< *cmd
<< "\n";
1609 // Create the makefile command to invoke the link script.
1610 std::string link_command
= "$(CMAKE_COMMAND) -E cmake_link_script ";
1611 link_command
+= this->Convert(linkScriptName
.c_str(),
1612 cmLocalGenerator::START_OUTPUT
,
1613 cmLocalGenerator::SHELL
);
1614 link_command
+= " --verbose=$(VERBOSE)";
1615 makefile_commands
.push_back(link_command
);
1616 makefile_depends
.push_back(linkScriptName
);
1619 //----------------------------------------------------------------------------
1621 cmMakefileTargetGenerator
1622 ::CreateResponseFile(const char* name
, std::string
const& options
,
1623 std::vector
<std::string
>& makefile_depends
)
1625 // Create the response file.
1626 std::string responseFileNameFull
= this->TargetBuildDirectoryFull
;
1627 responseFileNameFull
+= "/";
1628 responseFileNameFull
+= name
;
1629 cmGeneratedFileStream
responseStream(responseFileNameFull
.c_str());
1630 responseStream
.SetCopyIfDifferent(true);
1631 responseStream
<< options
<< "\n";
1633 // Add a dependency so the target will rebuild when the set of
1635 makefile_depends
.push_back(responseFileNameFull
);
1637 // Construct the name to be used on the command line.
1638 std::string responseFileName
= this->TargetBuildDirectory
;
1639 responseFileName
+= "/";
1640 responseFileName
+= name
;
1641 return responseFileName
;
1644 //----------------------------------------------------------------------------
1646 cmMakefileTargetGenerator
1647 ::CreateObjectLists(bool useLinkScript
, bool useArchiveRules
,
1648 bool useResponseFile
, std::string
& buildObjs
,
1649 std::vector
<std::string
>& makefile_depends
)
1651 std::string variableName
;
1652 std::string variableNameExternal
;
1653 this->WriteObjectsVariable(variableName
, variableNameExternal
);
1656 // MSVC response files cannot exceed 128K.
1657 std::string::size_type
const responseFileLimit
= 131000;
1659 // Construct the individual object list strings.
1660 std::vector
<std::string
> object_strings
;
1661 this->WriteObjectsStrings(object_strings
, responseFileLimit
);
1663 // Write a response file for each string.
1664 const char* sep
= "";
1665 for(unsigned int i
= 0; i
< object_strings
.size(); ++i
)
1667 // Number the response files.
1669 sprintf(rsp
, "objects%u.rsp", i
+1);
1671 // Create this response file.
1672 std::string objects_rsp
=
1673 this->CreateResponseFile(rsp
, object_strings
[i
], makefile_depends
);
1675 // Separate from previous response file references.
1679 // Reference the response file.
1681 buildObjs
+= this->Convert(objects_rsp
.c_str(),
1682 cmLocalGenerator::NONE
,
1683 cmLocalGenerator::SHELL
);
1686 else if(useLinkScript
)
1688 if(!useArchiveRules
)
1690 this->WriteObjectsString(buildObjs
);
1696 buildObjs
+= variableName
;
1697 buildObjs
+= ") $(";
1698 buildObjs
+= variableNameExternal
;
1703 //----------------------------------------------------------------------------
1704 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1706 // Compute the module directory.
1707 if(!this->FortranModuleDirectoryComputed
)
1709 const char* target_mod_dir
=
1710 this->Target
->GetProperty("Fortran_MODULE_DIRECTORY");
1711 const char* moddir_flag
=
1712 this->Makefile
->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1713 if(target_mod_dir
&& moddir_flag
)
1715 // Compute the full path to the module directory.
1716 if(cmSystemTools::FileIsFullPath(target_mod_dir
))
1718 // Already a full path.
1719 this->FortranModuleDirectory
= target_mod_dir
;
1723 // Interpret relative to the current output directory.
1724 this->FortranModuleDirectory
=
1725 this->Makefile
->GetCurrentOutputDirectory();
1726 this->FortranModuleDirectory
+= "/";
1727 this->FortranModuleDirectory
+= target_mod_dir
;
1730 // Make sure the module output directory exists.
1731 cmSystemTools::MakeDirectory(this->FortranModuleDirectory
.c_str());
1733 this->FortranModuleDirectoryComputed
= true;
1736 // Return the computed directory.
1737 if(this->FortranModuleDirectory
.empty())
1743 return this->FortranModuleDirectory
.c_str();
1747 //----------------------------------------------------------------------------
1748 void cmMakefileTargetGenerator::AddFortranFlags(std::string
& flags
)
1750 // Add a module output directory flag if necessary.
1751 if(const char* mod_dir
= this->GetFortranModuleDirectory())
1753 const char* moddir_flag
=
1754 this->Makefile
->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1755 std::string modflag
= moddir_flag
;
1756 modflag
+= this->Convert(mod_dir
,
1757 cmLocalGenerator::START_OUTPUT
,
1758 cmLocalGenerator::SHELL
);
1759 this->LocalGenerator
->AppendFlags(flags
, modflag
.c_str());
1762 // If there is a separate module path flag then duplicate the
1763 // include path with it. This compiler does not search the include
1764 // path for modules.
1765 if(const char* modpath_flag
=
1766 this->Makefile
->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1768 std::vector
<std::string
> includes
;
1769 this->LocalGenerator
->GetIncludeDirectories(includes
);
1770 for(std::vector
<std::string
>::const_iterator idi
= includes
.begin();
1771 idi
!= includes
.end(); ++idi
)
1773 std::string flg
= modpath_flag
;
1774 flg
+= this->Convert(idi
->c_str(),
1775 cmLocalGenerator::NONE
,
1776 cmLocalGenerator::SHELL
);
1777 this->LocalGenerator
->AppendFlags(flags
, flg
.c_str());