1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileTargetGenerator.cxx,v $
6 Date: $Date: 2008-02-27 22:10:45 $
7 Version: $Revision: 1.93 $
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"
28 #include "cmMakefileExecutableTargetGenerator.h"
29 #include "cmMakefileLibraryTargetGenerator.h"
30 #include "cmMakefileUtilityTargetGenerator.h"
33 cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget
* target
)
35 this->BuildFileStream
= 0;
36 this->InfoFileStream
= 0;
37 this->FlagFileStream
= 0;
38 this->CustomCommandDriver
= OnBuild
;
39 this->FortranModuleDirectoryComputed
= false;
40 this->Target
= target
;
41 this->Makefile
= this->Target
->GetMakefile();
42 this->LocalGenerator
=
43 static_cast<cmLocalUnixMakefileGenerator3
*>(
44 this->Makefile
->GetLocalGenerator());
45 this->GlobalGenerator
=
46 static_cast<cmGlobalUnixMakefileGenerator3
*>(
47 this->LocalGenerator
->GetGlobalGenerator());
50 cmMakefileTargetGenerator
*
51 cmMakefileTargetGenerator::New(cmTarget
*tgt
)
53 cmMakefileTargetGenerator
*result
= 0;
55 switch (tgt
->GetType())
57 case cmTarget::EXECUTABLE
:
58 result
= new cmMakefileExecutableTargetGenerator(tgt
);
60 case cmTarget::STATIC_LIBRARY
:
61 case cmTarget::SHARED_LIBRARY
:
62 case cmTarget::MODULE_LIBRARY
:
63 result
= new cmMakefileLibraryTargetGenerator(tgt
);
65 case cmTarget::UTILITY
:
66 result
= new cmMakefileUtilityTargetGenerator(tgt
);
70 // break; /* unreachable */
75 //----------------------------------------------------------------------------
76 void cmMakefileTargetGenerator::CreateRuleFile()
78 // Create a directory for this target.
79 this->TargetBuildDirectory
=
80 this->LocalGenerator
->GetTargetDirectory(*this->Target
);
81 this->TargetBuildDirectoryFull
=
82 this->LocalGenerator
->ConvertToFullPath(this->TargetBuildDirectory
);
83 cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull
.c_str());
85 // Construct the rule file name.
86 this->BuildFileName
= this->TargetBuildDirectory
;
87 this->BuildFileName
+= "/build.make";
88 this->BuildFileNameFull
= this->TargetBuildDirectoryFull
;
89 this->BuildFileNameFull
+= "/build.make";
91 // Construct the rule file name.
92 this->ProgressFileName
= this->TargetBuildDirectory
;
93 this->ProgressFileName
+= "/progress.make";
94 this->ProgressFileNameFull
= this->TargetBuildDirectoryFull
;
95 this->ProgressFileNameFull
+= "/progress.make";
97 // reset the progress count
98 this->NumberOfProgressActions
= 0;
100 // Open the rule file. This should be copy-if-different because the
101 // rules may depend on this file itself.
102 this->BuildFileStream
=
103 new cmGeneratedFileStream(this->BuildFileNameFull
.c_str());
104 this->BuildFileStream
->SetCopyIfDifferent(true);
105 if(!this->BuildFileStream
)
109 this->LocalGenerator
->WriteDisclaimer(*this->BuildFileStream
);
110 this->LocalGenerator
->WriteSpecialTargetsTop(*this->BuildFileStream
);
113 //----------------------------------------------------------------------------
114 void cmMakefileTargetGenerator::WriteTargetBuildRules()
116 // write the custom commands for this target
117 // Look for files registered for cleaning in this directory.
118 if(const char* additional_clean_files
=
119 this->Makefile
->GetProperty
120 ("ADDITIONAL_MAKE_CLEAN_FILES"))
122 cmSystemTools::ExpandListArgument(additional_clean_files
,
126 // add custom commands to the clean rules?
127 const char* clean_no_custom
=
128 this->Makefile
->GetProperty("CLEAN_NO_CUSTOM");
129 bool clean
= cmSystemTools::IsOff(clean_no_custom
);
131 // First generate the object rule files. Save a list of all object
132 // files for this target.
133 const std::vector
<cmSourceFile
*>& sources
= this->Target
->GetSourceFiles();
134 for(std::vector
<cmSourceFile
*>::const_iterator source
= sources
.begin();
135 source
!= sources
.end(); ++source
)
137 cmTarget::SourceFileFlags tsFlags
=
138 this->Target
->GetTargetSourceFileFlags(*source
);
139 if(cmCustomCommand
* cc
= (*source
)->GetCustomCommand())
141 this->GenerateCustomRuleFile(*cc
);
144 const std::vector
<std::string
>& outputs
= cc
->GetOutputs();
145 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
146 o
!= outputs
.end(); ++o
)
148 this->CleanFiles
.push_back
149 (this->Convert(o
->c_str(),
150 cmLocalGenerator::START_OUTPUT
,
151 cmLocalGenerator::UNCHANGED
));
155 else if(tsFlags
.Type
!= cmTarget::SourceFileTypeNormal
)
157 this->WriteMacOSXContentRules(*(*source
), tsFlags
.MacFolder
);
159 else if(!(*source
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
161 if(!this->GlobalGenerator
->IgnoreFile
162 ((*source
)->GetExtension().c_str()))
164 // Generate this object file's rule file.
165 this->WriteObjectRuleFiles(*(*source
));
167 else if((*source
)->GetPropertyAsBool("EXTERNAL_OBJECT"))
169 // This is an external object file. Just add it.
170 this->ExternalObjects
.push_back((*source
)->GetFullPath());
174 // We only get here if a source file is not an external object
175 // and has an extension that is listed as an ignored file type
176 // for this language. No message or diagnosis should be
184 //----------------------------------------------------------------------------
185 void cmMakefileTargetGenerator::WriteCommonCodeRules()
187 // Include the dependencies for the target.
188 std::string dependFileNameFull
= this->TargetBuildDirectoryFull
;
189 dependFileNameFull
+= "/depend.make";
190 *this->BuildFileStream
191 << "# Include any dependencies generated for this target.\n"
192 << this->LocalGenerator
->IncludeDirective
<< " "
193 << this->Convert(dependFileNameFull
.c_str(),
194 cmLocalGenerator::HOME_OUTPUT
,
195 cmLocalGenerator::MAKEFILE
)
198 // Include the progress variables for the target.
199 *this->BuildFileStream
200 << "# Include the progress variables for this target.\n"
201 << this->LocalGenerator
->IncludeDirective
<< " "
202 << this->Convert(this->ProgressFileNameFull
.c_str(),
203 cmLocalGenerator::HOME_OUTPUT
,
204 cmLocalGenerator::MAKEFILE
)
207 // make sure the depend file exists
208 if (!cmSystemTools::FileExists(dependFileNameFull
.c_str()))
210 // Write an empty dependency file.
211 cmGeneratedFileStream
depFileStream(dependFileNameFull
.c_str());
213 << "# Empty dependencies file for " << this->Target
->GetName() << ".\n"
214 << "# This may be replaced when dependencies are built." << std::endl
;
217 // Open the flags file. This should be copy-if-different because the
218 // rules may depend on this file itself.
219 this->FlagFileNameFull
= this->TargetBuildDirectoryFull
;
220 this->FlagFileNameFull
+= "/flags.make";
221 this->FlagFileStream
=
222 new cmGeneratedFileStream(this->FlagFileNameFull
.c_str());
223 this->FlagFileStream
->SetCopyIfDifferent(true);
224 if(!this->FlagFileStream
)
228 this->LocalGenerator
->WriteDisclaimer(*this->FlagFileStream
);
230 // Include the flags for the target.
231 *this->BuildFileStream
232 << "# Include the compile flags for this target's objects.\n"
233 << this->LocalGenerator
->IncludeDirective
<< " "
234 << this->Convert(this->FlagFileNameFull
.c_str(),
235 cmLocalGenerator::HOME_OUTPUT
,
236 cmLocalGenerator::MAKEFILE
)
240 //----------------------------------------------------------------------------
241 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
243 // write language flags for target
244 std::set
<cmStdString
> languages
;
245 this->Target
->GetLanguages(languages
);
246 // put the compiler in the rules.make file so that if it changes
248 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
249 l
!= languages
.end(); ++l
)
251 cmStdString compiler
= "CMAKE_";
253 compiler
+= "_COMPILER";
254 *this->FlagFileStream
<< "# compile " << l
->c_str() << " with " <<
255 this->Makefile
->GetSafeDefinition(compiler
.c_str()) << "\n";
258 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
259 l
!= languages
.end(); ++l
)
261 const char *lang
= l
->c_str();
264 bool shared
= ((this->Target
->GetType() == cmTarget::SHARED_LIBRARY
) ||
265 (this->Target
->GetType() == cmTarget::MODULE_LIBRARY
));
267 // Add the export symbol definition for shared library objects.
268 if(const char* exportMacro
= this->Target
->GetExportMacro())
271 flags
+= exportMacro
;
274 // Add preprocessor definitions for this target and configuration.
275 this->LocalGenerator
->AppendDefines
276 (defines
, this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), lang
);
277 this->LocalGenerator
->AppendDefines
278 (defines
, this->Target
->GetProperty("COMPILE_DEFINITIONS"), lang
);
279 std::string defPropName
= "COMPILE_DEFINITIONS_";
281 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
);
282 this->LocalGenerator
->AppendDefines
283 (defines
, this->Makefile
->GetProperty(defPropName
.c_str()), lang
);
284 this->LocalGenerator
->AppendDefines
285 (defines
, this->Target
->GetProperty(defPropName
.c_str()), lang
);
287 // Add language-specific flags.
289 ->AddLanguageFlags(flags
, lang
,
290 this->LocalGenerator
->ConfigurationName
.c_str());
292 // Fortran-specific flags computed for this target.
295 this->AddFortranFlags(flags
);
298 // Add shared-library flags if needed.
299 this->LocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
301 // Add include directory flags.
302 this->LocalGenerator
->
303 AppendFlags(flags
, this->LocalGenerator
->GetIncludeFlags(lang
));
304 // Add include directory flags.
305 this->LocalGenerator
->
306 AppendFlags(flags
,this->GetFrameworkFlags().c_str());
308 *this->FlagFileStream
<< lang
<< "_FLAGS = " << flags
<< "\n\n";
309 *this->FlagFileStream
<< lang
<< "_DEFINES = " << defines
<< "\n\n";
312 // Add target-specific flags.
313 if(this->Target
->GetProperty("COMPILE_FLAGS"))
316 this->LocalGenerator
->AppendFlags
317 (flags
, this->Target
->GetProperty("COMPILE_FLAGS"));
318 *this->FlagFileStream
<< "# TARGET_FLAGS = " << flags
<< "\n\n";
322 //----------------------------------------------------------------------------
323 void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile
& source
,
326 // Skip OS X content when not building a Framework or Bundle.
327 if(this->MacContentDirectory
.empty())
332 // Construct the full path to the content subdirectory.
333 std::string macdir
= this->MacContentDirectory
;
335 cmSystemTools::MakeDirectory(macdir
.c_str());
337 // Get the input file location.
338 std::string input
= source
.GetFullPath();
340 // Get the output file location.
341 std::string output
= macdir
;
343 output
+= cmSystemTools::GetFilenameName(input
);
344 this->CleanFiles
.push_back(this->Convert(output
.c_str(),
345 cmLocalGenerator::START_OUTPUT
));
346 output
= this->Convert(output
.c_str(), cmLocalGenerator::HOME_OUTPUT
);
348 // Create a rule to copy the content into the bundle.
349 std::vector
<std::string
> depends
;
350 std::vector
<std::string
> commands
;
351 depends
.push_back(input
);
352 std::string copyEcho
= "Copying OS X content ";
354 this->LocalGenerator
->AppendEcho(commands
, copyEcho
.c_str(),
355 cmLocalUnixMakefileGenerator3::EchoBuild
);
356 std::string copyCommand
= "$(CMAKE_COMMAND) -E copy ";
357 copyCommand
+= this->Convert(input
.c_str(),
358 cmLocalGenerator::NONE
,
359 cmLocalGenerator::SHELL
);
361 copyCommand
+= this->Convert(output
.c_str(),
362 cmLocalGenerator::NONE
,
363 cmLocalGenerator::SHELL
);
364 commands
.push_back(copyCommand
);
365 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
367 depends
, commands
, false);
368 this->ExtraFiles
.insert(output
);
371 //----------------------------------------------------------------------------
372 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile
& source
)
374 // Identify the language of the source file.
375 const char* lang
= this->LocalGenerator
->GetSourceFileLanguage(source
);
378 // don't know anything about this file so skip it
382 // Get the full path name of the object file.
383 bool hasSourceExtension
;
384 std::string objNoTargetDir
;
386 this->LocalGenerator
->GetObjectFileName(*this->Target
, source
,
388 &hasSourceExtension
);
390 // Avoid generating duplicate rules.
391 if(this->ObjectFiles
.find(obj
) == this->ObjectFiles
.end())
393 this->ObjectFiles
.insert(obj
);
398 err
<< "Warning: Source file \""
399 << source
.GetFullPath()
400 << "\" is listed multiple times for target \""
401 << this->Target
->GetName()
403 cmSystemTools::Message(err
.str().c_str(), "Warning");
407 // Create the directory containing the object file. This may be a
408 // subdirectory under the target's directory.
409 std::string dir
= cmSystemTools::GetFilenamePath(obj
.c_str());
410 cmSystemTools::MakeDirectory
411 (this->LocalGenerator
->ConvertToFullPath(dir
).c_str());
413 // Save this in the target's list of object files.
414 this->Objects
.push_back(obj
);
415 this->CleanFiles
.push_back(obj
);
418 //std::string relativeObj
419 //= this->LocalGenerator->GetHomeRelativeOutputPath();
420 //relativeObj += obj;
422 // we compute some depends when writing the depend.make that we will also
423 // use in the build.make, same with depMakeFile
424 std::vector
<std::string
> depends
;
425 std::string depMakeFile
;
427 // generate the build rule file
428 this->WriteObjectBuildFile(obj
, lang
, source
, depends
);
430 // The object file should be checked for dependency integrity.
431 std::string objFullPath
= this->Makefile
->GetCurrentOutputDirectory();
435 this->Convert(objFullPath
.c_str(), cmLocalGenerator::FULL
);
436 std::string srcFullPath
=
437 this->Convert(source
.GetFullPath().c_str(), cmLocalGenerator::FULL
);
438 this->LocalGenerator
->
439 AddImplicitDepends(*this->Target
, lang
,
441 srcFullPath
.c_str());
443 // add this to the list of objects for this local generator
444 if(cmSystemTools::FileIsFullPath(objNoTargetDir
.c_str()))
446 objNoTargetDir
= cmSystemTools::GetFilenameName(objNoTargetDir
);
448 cmLocalUnixMakefileGenerator3::LocalObjectInfo
& info
=
449 this->LocalGenerator
->LocalObjectFiles
[objNoTargetDir
];
450 info
.HasSourceExtension
= hasSourceExtension
;
452 cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target
, lang
)
456 //----------------------------------------------------------------------------
458 cmMakefileTargetGenerator
459 ::WriteObjectBuildFile(std::string
&obj
,
461 cmSourceFile
& source
,
462 std::vector
<std::string
>& depends
)
464 this->LocalGenerator
->AppendRuleDepend(depends
,
465 this->FlagFileNameFull
.c_str());
467 // generate the depend scanning rule
468 this->WriteObjectDependRules(source
, depends
);
470 std::string relativeObj
= this->LocalGenerator
->GetHomeRelativeOutputPath();
472 // Write the build rule.
474 // Build the set of compiler flags.
477 // Add language-specific flags.
478 std::string langFlags
= "$(";
480 langFlags
+= "_FLAGS)";
481 this->LocalGenerator
->AppendFlags(flags
, langFlags
.c_str());
483 // Add target-specific flags.
484 if(this->Target
->GetProperty("COMPILE_FLAGS"))
486 this->LocalGenerator
->AppendFlags
487 (flags
, this->Target
->GetProperty("COMPILE_FLAGS"));
490 // Add flags from source file properties.
491 if (source
.GetProperty("COMPILE_FLAGS"))
493 this->LocalGenerator
->AppendFlags
494 (flags
, source
.GetProperty("COMPILE_FLAGS"));
495 *this->FlagFileStream
<< "# Custom flags: "
496 << relativeObj
<< "_FLAGS = "
497 << source
.GetProperty("COMPILE_FLAGS")
502 // Add language-specific defines.
503 std::string defines
= "$(";
505 defines
+= "_DEFINES)";
507 // Add source-sepcific preprocessor definitions.
508 if(const char* compile_defs
= source
.GetProperty("COMPILE_DEFINITIONS"))
510 this->LocalGenerator
->AppendDefines(defines
, compile_defs
, lang
);
511 *this->FlagFileStream
<< "# Custom defines: "
512 << relativeObj
<< "_DEFINES = "
513 << compile_defs
<< "\n"
516 std::string configUpper
=
517 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
);
518 std::string defPropName
= "COMPILE_DEFINITIONS_";
519 defPropName
+= configUpper
;
520 if(const char* config_compile_defs
=
521 source
.GetProperty(defPropName
.c_str()))
523 this->LocalGenerator
->AppendDefines(defines
, config_compile_defs
, lang
);
524 *this->FlagFileStream
525 << "# Custom defines: "
526 << relativeObj
<< "_DEFINES_" << configUpper
527 << " = " << config_compile_defs
<< "\n"
531 // Get the output paths for source and object files.
532 std::string sourceFile
= source
.GetFullPath();
533 if(this->LocalGenerator
->UseRelativePaths
)
535 sourceFile
= this->Convert(sourceFile
.c_str(),
536 cmLocalGenerator::HOME_OUTPUT
);
538 sourceFile
= this->Convert(sourceFile
.c_str(),
539 cmLocalGenerator::NONE
,
540 cmLocalGenerator::SHELL
);
541 std::string objectFile
= this->Convert(obj
.c_str(),
542 cmLocalGenerator::START_OUTPUT
,
543 cmLocalGenerator::SHELL
);
545 // Construct the build message.
546 std::vector
<std::string
> no_commands
;
547 std::vector
<std::string
> commands
;
549 // add in a progress call if needed
550 std::string progressDir
= this->Makefile
->GetHomeOutputDirectory();
551 progressDir
+= cmake::GetCMakeFilesDirectory();
552 cmOStringStream progCmd
;
553 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
554 progCmd
<< this->LocalGenerator
->Convert(progressDir
.c_str(),
555 cmLocalGenerator::FULL
,
556 cmLocalGenerator::SHELL
);
557 this->NumberOfProgressActions
++;
558 progCmd
<< " $(CMAKE_PROGRESS_"
559 << this->NumberOfProgressActions
561 commands
.push_back(progCmd
.str());
563 std::string buildEcho
= "Building ";
565 buildEcho
+= " object ";
566 buildEcho
+= relativeObj
;
567 this->LocalGenerator
->AppendEcho(commands
, buildEcho
.c_str(),
568 cmLocalUnixMakefileGenerator3::EchoBuild
);
570 // Construct the compile rules.
571 std::string compileRuleVar
= "CMAKE_";
572 compileRuleVar
+= lang
;
573 compileRuleVar
+= "_COMPILE_OBJECT";
574 std::string compileRule
=
575 this->Makefile
->GetRequiredDefinition(compileRuleVar
.c_str());
576 std::vector
<std::string
> compileCommands
;
577 cmSystemTools::ExpandListArgument(compileRule
, compileCommands
);
579 // Change the command working directory to the local build tree.
580 this->LocalGenerator
->CreateCDCommand
582 this->Makefile
->GetStartOutputDirectory(),
583 this->Makefile
->GetHomeOutputDirectory());
584 commands
.insert(commands
.end(),
585 compileCommands
.begin(), compileCommands
.end());
587 std::string targetOutPathPDB
;
589 std::string targetFullPathPDB
;
590 const char* configName
= this->LocalGenerator
->ConfigurationName
.c_str();
591 if(this->Target
->GetType() == cmTarget::EXECUTABLE
||
592 this->Target
->GetType() == cmTarget::STATIC_LIBRARY
||
593 this->Target
->GetType() == cmTarget::SHARED_LIBRARY
||
594 this->Target
->GetType() == cmTarget::MODULE_LIBRARY
)
596 targetFullPathPDB
= this->Target
->GetDirectory();
597 targetFullPathPDB
+= "/";
598 targetFullPathPDB
+= this->Target
->GetPDBName(configName
);
601 this->Convert(targetFullPathPDB
.c_str(),cmLocalGenerator::FULL
,
602 cmLocalGenerator::SHELL
);
604 cmLocalGenerator::RuleVariables vars
;
605 vars
.Language
= lang
;
606 vars
.TargetPDB
= targetOutPathPDB
.c_str();
607 vars
.Source
= sourceFile
.c_str();
608 std::string shellObj
=
609 this->Convert(obj
.c_str(),
610 cmLocalGenerator::NONE
,
611 cmLocalGenerator::SHELL
).c_str();
612 vars
.Object
= shellObj
.c_str();
613 std::string objectDir
= cmSystemTools::GetFilenamePath(obj
);
614 vars
.ObjectDir
= objectDir
.c_str();
615 vars
.Flags
= flags
.c_str();
616 vars
.Defines
= defines
.c_str();
618 // Expand placeholders in the commands.
619 for(std::vector
<std::string
>::iterator i
= commands
.begin();
620 i
!= commands
.end(); ++i
)
622 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
627 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
629 depends
, commands
, false);
631 // Check for extra outputs created by the compilation.
632 if(const char* extra_outputs_str
=
633 source
.GetProperty("OBJECT_OUTPUTS"))
635 std::vector
<std::string
> extra_outputs
;
636 cmSystemTools::ExpandListArgument(extra_outputs_str
, extra_outputs
);
637 for(std::vector
<std::string
>::const_iterator eoi
= extra_outputs
.begin();
638 eoi
!= extra_outputs
.end(); ++eoi
)
640 // Register this as an extra output for the object file rule.
641 // This will cause the object file to be rebuilt if the extra
642 // output is missing.
643 this->GenerateExtraOutput(eoi
->c_str(), relativeObj
.c_str(), false);
645 // Register this as an extra file to clean.
646 this->CleanFiles
.push_back(eoi
->c_str());
650 bool lang_is_c_or_cxx
= ((strcmp(lang
, "C") == 0) ||
651 (strcmp(lang
, "CXX") == 0));
652 bool do_preprocess_rules
= lang_is_c_or_cxx
&&
653 this->LocalGenerator
->GetCreatePreprocessedSourceRules();
654 bool do_assembly_rules
= lang_is_c_or_cxx
&&
655 this->LocalGenerator
->GetCreateAssemblySourceRules();
656 if(do_preprocess_rules
|| do_assembly_rules
)
658 std::vector
<std::string
> force_depends
;
659 force_depends
.push_back("cmake_force");
660 std::string::size_type dot_pos
= relativeObj
.rfind(".");
661 std::string relativeObjBase
= relativeObj
.substr(0, dot_pos
);
662 dot_pos
= obj
.rfind(".");
663 std::string objBase
= obj
.substr(0, dot_pos
);
665 if(do_preprocess_rules
)
668 std::string relativeObjI
= relativeObjBase
+ ".i";
669 std::string objI
= objBase
+ ".i";
671 std::string preprocessEcho
= "Preprocessing ";
672 preprocessEcho
+= lang
;
673 preprocessEcho
+= " source to ";
674 preprocessEcho
+= objI
;
675 this->LocalGenerator
->AppendEcho(
676 commands
, preprocessEcho
.c_str(),
677 cmLocalUnixMakefileGenerator3::EchoBuild
680 std::string preprocessRuleVar
= "CMAKE_";
681 preprocessRuleVar
+= lang
;
682 preprocessRuleVar
+= "_CREATE_PREPROCESSED_SOURCE";
683 if(const char* preprocessRule
=
684 this->Makefile
->GetDefinition(preprocessRuleVar
.c_str()))
686 std::vector
<std::string
> preprocessCommands
;
687 cmSystemTools::ExpandListArgument(preprocessRule
, preprocessCommands
);
688 this->LocalGenerator
->CreateCDCommand
690 this->Makefile
->GetStartOutputDirectory(),
691 this->Makefile
->GetHomeOutputDirectory());
692 commands
.insert(commands
.end(),
693 preprocessCommands
.begin(),
694 preprocessCommands
.end());
696 std::string shellObjI
=
697 this->Convert(objI
.c_str(),
698 cmLocalGenerator::NONE
,
699 cmLocalGenerator::SHELL
).c_str();
700 vars
.PreprocessedSource
= shellObjI
.c_str();
702 // Expand placeholders in the commands.
703 for(std::vector
<std::string
>::iterator i
= commands
.begin();
704 i
!= commands
.end(); ++i
)
706 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
711 std::string cmd
= "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
712 cmd
+= preprocessRuleVar
;
713 commands
.push_back(cmd
);
716 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
717 relativeObjI
.c_str(),
718 force_depends
, commands
, false);
721 if(do_assembly_rules
)
724 std::string relativeObjS
= relativeObjBase
+ ".s";
725 std::string objS
= objBase
+ ".s";
727 std::string assemblyEcho
= "Compiling ";
728 assemblyEcho
+= lang
;
729 assemblyEcho
+= " source to assembly ";
730 assemblyEcho
+= objS
;
731 this->LocalGenerator
->AppendEcho(
732 commands
, assemblyEcho
.c_str(),
733 cmLocalUnixMakefileGenerator3::EchoBuild
736 std::string assemblyRuleVar
= "CMAKE_";
737 assemblyRuleVar
+= lang
;
738 assemblyRuleVar
+= "_CREATE_ASSEMBLY_SOURCE";
739 if(const char* assemblyRule
=
740 this->Makefile
->GetDefinition(assemblyRuleVar
.c_str()))
742 std::vector
<std::string
> assemblyCommands
;
743 cmSystemTools::ExpandListArgument(assemblyRule
, assemblyCommands
);
744 this->LocalGenerator
->CreateCDCommand
746 this->Makefile
->GetStartOutputDirectory(),
747 this->Makefile
->GetHomeOutputDirectory());
748 commands
.insert(commands
.end(),
749 assemblyCommands
.begin(),
750 assemblyCommands
.end());
752 std::string shellObjS
=
753 this->Convert(objS
.c_str(),
754 cmLocalGenerator::NONE
,
755 cmLocalGenerator::SHELL
).c_str();
756 vars
.AssemblySource
= shellObjS
.c_str();
758 // Expand placeholders in the commands.
759 for(std::vector
<std::string
>::iterator i
= commands
.begin();
760 i
!= commands
.end(); ++i
)
762 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
767 std::string cmd
= "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
768 cmd
+= assemblyRuleVar
;
769 commands
.push_back(cmd
);
772 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
773 relativeObjS
.c_str(),
774 force_depends
, commands
, false);
778 // If the language needs provides-requires mode, create the
779 // corresponding targets.
780 std::string objectRequires
= relativeObj
;
781 objectRequires
+= ".requires";
782 std::vector
<std::string
> p_depends
;
783 // always provide an empty requires target
784 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
785 objectRequires
.c_str(), p_depends
,
788 // write a build rule to recursively build what this obj provides
789 std::string objectProvides
= relativeObj
;
790 objectProvides
+= ".provides";
791 std::string temp
= relativeObj
;
792 temp
+= ".provides.build";
793 std::vector
<std::string
> r_commands
;
794 std::string tgtMakefileName
=
795 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
796 tgtMakefileName
+= "/build.make";
798 (this->LocalGenerator
->GetRecursiveMakeCall(tgtMakefileName
.c_str(),
802 p_depends
.push_back(objectRequires
);
803 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
804 objectProvides
.c_str(), p_depends
,
807 // write the provides.build rule dependency on the obj file
809 p_depends
.push_back(relativeObj
);
810 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
811 temp
.c_str(), p_depends
, no_commands
,
815 //----------------------------------------------------------------------------
816 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
818 std::vector
<std::string
> depends
;
819 std::vector
<std::string
> no_commands
;
821 // Construct the name of the dependency generation target.
822 std::string depTarget
=
823 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
824 depTarget
+= "/requires";
826 // This target drives dependency generation for all object files.
827 std::string relPath
= this->LocalGenerator
->GetHomeRelativeOutputPath();
828 std::string objTarget
;
829 for(std::vector
<std::string
>::const_iterator obj
= this->Objects
.begin();
830 obj
!= this->Objects
.end(); ++obj
)
834 objTarget
+= ".requires";
835 depends
.push_back(objTarget
);
839 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
841 depends
, no_commands
, true);
844 //----------------------------------------------------------------------------
845 void cmMakefileTargetGenerator::WriteTargetCleanRules()
847 std::vector
<std::string
> depends
;
848 std::vector
<std::string
> commands
;
850 // Construct the clean target name.
851 std::string cleanTarget
=
852 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
853 cleanTarget
+= "/clean";
855 // Construct the clean command.
856 this->LocalGenerator
->AppendCleanCommand(commands
, this->CleanFiles
,
858 this->LocalGenerator
->CreateCDCommand
860 this->Makefile
->GetStartOutputDirectory(),
861 this->Makefile
->GetHomeOutputDirectory());
864 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
866 depends
, commands
, true);
870 //----------------------------------------------------------------------------
871 void cmMakefileTargetGenerator::WriteTargetDependRules()
873 // must write the targets depend info file
874 std::string dir
= this->LocalGenerator
->GetTargetDirectory(*this->Target
);
875 this->InfoFileNameFull
= dir
;
876 this->InfoFileNameFull
+= "/DependInfo.cmake";
877 this->InfoFileNameFull
=
878 this->LocalGenerator
->ConvertToFullPath(this->InfoFileNameFull
);
879 this->InfoFileStream
=
880 new cmGeneratedFileStream(this->InfoFileNameFull
.c_str());
881 this->InfoFileStream
->SetCopyIfDifferent(true);
882 if(!*this->InfoFileStream
)
886 this->LocalGenerator
->
887 WriteDependLanguageInfo(*this->InfoFileStream
,*this->Target
);
889 // Store multiple output pairs in the depend info file.
890 if(!this->MultipleOutputPairs
.empty())
892 *this->InfoFileStream
894 << "# Pairs of files generated by the same build rule.\n"
895 << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
896 for(MultipleOutputPairsType::const_iterator pi
=
897 this->MultipleOutputPairs
.begin();
898 pi
!= this->MultipleOutputPairs
.end(); ++pi
)
900 *this->InfoFileStream
<< " \"" << pi
->first
<< "\" \""
901 << pi
->second
<< "\"\n";
903 *this->InfoFileStream
<< " )\n\n";
906 // Store list of targets linked directly or transitively.
908 *this->InfoFileStream
910 << "# Targets to which this target links.\n"
911 << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
912 cmGlobalGenerator
* gg
= this->GlobalGenerator
;
913 std::set
<cmTarget
const*> emitted
;
914 cmTarget::LinkLibraryVectorType
const& libs
=
915 this->Target
->GetLinkLibraries();
916 for(cmTarget::LinkLibraryVectorType::const_iterator j
= libs
.begin();
917 j
!= libs
.end(); ++j
)
919 if(cmTarget
const* linkee
= gg
->FindTarget(0, j
->first
.c_str()))
921 if(emitted
.insert(linkee
).second
)
923 cmMakefile
* mf
= linkee
->GetMakefile();
924 cmLocalGenerator
* lg
= mf
->GetLocalGenerator();
925 std::string di
= mf
->GetStartOutputDirectory();
927 di
+= lg
->GetTargetDirectory(*linkee
);
928 di
+= "/DependInfo.cmake";
929 *this->InfoFileStream
<< " \"" << di
<< "\"\n";
933 *this->InfoFileStream
937 // Check for a target-specific module output directory.
938 if(const char* mdir
= this->GetFortranModuleDirectory())
940 *this->InfoFileStream
942 << "# Fortran module output directory.\n"
943 << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir
<< "\")\n";
946 // and now write the rule to use it
947 std::vector
<std::string
> depends
;
948 std::vector
<std::string
> commands
;
950 // Construct the name of the dependency generation target.
951 std::string depTarget
=
952 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
953 depTarget
+= "/depend";
955 // Add a command to call CMake to scan dependencies. CMake will
956 // touch the corresponding depends file after scanning dependencies.
957 cmOStringStream depCmd
;
958 // TODO: Account for source file properties and directory-level
959 // definitions when scanning for dependencies.
960 #if !defined(_WIN32) || defined(__CYGWIN__)
961 // This platform supports symlinks, so cmSystemTools will translate
962 // paths. Make sure PWD is set to the original name of the home
963 // output directory to help cmSystemTools to create the same
964 // translation table for the dependency scanning process.
966 << (this->LocalGenerator
->Convert(
967 this->Makefile
->GetHomeOutputDirectory(),
968 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
))
971 // Generate a call this signature:
973 // cmake -E cmake_depends <generator>
974 // <home-src-dir> <start-src-dir>
975 // <home-out-dir> <start-out-dir>
976 // <dep-info> --color=$(COLOR)
978 // This gives the dependency scanner enough information to recreate
979 // the state of our local generator sufficiently for its needs.
980 depCmd
<< "$(CMAKE_COMMAND) -E cmake_depends \""
981 << this->GlobalGenerator
->GetName() << "\" "
982 << this->Convert(this->Makefile
->GetHomeDirectory(),
983 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
985 << this->Convert(this->Makefile
->GetStartDirectory(),
986 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
988 << this->Convert(this->Makefile
->GetHomeOutputDirectory(),
989 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
991 << this->Convert(this->Makefile
->GetStartOutputDirectory(),
992 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
994 << this->Convert(this->InfoFileNameFull
.c_str(),
995 cmLocalGenerator::FULL
, cmLocalGenerator::SHELL
)
996 << " --color=$(COLOR)";
997 commands
.push_back(depCmd
.str());
999 // Make sure all custom command outputs in this target are built.
1000 if(this->CustomCommandDriver
== OnDepends
)
1002 this->DriveCustomCommands(depends
);
1006 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1008 depends
, commands
, true);
1011 //----------------------------------------------------------------------------
1013 cmMakefileTargetGenerator
1014 ::DriveCustomCommands(std::vector
<std::string
>& depends
)
1016 // Depend on all custom command outputs.
1017 const std::vector
<cmSourceFile
*>& sources
=
1018 this->Target
->GetSourceFiles();
1019 for(std::vector
<cmSourceFile
*>::const_iterator source
= sources
.begin();
1020 source
!= sources
.end(); ++source
)
1022 if(cmCustomCommand
* cc
= (*source
)->GetCustomCommand())
1024 const std::vector
<std::string
>& outputs
= cc
->GetOutputs();
1025 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1026 o
!= outputs
.end(); ++o
)
1028 depends
.push_back(*o
);
1034 //----------------------------------------------------------------------------
1035 void cmMakefileTargetGenerator
1036 ::WriteObjectDependRules(cmSourceFile
& source
,
1037 std::vector
<std::string
>& depends
)
1039 // Create the list of dependencies known at cmake time. These are
1040 // shared between the object file and dependency scanning rule.
1041 depends
.push_back(source
.GetFullPath());
1042 if(const char* objectDeps
= source
.GetProperty("OBJECT_DEPENDS"))
1044 std::vector
<std::string
> deps
;
1045 cmSystemTools::ExpandListArgument(objectDeps
, deps
);
1046 for(std::vector
<std::string
>::iterator i
= deps
.begin();
1047 i
!= deps
.end(); ++i
)
1049 depends
.push_back(i
->c_str());
1054 //----------------------------------------------------------------------------
1055 void cmMakefileTargetGenerator
1056 ::GenerateCustomRuleFile(const cmCustomCommand
& cc
)
1058 // Collect the commands.
1059 std::vector
<std::string
> commands
;
1060 std::string comment
= this->LocalGenerator
->ConstructComment(cc
);
1061 if(!comment
.empty())
1063 // add in a progress call if needed
1064 std::string progressDir
= this->Makefile
->GetHomeOutputDirectory();
1065 progressDir
+= cmake::GetCMakeFilesDirectory();
1066 cmOStringStream progCmd
;
1067 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_report ";
1068 progCmd
<< this->LocalGenerator
->Convert(progressDir
.c_str(),
1069 cmLocalGenerator::FULL
,
1070 cmLocalGenerator::SHELL
);
1071 this->NumberOfProgressActions
++;
1072 progCmd
<< " $(CMAKE_PROGRESS_"
1073 << this->NumberOfProgressActions
1075 commands
.push_back(progCmd
.str());
1076 this->LocalGenerator
1077 ->AppendEcho(commands
, comment
.c_str(),
1078 cmLocalUnixMakefileGenerator3::EchoGenerate
);
1080 this->LocalGenerator
->AppendCustomCommand(commands
, cc
);
1082 // Collect the dependencies.
1083 std::vector
<std::string
> depends
;
1084 this->LocalGenerator
->AppendCustomDepend(depends
, cc
);
1086 // Add a dependency on the rule file itself.
1087 this->LocalGenerator
->AppendRuleDepend(depends
,
1088 this->BuildFileNameFull
.c_str());
1090 // Check whether we need to bother checking for a symbolic output.
1091 bool need_symbolic
= this->GlobalGenerator
->GetNeedSymbolicMark();
1094 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1095 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1097 bool symbolic
= false;
1100 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1102 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1105 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1106 o
->c_str(), depends
, commands
,
1110 // Write rules to drive building any outputs beyond the first.
1111 const char* in
= o
->c_str();
1112 for(++o
; o
!= outputs
.end(); ++o
)
1114 bool symbolic
= false;
1117 if(cmSourceFile
* sf
= this->Makefile
->GetSource(o
->c_str()))
1119 symbolic
= sf
->GetPropertyAsBool("SYMBOLIC");
1122 this->GenerateExtraOutput(o
->c_str(), in
, symbolic
);
1125 // Setup implicit dependency scanning.
1126 for(cmCustomCommand::ImplicitDependsList::const_iterator
1127 idi
= cc
.GetImplicitDepends().begin();
1128 idi
!= cc
.GetImplicitDepends().end(); ++idi
)
1130 std::string objFullPath
=
1131 this->Convert(outputs
[0].c_str(), cmLocalGenerator::FULL
);
1132 std::string srcFullPath
=
1133 this->Convert(idi
->second
.c_str(), cmLocalGenerator::FULL
);
1134 this->LocalGenerator
->
1135 AddImplicitDepends(*this->Target
, idi
->first
.c_str(),
1136 objFullPath
.c_str(),
1137 srcFullPath
.c_str());
1141 //----------------------------------------------------------------------------
1143 cmMakefileTargetGenerator
1144 ::GenerateExtraOutput(const char* out
, const char* in
, bool symbolic
)
1146 // Add a rule to build the primary output if the extra output needs
1148 std::vector
<std::string
> commands
;
1149 std::vector
<std::string
> depends
;
1150 std::string emptyCommand
= this->GlobalGenerator
->GetEmptyRuleHackCommand();
1151 if(!emptyCommand
.empty())
1153 commands
.push_back(emptyCommand
);
1155 depends
.push_back(in
);
1156 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
1157 out
, depends
, commands
,
1160 // Register the extra output as paired with the first output so that
1161 // the check-build-system step will remove the primary output if any
1162 // extra outputs are missing. This forces the rule to regenerate
1164 this->AddMultipleOutputPair(out
, in
);
1167 //----------------------------------------------------------------------------
1169 cmMakefileTargetGenerator
1170 ::WriteObjectsVariable(std::string
& variableName
,
1171 std::string
& variableNameExternal
)
1173 // Write a make variable assignment that lists all objects for the
1176 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1178 *this->BuildFileStream
1179 << "# Object files for target " << this->Target
->GetName() << "\n"
1180 << variableName
.c_str() << " =";
1182 const char* objName
=
1183 this->Makefile
->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1184 const char* lineContinue
=
1185 this->Makefile
->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1188 lineContinue
= "\\";
1190 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1191 i
!= this->Objects
.end(); ++i
)
1193 *this->BuildFileStream
<< " " << lineContinue
<< "\n";
1196 *this->BuildFileStream
<<
1197 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1198 cmLocalGenerator::MAKEFILE
);
1202 *this->BuildFileStream
<<
1203 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1206 *this->BuildFileStream
<< "\n";
1208 // Write a make variable assignment that lists all external objects
1210 variableNameExternal
=
1211 this->LocalGenerator
->CreateMakeVariable(this->Target
->GetName(),
1212 "_EXTERNAL_OBJECTS");
1213 *this->BuildFileStream
1215 << "# External object files for target "
1216 << this->Target
->GetName() << "\n"
1217 << variableNameExternal
.c_str() << " =";
1218 for(std::vector
<std::string
>::const_iterator i
=
1219 this->ExternalObjects
.begin();
1220 i
!= this->ExternalObjects
.end(); ++i
)
1222 object
= this->Convert(i
->c_str(),cmLocalGenerator::START_OUTPUT
);
1223 *this->BuildFileStream
1224 << " " << lineContinue
<< "\n"
1225 << this->Makefile
->GetSafeDefinition("CMAKE_OBJECT_NAME");
1228 *this->BuildFileStream
<<
1229 this->Convert(i
->c_str(), cmLocalGenerator::START_OUTPUT
,
1230 cmLocalGenerator::MAKEFILE
);
1234 *this->BuildFileStream
<<
1235 this->LocalGenerator
->ConvertToQuotedOutputPath(i
->c_str());
1238 *this->BuildFileStream
<< "\n" << "\n";
1241 //----------------------------------------------------------------------------
1243 cmMakefileTargetGenerator
1244 ::WriteObjectsString(std::string
& buildObjs
)
1246 std::vector
<std::string
> objStrings
;
1247 this->WriteObjectsStrings(objStrings
);
1248 buildObjs
= objStrings
[0];
1251 //----------------------------------------------------------------------------
1252 class cmMakefileTargetGeneratorObjectStrings
1255 cmMakefileTargetGeneratorObjectStrings(std::vector
<std::string
>& strings
,
1257 cmLocalUnixMakefileGenerator3
* lg
,
1258 std::string::size_type limit
):
1259 Strings(strings
), Makefile(mf
), LocalGenerator(lg
), LengthLimit(limit
)
1263 void Feed(std::string
const& obj
)
1265 // Construct the name of the next object.
1267 this->LocalGenerator
->Convert(obj
.c_str(),
1268 cmLocalGenerator::START_OUTPUT
,
1269 cmLocalGenerator::SHELL
);
1271 // Roll over to next string if the limit will be exceeded.
1272 if(this->LengthLimit
!= std::string::npos
&&
1273 (this->CurrentString
.length() + 1 + this->NextObject
.length()
1274 > this->LengthLimit
))
1276 this->Strings
.push_back(this->CurrentString
);
1277 this->CurrentString
= "";
1281 // Separate from previous object.
1282 this->CurrentString
+= this->Space
;
1285 // Append this object.
1286 this->CurrentString
+= this->NextObject
;
1290 this->Strings
.push_back(this->CurrentString
);
1293 std::vector
<std::string
>& Strings
;
1294 cmMakefile
* Makefile
;
1295 cmLocalUnixMakefileGenerator3
* LocalGenerator
;
1296 std::string::size_type LengthLimit
;
1297 std::string CurrentString
;
1298 std::string NextObject
;
1302 //----------------------------------------------------------------------------
1304 cmMakefileTargetGenerator
1305 ::WriteObjectsStrings(std::vector
<std::string
>& objStrings
,
1306 std::string::size_type limit
)
1308 cmMakefileTargetGeneratorObjectStrings
1309 helper(objStrings
, this->Makefile
, this->LocalGenerator
, limit
);
1310 for(std::vector
<std::string
>::const_iterator i
= this->Objects
.begin();
1311 i
!= this->Objects
.end(); ++i
)
1315 for(std::vector
<std::string
>::const_iterator i
=
1316 this->ExternalObjects
.begin();
1317 i
!= this->ExternalObjects
.end(); ++i
)
1324 //----------------------------------------------------------------------------
1325 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output
,
1328 // Compute the name of the driver target.
1330 this->LocalGenerator
->GetRelativeTargetDirectory(*this->Target
);
1331 std::string buildTargetRuleName
= dir
;
1332 buildTargetRuleName
+= relink
?"/preinstall":"/build";
1333 buildTargetRuleName
= this->Convert(buildTargetRuleName
.c_str(),
1334 cmLocalGenerator::HOME_OUTPUT
,
1335 cmLocalGenerator::UNCHANGED
);
1337 // Build the list of target outputs to drive.
1338 std::vector
<std::string
> depends
;
1341 depends
.push_back(main_output
);
1344 const char* comment
= 0;
1347 // Setup the comment for the preinstall driver.
1348 comment
= "Rule to relink during preinstall.";
1352 // Setup the comment for the main build driver.
1353 comment
= "Rule to build all files generated by this target.";
1355 // Make sure all custom command outputs in this target are built.
1356 if(this->CustomCommandDriver
== OnBuild
)
1358 this->DriveCustomCommands(depends
);
1361 // Make sure the extra files are built.
1362 for(std::set
<cmStdString
>::const_iterator i
= this->ExtraFiles
.begin();
1363 i
!= this->ExtraFiles
.end(); ++i
)
1365 depends
.push_back(*i
);
1369 // Write the driver rule.
1370 std::vector
<std::string
> no_commands
;
1371 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, comment
,
1372 buildTargetRuleName
.c_str(),
1373 depends
, no_commands
, true);
1376 //----------------------------------------------------------------------------
1377 std::string
cmMakefileTargetGenerator::GetFrameworkFlags()
1380 return std::string();
1382 std::set
<cmStdString
> emitted
;
1383 emitted
.insert("/System/Library/Frameworks");
1384 std::vector
<std::string
> includes
;
1385 this->LocalGenerator
->GetIncludeDirectories(includes
);
1386 std::vector
<std::string
>::iterator i
;
1387 // check all include directories for frameworks as this
1388 // will already have added a -F for the framework
1389 for(i
= includes
.begin(); i
!= includes
.end(); ++i
)
1391 if(this->Target
->NameResolvesToFramework(i
->c_str()))
1393 std::string frameworkDir
= *i
;
1394 frameworkDir
+= "/../";
1395 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1396 emitted
.insert(frameworkDir
);
1401 std::vector
<std::string
>& frameworks
= this->Target
->GetFrameworks();
1402 for(i
= frameworks
.begin();
1403 i
!= frameworks
.end(); ++i
)
1405 if(emitted
.insert(*i
).second
)
1408 flags
+= this->LocalGenerator
->ConvertToOutputForExisting(i
->c_str());
1416 //----------------------------------------------------------------------------
1417 void cmMakefileTargetGenerator
1418 ::AppendTargetDepends(std::vector
<std::string
>& depends
)
1420 // Static libraries never depend on anything for linking.
1421 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
1425 // Compute which library configuration to link.
1426 cmTarget::LinkLibraryType linkType
= cmTarget::OPTIMIZED
;
1427 if(cmSystemTools::UpperCase(
1428 this->LocalGenerator
->ConfigurationName
.c_str()) == "DEBUG")
1430 linkType
= cmTarget::DEBUG
;
1432 // Keep track of dependencies already listed.
1433 std::set
<cmStdString
> emitted
;
1435 // A target should not depend on itself.
1436 emitted
.insert(this->Target
->GetName());
1438 // Loop over all library dependencies.
1439 const cmTarget::LinkLibraryVectorType
& tlibs
=
1440 this->Target
->GetLinkLibraries();
1441 for(cmTarget::LinkLibraryVectorType::const_iterator lib
= tlibs
.begin();
1442 lib
!= tlibs
.end(); ++lib
)
1444 // skip the library if it is not general and the link type
1445 // does not match the current target
1446 if(lib
->second
!= cmTarget::GENERAL
&&
1447 lib
->second
!= linkType
)
1452 // Don't emit the same library twice for this target.
1453 if(emitted
.insert(lib
->first
).second
)
1455 // Depend on other CMake targets.
1457 this->GlobalGenerator
->FindTarget(0, lib
->first
.c_str()))
1459 if(const char* location
=
1460 tgt
->GetLocation(this->LocalGenerator
->ConfigurationName
.c_str()))
1462 depends
.push_back(location
);
1465 // depend on full path libs as well
1466 else if(cmSystemTools::FileIsFullPath(lib
->first
.c_str()))
1468 depends
.push_back(lib
->first
.c_str());
1474 //----------------------------------------------------------------------------
1475 void cmMakefileTargetGenerator
1476 ::CloseFileStreams()
1478 delete this->BuildFileStream
;
1479 delete this->InfoFileStream
;
1480 delete this->FlagFileStream
;
1483 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar
,
1484 const char* linkLang
,
1485 std::string
& linkFlags
)
1487 // check for language flags that are not allowed at link time, and
1488 // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1489 // which fails, there may be more]
1491 std::string removeFlags
= "CMAKE_";
1492 removeFlags
+= linkLang
;
1493 removeFlags
+= flagVar
;
1494 std::string removeflags
=
1495 this->Makefile
->GetSafeDefinition(removeFlags
.c_str());
1496 std::vector
<std::string
> removeList
;
1497 cmSystemTools::ExpandListArgument(removeflags
, removeList
);
1498 for(std::vector
<std::string
>::iterator i
= removeList
.begin();
1499 i
!= removeList
.end(); ++i
)
1501 cmSystemTools::ReplaceString(linkFlags
, i
->c_str(), "");
1505 void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total
,
1506 unsigned long ¤t
)
1508 cmGeneratedFileStream
*progressFileStream
=
1509 new cmGeneratedFileStream(this->ProgressFileNameFull
.c_str());
1510 if(!progressFileStream
)
1517 for (i
= 1; i
<= this->NumberOfProgressActions
; ++i
)
1520 << "CMAKE_PROGRESS_" << i
<< " = ";
1524 *progressFileStream
<< num
;
1525 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1528 else if (((i
+current
)*100)/total
> ((i
-1+current
)*100)/total
)
1530 num
= ((i
+current
)*100)/total
;
1531 *progressFileStream
<< num
;
1532 this->LocalGenerator
->ProgressFiles
[this->Target
->GetName()]
1535 *progressFileStream
<< "\n";
1537 *progressFileStream
<< "\n";
1538 current
+= this->NumberOfProgressActions
;
1539 delete progressFileStream
;
1542 //----------------------------------------------------------------------------
1544 cmMakefileTargetGenerator
1545 ::AddMultipleOutputPair(const char* depender
, const char* dependee
)
1547 MultipleOutputPairsType::value_type
p(depender
, dependee
);
1548 this->MultipleOutputPairs
.insert(p
);
1551 //----------------------------------------------------------------------------
1553 cmMakefileTargetGenerator
1554 ::CreateLinkScript(const char* name
,
1555 std::vector
<std::string
> const& link_commands
,
1556 std::vector
<std::string
>& makefile_commands
,
1557 std::vector
<std::string
>& makefile_depends
)
1559 // Create the link script file.
1560 std::string linkScriptName
= this->TargetBuildDirectoryFull
;
1561 linkScriptName
+= "/";
1562 linkScriptName
+= name
;
1563 cmGeneratedFileStream
linkScriptStream(linkScriptName
.c_str());
1564 linkScriptStream
.SetCopyIfDifferent(true);
1565 for(std::vector
<std::string
>::const_iterator cmd
= link_commands
.begin();
1566 cmd
!= link_commands
.end(); ++cmd
)
1568 // Do not write out empty commands or commands beginning in the
1570 if(!cmd
->empty() && (*cmd
)[0] != ':')
1572 linkScriptStream
<< *cmd
<< "\n";
1576 // Create the makefile command to invoke the link script.
1577 std::string link_command
= "$(CMAKE_COMMAND) -E cmake_link_script ";
1578 link_command
+= this->Convert(linkScriptName
.c_str(),
1579 cmLocalGenerator::START_OUTPUT
,
1580 cmLocalGenerator::SHELL
);
1581 link_command
+= " --verbose=$(VERBOSE)";
1582 makefile_commands
.push_back(link_command
);
1583 makefile_depends
.push_back(linkScriptName
);
1586 //----------------------------------------------------------------------------
1588 cmMakefileTargetGenerator
1589 ::CreateResponseFile(const char* name
, std::string
const& options
,
1590 std::vector
<std::string
>& makefile_depends
)
1592 // Create the response file.
1593 std::string responseFileNameFull
= this->TargetBuildDirectoryFull
;
1594 responseFileNameFull
+= "/";
1595 responseFileNameFull
+= name
;
1596 cmGeneratedFileStream
responseStream(responseFileNameFull
.c_str());
1597 responseStream
<< options
<< "\n";
1599 // Add a dependency so the target will rebuild when the set of
1601 makefile_depends
.push_back(responseFileNameFull
);
1603 // Construct the name to be used on the command line.
1604 std::string responseFileName
= this->TargetBuildDirectory
;
1605 responseFileName
+= "/";
1606 responseFileName
+= name
;
1607 return responseFileName
;
1610 //----------------------------------------------------------------------------
1611 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1613 // Compute the module directory.
1614 if(!this->FortranModuleDirectoryComputed
)
1616 const char* target_mod_dir
=
1617 this->Target
->GetProperty("Fortran_MODULE_DIRECTORY");
1618 const char* moddir_flag
=
1619 this->Makefile
->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1620 if(target_mod_dir
&& moddir_flag
)
1622 // Compute the full path to the module directory.
1623 if(cmSystemTools::FileIsFullPath(target_mod_dir
))
1625 // Already a full path.
1626 this->FortranModuleDirectory
= target_mod_dir
;
1630 // Interpret relative to the current output directory.
1631 this->FortranModuleDirectory
=
1632 this->Makefile
->GetCurrentOutputDirectory();
1633 this->FortranModuleDirectory
+= "/";
1634 this->FortranModuleDirectory
+= target_mod_dir
;
1637 // Make sure the module output directory exists.
1638 cmSystemTools::MakeDirectory(this->FortranModuleDirectory
.c_str());
1640 this->FortranModuleDirectoryComputed
= true;
1643 // Return the computed directory.
1644 if(this->FortranModuleDirectory
.empty())
1650 return this->FortranModuleDirectory
.c_str();
1654 //----------------------------------------------------------------------------
1655 void cmMakefileTargetGenerator::AddFortranFlags(std::string
& flags
)
1657 // Add a module output directory flag if necessary.
1658 if(const char* mod_dir
= this->GetFortranModuleDirectory())
1660 const char* moddir_flag
=
1661 this->Makefile
->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1662 std::string modflag
= moddir_flag
;
1663 modflag
+= this->Convert(mod_dir
,
1664 cmLocalGenerator::START_OUTPUT
,
1665 cmLocalGenerator::SHELL
);
1666 this->LocalGenerator
->AppendFlags(flags
, modflag
.c_str());
1669 // If there is a separate module path flag then duplicate the
1670 // include path with it. This compiler does not search the include
1671 // path for modules.
1672 if(const char* modpath_flag
=
1673 this->Makefile
->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1675 std::vector
<std::string
> includes
;
1676 this->LocalGenerator
->GetIncludeDirectories(includes
);
1677 for(std::vector
<std::string
>::const_iterator idi
= includes
.begin();
1678 idi
!= includes
.end(); ++idi
)
1680 std::string flg
= modpath_flag
;
1681 flg
+= this->Convert(idi
->c_str(),
1682 cmLocalGenerator::NONE
,
1683 cmLocalGenerator::SHELL
);
1684 this->LocalGenerator
->AppendFlags(flags
, flg
.c_str());