1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalUnixMakefileGenerator3.cxx,v $
6 Date: $Date: 2009-09-22 18:40:23 $
7 Version: $Revision: 1.270 $
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 "cmLocalUnixMakefileGenerator3.h"
19 #include "cmDepends.h"
20 #include "cmGeneratedFileStream.h"
21 #include "cmGlobalUnixMakefileGenerator3.h"
22 #include "cmMakefile.h"
23 #include "cmMakefileTargetGenerator.h"
24 #include "cmSourceFile.h"
26 #include "cmVersion.h"
27 #include "cmFileTimeComparison.h"
29 // Include dependency scanners for supported languages. Only the
30 // C/C++ scanner is needed for bootstrapping CMake.
31 #include "cmDependsC.h"
32 #ifdef CMAKE_BUILD_WITH_CMAKE
33 # include "cmDependsFortran.h"
34 # include "cmDependsJava.h"
35 # include <cmsys/Terminal.h>
38 #include <cmsys/auto_ptr.hxx>
40 #include <memory> // auto_ptr
43 //----------------------------------------------------------------------------
44 // Helper function used below.
45 static std::string
cmSplitExtension(std::string
const& in
, std::string
& base
)
48 std::string::size_type dot_pos
= in
.rfind(".");
49 if(dot_pos
!= std::string::npos
)
51 // Remove the extension first in case &base == &in.
52 ext
= in
.substr(dot_pos
, std::string::npos
);
53 base
= in
.substr(0, dot_pos
);
62 //----------------------------------------------------------------------------
63 cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
65 this->SilentNoColon
= false;
66 this->WindowsShell
= false;
67 this->IncludeDirective
= "include";
68 this->MakefileVariableSize
= 0;
69 this->IgnoreLibPrefix
= false;
70 this->PassMakeflags
= false;
71 this->DefineWindowsNULL
= false;
73 this->ColorMakefile
= false;
74 this->SkipPreprocessedSourceRules
= false;
75 this->SkipAssemblySourceRules
= false;
76 this->NativeEchoCommand
= "@echo ";
77 this->NativeEchoWindows
= true;
78 this->MakeCommandEscapeTargetTwice
= false;
79 this->IsMakefileGenerator
= true;
80 this->BorlandMakeCurlyHack
= false;
83 //----------------------------------------------------------------------------
84 cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3()
88 //----------------------------------------------------------------------------
89 void cmLocalUnixMakefileGenerator3::Configure()
91 // Compute the path to use when referencing the current output
92 // directory from the top output directory.
93 this->HomeRelativeOutputPath
=
94 this->Convert(this->Makefile
->GetStartOutputDirectory(), HOME_OUTPUT
);
95 if(this->HomeRelativeOutputPath
== ".")
97 this->HomeRelativeOutputPath
= "";
99 if(!this->HomeRelativeOutputPath
.empty())
101 this->HomeRelativeOutputPath
+= "/";
103 this->cmLocalGenerator::Configure();
106 //----------------------------------------------------------------------------
107 void cmLocalUnixMakefileGenerator3::Generate()
109 // Store the configuration name that will be generated.
110 if(const char* config
= this->Makefile
->GetDefinition("CMAKE_BUILD_TYPE"))
112 // Use the build type given by the user.
113 this->ConfigurationName
= config
;
117 // No configuration type given.
118 this->ConfigurationName
= "";
121 // Record whether some options are enabled to avoid checking many
123 if(!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile())
125 this->ColorMakefile
= this->Makefile
->IsOn("CMAKE_COLOR_MAKEFILE");
127 this->SkipPreprocessedSourceRules
=
128 this->Makefile
->IsOn("CMAKE_SKIP_PREPROCESSED_SOURCE_RULES");
129 this->SkipAssemblySourceRules
=
130 this->Makefile
->IsOn("CMAKE_SKIP_ASSEMBLY_SOURCE_RULES");
132 // Generate the rule files for each target.
133 cmTargets
& targets
= this->Makefile
->GetTargets();
134 cmGlobalUnixMakefileGenerator3
* gg
=
135 static_cast<cmGlobalUnixMakefileGenerator3
*>(this->GlobalGenerator
);
136 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
138 cmsys::auto_ptr
<cmMakefileTargetGenerator
> tg(
139 cmMakefileTargetGenerator::New(&(t
->second
)));
142 tg
->WriteRuleFiles();
143 gg
->RecordTargetProgress(tg
.get());
147 // write the local Makefile
148 this->WriteLocalMakefile();
150 // Write the cmake file with information for this directory.
151 this->WriteDirectoryInformationFile();
154 //----------------------------------------------------------------------------
155 void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets
156 (std::vector
<std::string
>& targets
)
158 for (std::map
<cmStdString
, LocalObjectInfo
>::iterator lo
=
159 this->LocalObjectFiles
.begin();
160 lo
!= this->LocalObjectFiles
.end(); ++lo
)
162 targets
.push_back(lo
->first
);
164 std::string::size_type dot_pos
= lo
->first
.rfind(".");
165 std::string base
= lo
->first
.substr(0, dot_pos
);
166 if(lo
->second
.HasPreprocessRule
)
168 targets
.push_back(base
+ ".i");
171 if(lo
->second
.HasAssembleRule
)
173 targets
.push_back(base
+ ".s");
178 //----------------------------------------------------------------------------
179 void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
181 // generate the includes
182 std::string ruleFileName
= "Makefile";
184 // Open the rule file. This should be copy-if-different because the
185 // rules may depend on this file itself.
186 std::string ruleFileNameFull
= this->ConvertToFullPath(ruleFileName
);
187 cmGeneratedFileStream
ruleFileStream(ruleFileNameFull
.c_str());
192 // always write the top makefile
195 ruleFileStream
.SetCopyIfDifferent(true);
198 // write the all rules
199 this->WriteLocalAllRules(ruleFileStream
);
201 // only write local targets unless at the top Keep track of targets already
203 std::set
<cmStdString
> emittedTargets
;
206 // write our targets, and while doing it collect up the object
208 this->WriteLocalMakefileTargets(ruleFileStream
,emittedTargets
);
212 cmGlobalUnixMakefileGenerator3
*gg
=
213 static_cast<cmGlobalUnixMakefileGenerator3
*>(this->GlobalGenerator
);
214 gg
->WriteConvenienceRules(ruleFileStream
,emittedTargets
);
217 bool do_preprocess_rules
=
218 this->GetCreatePreprocessedSourceRules();
219 bool do_assembly_rules
=
220 this->GetCreateAssemblySourceRules();
222 // now write out the object rules
223 // for each object file name
224 for (std::map
<cmStdString
, LocalObjectInfo
>::iterator lo
=
225 this->LocalObjectFiles
.begin();
226 lo
!= this->LocalObjectFiles
.end(); ++lo
)
228 // Add a convenience rule for building the object file.
229 this->WriteObjectConvenienceRule(ruleFileStream
,
230 "target to build an object file",
231 lo
->first
.c_str(), lo
->second
);
233 // Check whether preprocessing and assembly rules make sense.
234 // They make sense only for C and C++ sources.
235 bool lang_is_c_or_cxx
= false;
236 for(std::vector
<LocalObjectEntry
>::const_iterator ei
=
237 lo
->second
.begin(); ei
!= lo
->second
.end(); ++ei
)
239 if(ei
->Language
== "C" || ei
->Language
== "CXX")
241 lang_is_c_or_cxx
= true;
245 // Add convenience rules for preprocessed and assembly files.
246 if(lang_is_c_or_cxx
&& (do_preprocess_rules
|| do_assembly_rules
))
248 std::string::size_type dot_pos
= lo
->first
.rfind(".");
249 std::string base
= lo
->first
.substr(0, dot_pos
);
250 if(do_preprocess_rules
)
252 this->WriteObjectConvenienceRule(
253 ruleFileStream
, "target to preprocess a source file",
254 (base
+ ".i").c_str(), lo
->second
);
255 lo
->second
.HasPreprocessRule
= true;
257 if(do_assembly_rules
)
259 this->WriteObjectConvenienceRule(
260 ruleFileStream
, "target to generate assembly for a file",
261 (base
+ ".s").c_str(), lo
->second
);
262 lo
->second
.HasAssembleRule
= true;
267 // add a help target as long as there isn;t a real target named help
268 if(emittedTargets
.insert("help").second
)
270 cmGlobalUnixMakefileGenerator3
*gg
=
271 static_cast<cmGlobalUnixMakefileGenerator3
*>(this->GlobalGenerator
);
272 gg
->WriteHelpRule(ruleFileStream
,this);
275 this->WriteSpecialTargetsBottom(ruleFileStream
);
278 //----------------------------------------------------------------------------
280 cmLocalUnixMakefileGenerator3
281 ::WriteObjectConvenienceRule(std::ostream
& ruleFileStream
,
282 const char* comment
, const char* output
,
283 LocalObjectInfo
const& info
)
285 // If the rule includes the source file extension then create a
286 // version that has the extension removed. The help should include
287 // only the version without source extension.
289 if(info
.HasSourceExtension
)
291 // Remove the last extension. This should be kept.
292 std::string outBase1
= output
;
293 std::string outExt1
= cmSplitExtension(outBase1
, outBase1
);
295 // Now remove the source extension and put back the last
297 std::string outNoExt
;
298 cmSplitExtension(outBase1
, outNoExt
);
301 // Add a rule to drive the rule below.
302 std::vector
<std::string
> depends
;
303 depends
.push_back(output
);
304 std::vector
<std::string
> no_commands
;
305 this->WriteMakeRule(ruleFileStream
, 0,
306 outNoExt
.c_str(), depends
, no_commands
, true, true);
310 // Recursively make the rule for each target using the object file.
311 std::vector
<std::string
> commands
;
312 for(std::vector
<LocalObjectEntry
>::const_iterator t
= info
.begin();
313 t
!= info
.end(); ++t
)
315 std::string tgtMakefileName
=
316 this->GetRelativeTargetDirectory(*(t
->Target
));
317 std::string targetName
= tgtMakefileName
;
318 tgtMakefileName
+= "/build.make";
320 targetName
+= output
;
322 this->GetRecursiveMakeCall(tgtMakefileName
.c_str(), targetName
.c_str())
325 this->CreateCDCommand(commands
,
326 this->Makefile
->GetHomeOutputDirectory(),
327 cmLocalGenerator::START_OUTPUT
);
329 // Write the rule to the makefile.
330 std::vector
<std::string
> no_depends
;
331 this->WriteMakeRule(ruleFileStream
, comment
,
332 output
, no_depends
, commands
, true, inHelp
);
335 //----------------------------------------------------------------------------
336 void cmLocalUnixMakefileGenerator3
337 ::WriteLocalMakefileTargets(std::ostream
& ruleFileStream
,
338 std::set
<cmStdString
> &emitted
)
340 std::vector
<std::string
> depends
;
341 std::vector
<std::string
> commands
;
343 // for each target we just provide a rule to cd up to the top and do a make
345 cmTargets
& targets
= this->Makefile
->GetTargets();
346 std::string localName
;
347 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
349 if((t
->second
.GetType() == cmTarget::EXECUTABLE
) ||
350 (t
->second
.GetType() == cmTarget::STATIC_LIBRARY
) ||
351 (t
->second
.GetType() == cmTarget::SHARED_LIBRARY
) ||
352 (t
->second
.GetType() == cmTarget::MODULE_LIBRARY
) ||
353 (t
->second
.GetType() == cmTarget::UTILITY
))
355 emitted
.insert(t
->second
.GetName());
357 // for subdirs add a rule to build this specific target by name.
358 localName
= this->GetRelativeTargetDirectory(t
->second
);
359 localName
+= "/rule";
363 // Build the target for this pass.
364 std::string makefile2
= cmake::GetCMakeFilesDirectoryPostSlash();
365 makefile2
+= "Makefile2";
366 commands
.push_back(this->GetRecursiveMakeCall
367 (makefile2
.c_str(),localName
.c_str()));
368 this->CreateCDCommand(commands
,
369 this->Makefile
->GetHomeOutputDirectory(),
370 cmLocalGenerator::START_OUTPUT
);
371 this->WriteMakeRule(ruleFileStream
, "Convenience name for target.",
372 localName
.c_str(), depends
, commands
, true);
374 // Add a target with the canonical name (no prefix, suffix or path).
375 if(localName
!= t
->second
.GetName())
378 depends
.push_back(localName
);
379 this->WriteMakeRule(ruleFileStream
, "Convenience name for target.",
380 t
->second
.GetName(), depends
, commands
, true);
383 // Add a fast rule to build the target
384 std::string makefileName
= this->GetRelativeTargetDirectory(t
->second
);
385 makefileName
+= "/build.make";
386 // make sure the makefile name is suitable for a makefile
387 std::string makeTargetName
=
388 this->GetRelativeTargetDirectory(t
->second
);
389 makeTargetName
+= "/build";
390 localName
= t
->second
.GetName();
391 localName
+= "/fast";
394 commands
.push_back(this->GetRecursiveMakeCall
395 (makefileName
.c_str(), makeTargetName
.c_str()));
396 this->CreateCDCommand(commands
,
397 this->Makefile
->GetHomeOutputDirectory(),
398 cmLocalGenerator::START_OUTPUT
);
399 this->WriteMakeRule(ruleFileStream
, "fast build rule for target.",
400 localName
.c_str(), depends
, commands
, true);
402 // Add a local name for the rule to relink the target before
404 if(t
->second
.NeedRelinkBeforeInstall(this->ConfigurationName
.c_str()))
406 makeTargetName
= this->GetRelativeTargetDirectory(t
->second
);
407 makeTargetName
+= "/preinstall";
408 localName
= t
->second
.GetName();
409 localName
+= "/preinstall";
412 commands
.push_back(this->GetRecursiveMakeCall
413 (makefile2
.c_str(), makeTargetName
.c_str()));
414 this->CreateCDCommand(commands
,
415 this->Makefile
->GetHomeOutputDirectory(),
416 cmLocalGenerator::START_OUTPUT
);
417 this->WriteMakeRule(ruleFileStream
,
418 "Manual pre-install relink rule for target.",
419 localName
.c_str(), depends
, commands
, true);
425 //----------------------------------------------------------------------------
426 void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
428 std::string infoFileName
= this->Makefile
->GetStartOutputDirectory();
429 infoFileName
+= cmake::GetCMakeFilesDirectory();
430 infoFileName
+= "/CMakeDirectoryInformation.cmake";
432 // Open the output file.
433 cmGeneratedFileStream
infoFileStream(infoFileName
.c_str());
439 infoFileStream
.SetCopyIfDifferent(true);
440 // Write the do not edit header.
441 this->WriteDisclaimer(infoFileStream
);
443 // Setup relative path conversion tops.
445 << "# Relative path conversion top directories.\n"
446 << "SET(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" << this->RelativePathTopSource
448 << "SET(CMAKE_RELATIVE_PATH_TOP_BINARY \"" << this->RelativePathTopBinary
452 // Tell the dependency scanner to use unix paths if necessary.
453 if(cmSystemTools::GetForceUnixPaths())
456 << "# Force unix paths in dependencies.\n"
457 << "SET(CMAKE_FORCE_UNIX_PATHS 1)\n"
461 // Store the include search path for this directory.
463 << "# The C and CXX include file search paths:\n";
465 << "SET(CMAKE_C_INCLUDE_PATH\n";
466 std::vector
<std::string
> includeDirs
;
467 this->GetIncludeDirectories(includeDirs
);
468 for(std::vector
<std::string
>::iterator i
= includeDirs
.begin();
469 i
!= includeDirs
.end(); ++i
)
472 << " \"" << this->Convert(i
->c_str(),HOME_OUTPUT
).c_str() << "\"\n";
477 << "SET(CMAKE_CXX_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH})\n";
479 << "SET(CMAKE_Fortran_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH})\n";
481 // Store the include regular expressions for this directory.
484 << "# The C and CXX include file regular expressions for "
485 << "this directory.\n";
487 << "SET(CMAKE_C_INCLUDE_REGEX_SCAN ";
488 this->WriteCMakeArgument(infoFileStream
,
489 this->Makefile
->GetIncludeRegularExpression());
493 << "SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN ";
494 this->WriteCMakeArgument(infoFileStream
,
495 this->Makefile
->GetComplainRegularExpression());
499 << "SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n";
501 << "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN "
502 "${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
505 //----------------------------------------------------------------------------
507 cmLocalUnixMakefileGenerator3
508 ::ConvertToFullPath(const std::string
& localPath
)
510 std::string dir
= this->Makefile
->GetStartOutputDirectory();
517 const std::string
&cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
519 return this->HomeRelativeOutputPath
;
523 //----------------------------------------------------------------------------
525 cmLocalUnixMakefileGenerator3
526 ::WriteMakeRule(std::ostream
& os
,
529 const std::vector
<std::string
>& depends
,
530 const std::vector
<std::string
>& commands
,
534 // Make sure there is a target.
535 if(!target
|| !*target
)
537 cmSystemTools::Error("No target for WriteMakeRule! called with comment: ",
544 // Write the comment describing the rule in the makefile.
548 std::string::size_type lpos
= 0;
549 std::string::size_type rpos
;
550 while((rpos
= replace
.find('\n', lpos
)) != std::string::npos
)
552 os
<< "# " << replace
.substr(lpos
, rpos
-lpos
) << "\n";
555 os
<< "# " << replace
.substr(lpos
) << "\n";
558 // Construct the left hand side of the rule.
560 std::string tgt
= this->Convert(replace
.c_str(),HOME_OUTPUT
,MAKEFILE
);
561 const char* space
= "";
564 // Add a space before the ":" to avoid drive letter confusion on
569 // Mark the rule as symbolic if requested.
573 this->Makefile
->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE"))
575 os
<< tgt
.c_str() << space
<< ": " << sym
<< "\n";
582 // No dependencies. The commands will always run.
583 os
<< tgt
.c_str() << space
<< ":\n";
587 // Split dependencies into multiple rule lines. This allows for
588 // very long dependency lists even on older make implementations.
589 for(std::vector
<std::string
>::const_iterator dep
= depends
.begin();
590 dep
!= depends
.end(); ++dep
)
593 replace
= this->Convert(replace
.c_str(),HOME_OUTPUT
,MAKEFILE
);
594 os
<< tgt
.c_str() << space
<< ": " << replace
.c_str() << "\n";
598 // Write the list of commands.
599 for(std::vector
<std::string
>::const_iterator i
= commands
.begin();
600 i
!= commands
.end(); ++i
)
603 os
<< "\t" << replace
.c_str() << "\n";
605 if(symbolic
&& !this->WatcomWMake
)
607 os
<< ".PHONY : " << tgt
.c_str() << "\n";
610 // Add the output to the local help if requested.
613 this->LocalHelp
.push_back(target
);
617 //----------------------------------------------------------------------------
619 cmLocalUnixMakefileGenerator3
620 ::WriteMakeVariables(std::ostream
& makefileStream
)
622 this->WriteDivider(makefileStream
);
624 << "# Set environment variables for the build.\n"
626 if(this->DefineWindowsNULL
)
629 << "!IF \"$(OS)\" == \"Windows_NT\"\n"
635 if(this->WindowsShell
)
638 << "SHELL = cmd.exe\n"
645 << "# The shell in which to execute make rules.\n"
646 << "SHELL = /bin/sh\n"
651 std::string cmakecommand
=
652 this->Makefile
->GetRequiredDefinition("CMAKE_COMMAND");
654 << "# The CMake executable.\n"
655 << "CMAKE_COMMAND = "
656 << this->Convert(cmakecommand
.c_str(), FULL
, SHELL
).c_str()
660 << "# The command to remove a file.\n"
662 << this->Convert(cmakecommand
.c_str(),FULL
,SHELL
).c_str()
666 if(const char* edit_cmd
=
667 this->Makefile
->GetDefinition("CMAKE_EDIT_COMMAND"))
670 << "# The program to use to edit the cache.\n"
671 << "CMAKE_EDIT_COMMAND = "
672 << this->Convert(edit_cmd
,FULL
,SHELL
) << "\n"
677 << "# The top-level source directory on which CMake was run.\n"
678 << "CMAKE_SOURCE_DIR = "
679 << this->Convert(this->Makefile
->GetHomeDirectory(), FULL
, SHELL
)
683 << "# The top-level build directory on which CMake was run.\n"
684 << "CMAKE_BINARY_DIR = "
685 << this->Convert(this->Makefile
->GetHomeOutputDirectory(), FULL
, SHELL
)
690 //----------------------------------------------------------------------------
692 cmLocalUnixMakefileGenerator3
693 ::WriteSpecialTargetsTop(std::ostream
& makefileStream
)
695 this->WriteDivider(makefileStream
);
697 << "# Special targets provided by cmake.\n"
700 std::vector
<std::string
> no_commands
;
701 std::vector
<std::string
> no_depends
;
703 // Special target to cleanup operation of make tool.
704 // This should be the first target except for the default_target in
705 // the interface Makefile.
707 makefileStream
, "Disable implicit rules so canoncical targets will work.",
708 ".SUFFIXES", no_depends
, no_commands
, false);
710 if(!this->NMake
&& !this->WatcomWMake
&& !this->BorlandMakeCurlyHack
)
712 // turn off RCS and SCCS automatic stuff from gmake
714 << "# Remove some rules from gmake that .SUFFIXES does not remove.\n"
717 // Add a fake suffix to keep HP happy. Must be max 32 chars for SGI make.
718 std::vector
<std::string
> depends
;
719 depends
.push_back(".hpux_make_needs_suffix_list");
720 this->WriteMakeRule(makefileStream
, 0,
721 ".SUFFIXES", depends
, no_commands
, false);
723 cmGlobalUnixMakefileGenerator3
* gg
=
724 static_cast<cmGlobalUnixMakefileGenerator3
*>(this->GlobalGenerator
);
725 // Write special target to silence make output. This must be after
726 // the default target in case VERBOSE is set (which changes the
727 // name). The setting of CMAKE_VERBOSE_MAKEFILE to ON will cause a
728 // "VERBOSE=1" to be added as a make variable which will change the
729 // name of this special target. This gives a make-time choice to
731 if((this->Makefile
->IsOn("CMAKE_VERBOSE_MAKEFILE"))
732 || (gg
->GetForceVerboseMakefiles()))
735 << "# Produce verbose output by default.\n"
739 if(this->SilentNoColon
)
741 makefileStream
<< "$(VERBOSE).SILENT\n";
745 this->WriteMakeRule(makefileStream
,
746 "Suppress display of executed commands.",
752 // Work-around for makes that drop rules that have no dependencies
754 std::string hack
= gg
->GetEmptyRuleHackDepends();
757 no_depends
.push_back(hack
);
759 std::string hack_cmd
= gg
->GetEmptyRuleHackCommand();
760 if(!hack_cmd
.empty())
762 no_commands
.push_back(hack_cmd
);
765 // Special symbolic target that never exists to force dependers to
769 "A target that is always out of date.",
770 "cmake_force", no_depends
, no_commands
, true);
772 // Variables for reference by other rules.
773 this->WriteMakeVariables(makefileStream
);
776 //----------------------------------------------------------------------------
777 void cmLocalUnixMakefileGenerator3
778 ::WriteSpecialTargetsBottom(std::ostream
& makefileStream
)
780 this->WriteDivider(makefileStream
);
782 << "# Special targets to cleanup operation of make.\n"
785 // Write special "cmake_check_build_system" target to run cmake with
786 // the --check-build-system flag.
788 // Build command to run CMake to check if anything needs regenerating.
789 std::string cmakefileName
= cmake::GetCMakeFilesDirectoryPostSlash();
790 cmakefileName
+= "Makefile.cmake";
791 std::string runRule
=
792 "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
793 runRule
+= " --check-build-system ";
794 runRule
+= this->Convert(cmakefileName
.c_str(),NONE
,SHELL
);
797 std::vector
<std::string
> no_depends
;
798 std::vector
<std::string
> commands
;
799 commands
.push_back(runRule
);
802 this->CreateCDCommand(commands
,
803 this->Makefile
->GetHomeOutputDirectory(),
804 cmLocalGenerator::START_OUTPUT
);
806 this->WriteMakeRule(makefileStream
,
807 "Special rule to run CMake to check the build system "
809 "No rule that depends on this can have "
810 "commands that come from listfiles\n"
811 "because they might be regenerated.",
812 "cmake_check_build_system",
820 //----------------------------------------------------------------------------
822 cmLocalUnixMakefileGenerator3
823 ::WriteConvenienceRule(std::ostream
& ruleFileStream
,
824 const char* realTarget
,
825 const char* helpTarget
)
827 // A rule is only needed if the names are different.
828 if(strcmp(realTarget
, helpTarget
) != 0)
830 // The helper target depends on the real target.
831 std::vector
<std::string
> depends
;
832 depends
.push_back(realTarget
);
834 // There are no commands.
835 std::vector
<std::string
> no_commands
;
838 this->WriteMakeRule(ruleFileStream
, "Convenience name for target.",
839 helpTarget
, depends
, no_commands
, true);
844 //----------------------------------------------------------------------------
846 cmLocalUnixMakefileGenerator3
847 ::GetRelativeTargetDirectory(cmTarget
const& target
)
849 std::string dir
= this->HomeRelativeOutputPath
;
850 dir
+= this->GetTargetDirectory(target
);
851 return this->Convert(dir
.c_str(),NONE
,UNCHANGED
);
856 //----------------------------------------------------------------------------
857 void cmLocalUnixMakefileGenerator3::AppendFlags(std::string
& flags
,
858 const char* newFlags
)
860 if(this->WatcomWMake
&& newFlags
&& *newFlags
)
862 std::string newf
= newFlags
;
863 if(newf
.find("\\\"") != newf
.npos
)
865 cmSystemTools::ReplaceString(newf
, "\\\"", "\"");
866 this->cmLocalGenerator::AppendFlags(flags
, newf
.c_str());
870 this->cmLocalGenerator::AppendFlags(flags
, newFlags
);
873 //----------------------------------------------------------------------------
875 cmLocalUnixMakefileGenerator3
876 ::AppendRuleDepend(std::vector
<std::string
>& depends
,
877 const char* ruleFileName
)
879 // Add a dependency on the rule file itself unless an option to skip
880 // it is specifically enabled by the user or project.
882 this->Makefile
->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
883 if(!nodep
|| cmSystemTools::IsOff(nodep
))
885 depends
.push_back(ruleFileName
);
889 //----------------------------------------------------------------------------
891 cmLocalUnixMakefileGenerator3
892 ::AppendCustomDepends(std::vector
<std::string
>& depends
,
893 const std::vector
<cmCustomCommand
>& ccs
)
895 for(std::vector
<cmCustomCommand
>::const_iterator i
= ccs
.begin();
898 this->AppendCustomDepend(depends
, *i
);
902 //----------------------------------------------------------------------------
904 cmLocalUnixMakefileGenerator3
905 ::AppendCustomDepend(std::vector
<std::string
>& depends
,
906 const cmCustomCommand
& cc
)
908 for(std::vector
<std::string
>::const_iterator d
= cc
.GetDepends().begin();
909 d
!= cc
.GetDepends().end(); ++d
)
911 // Lookup the real name of the dependency in case it is a CMake target.
912 std::string dep
= this->GetRealDependency
913 (d
->c_str(), this->ConfigurationName
.c_str());
914 depends
.push_back(dep
);
918 //----------------------------------------------------------------------------
920 cmLocalUnixMakefileGenerator3
921 ::AppendCustomCommands(std::vector
<std::string
>& commands
,
922 const std::vector
<cmCustomCommand
>& ccs
,
924 cmLocalGenerator::RelativeRoot relative
)
926 for(std::vector
<cmCustomCommand
>::const_iterator i
= ccs
.begin();
929 this->AppendCustomCommand(commands
, *i
, target
, true, relative
);
933 //----------------------------------------------------------------------------
935 cmLocalUnixMakefileGenerator3
936 ::AppendCustomCommand(std::vector
<std::string
>& commands
,
937 const cmCustomCommand
& cc
,
940 cmLocalGenerator::RelativeRoot relative
,
941 std::ostream
* content
)
943 // Optionally create a command to display the custom command's
944 // comment text. This is used for pre-build, pre-link, and
945 // post-build command comments. Custom build step commands have
946 // their comments generated elsewhere.
949 const char* comment
= cc
.GetComment();
950 if(comment
&& *comment
)
952 this->AppendEcho(commands
, comment
,
953 cmLocalUnixMakefileGenerator3::EchoGenerate
);
957 // if the command specified a working directory use it.
958 const char* dir
= this->Makefile
->GetStartOutputDirectory();
959 const char* workingDir
= cc
.GetWorkingDirectory();
968 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
969 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
971 // Add each command line to the set of commands.
972 std::vector
<std::string
> commands1
;
973 for(cmCustomCommandLines::const_iterator cl
= cc
.GetCommandLines().begin();
974 cl
!= cc
.GetCommandLines().end(); ++cl
)
976 // Build the command line in a single string.
977 const cmCustomCommandLine
& commandLine
= *cl
;
978 std::string cmd
= GetRealLocation(commandLine
[0].c_str(),
979 this->ConfigurationName
.c_str());
982 cmSystemTools::ReplaceString(cmd
, "/./", "/");
983 // Convert the command to a relative path only if the current
984 // working directory will be the start-output directory.
985 bool had_slash
= cmd
.find("/") != cmd
.npos
;
988 cmd
= this->Convert(cmd
.c_str(),START_OUTPUT
);
990 bool has_slash
= cmd
.find("/") != cmd
.npos
;
991 if(had_slash
&& !has_slash
)
993 // This command was specified as a path to a file in the
994 // current directory. Add a leading "./" so it can run
995 // without the current directory being in the search path.
998 if(this->WatcomWMake
&&
999 cmSystemTools::FileIsFullPath(cmd
.c_str()) &&
1000 cmd
.find(" ") != cmd
.npos
)
1002 // On Watcom WMake use the windows short path for the command
1003 // name. This is needed to avoid funny quoting problems on
1004 // lines with shell redirection operators.
1006 if(cmSystemTools::GetShortPath(cmd
.c_str(), scmd
))
1011 std::string launcher
=
1012 this->MakeLauncher(cc
, target
, workingDir
? NONE
: START_OUTPUT
);
1013 cmd
= launcher
+ this->Convert(cmd
.c_str(),NONE
,SHELL
);
1014 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1019 cmd
+= this->EscapeForShellOldStyle(commandLine
[j
].c_str());
1023 cmd
+= this->EscapeForShell(commandLine
[j
].c_str(),
1024 escapeAllowMakeVars
);
1029 // Rule content does not include the launcher.
1030 *content
<< (cmd
.c_str()+launcher
.size());
1032 if(this->BorlandMakeCurlyHack
)
1034 // Borland Make has a very strange bug. If the first curly
1035 // brace anywhere in the command string is a left curly, it
1036 // must be written {{} instead of just {. Otherwise some
1037 // curly braces are removed. The hack can be skipped if the
1038 // first curly brace is the last character.
1039 std::string::size_type lcurly
= cmd
.find("{");
1040 if(lcurly
!= cmd
.npos
&& lcurly
< (cmd
.size()-1))
1042 std::string::size_type rcurly
= cmd
.find("}");
1043 if(rcurly
== cmd
.npos
|| rcurly
> lcurly
)
1045 // The first curly is a left curly. Use the hack.
1046 std::string hack_cmd
= cmd
.substr(0, lcurly
);
1048 hack_cmd
+= cmd
.substr(lcurly
+1);
1053 commands1
.push_back(cmd
);
1057 // Setup the proper working directory for the commands.
1058 this->CreateCDCommand(commands1
, dir
, relative
);
1060 // push back the custom commands
1061 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
1064 //----------------------------------------------------------------------------
1066 cmLocalUnixMakefileGenerator3::MakeLauncher(const cmCustomCommand
& cc
,
1068 RelativeRoot relative
)
1070 // Short-circuit if there is no launcher.
1071 const char* prop
= "RULE_LAUNCH_CUSTOM";
1072 const char* val
= this->GetRuleLauncher(target
, prop
);
1078 // Expand rules in the empty string. It may insert the launcher and
1079 // perform replacements.
1081 vars
.RuleLauncher
= prop
;
1082 vars
.CMTarget
= target
;
1084 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1085 if(!outputs
.empty())
1087 output
= this->Convert(outputs
[0].c_str(), relative
, SHELL
);
1089 vars
.Output
= output
.c_str();
1091 std::string launcher
;
1092 this->ExpandRuleVariables(launcher
, vars
);
1093 if(!launcher
.empty())
1100 //----------------------------------------------------------------------------
1102 cmLocalUnixMakefileGenerator3
1103 ::AppendCleanCommand(std::vector
<std::string
>& commands
,
1104 const std::vector
<std::string
>& files
,
1105 cmTarget
& target
, const char* filename
)
1109 std::string cleanfile
= this->Makefile
->GetCurrentOutputDirectory();
1111 cleanfile
+= this->GetTargetDirectory(target
);
1112 cleanfile
+= "/cmake_clean";
1116 cleanfile
+= filename
;
1118 cleanfile
+= ".cmake";
1119 std::string cleanfilePath
= this->Convert(cleanfile
.c_str(), FULL
);
1120 std::ofstream
fout(cleanfilePath
.c_str());
1123 cmSystemTools::Error("Could not create ", cleanfilePath
.c_str());
1125 fout
<< "FILE(REMOVE_RECURSE\n";
1126 std::string remove
= "$(CMAKE_COMMAND) -P ";
1127 remove
+= this->Convert(cleanfile
.c_str(), START_OUTPUT
, SHELL
);
1128 for(std::vector
<std::string
>::const_iterator f
= files
.begin();
1129 f
!= files
.end(); ++f
)
1131 std::string fc
= this->Convert(f
->c_str(),START_OUTPUT
,UNCHANGED
);
1132 fout
<< " " << this->EscapeForCMake(fc
.c_str()) << "\n";
1135 commands
.push_back(remove
);
1137 // For the main clean rule add per-language cleaning.
1140 // Get the set of source languages in the target.
1141 std::set
<cmStdString
> languages
;
1142 target
.GetLanguages(languages
);
1144 << "# Per-language clean rules from dependency scanning.\n"
1146 for(std::set
<cmStdString
>::const_iterator l
= languages
.begin();
1147 l
!= languages
.end(); ++l
)
1152 << " INCLUDE(" << this->GetTargetDirectory(target
)
1153 << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
1154 << "ENDFOREACH(lang)\n";
1159 //----------------------------------------------------------------------------
1161 cmLocalUnixMakefileGenerator3::AppendEcho(std::vector
<std::string
>& commands
,
1165 // Choose the color for the text.
1166 std::string color_name
;
1167 #ifdef CMAKE_BUILD_WITH_CMAKE
1168 if(this->GlobalGenerator
->GetToolSupportsColor() && this->ColorMakefile
)
1170 // See cmake::ExecuteEchoColor in cmake.cxx for these options.
1171 // This color set is readable on both black and white backgrounds.
1177 color_name
= "--magenta --bold ";
1180 color_name
= "--green ";
1183 color_name
= "--red --bold ";
1186 color_name
= "--blue --bold ";
1189 color_name
= "--cyan ";
1197 // Echo one line at a time.
1200 for(const char* c
= text
;; ++c
)
1202 if(*c
== '\n' || *c
== '\0')
1204 // Avoid writing a blank last line on end-of-string.
1205 if(*c
!= '\0' || !line
.empty())
1207 // Add a command to echo this line.
1209 if(color_name
.empty())
1211 // Use the native echo command.
1212 cmd
= this->NativeEchoCommand
;
1213 cmd
+= this->EscapeForShell(line
.c_str(), false,
1214 this->NativeEchoWindows
);
1218 // Use cmake to echo the text in color.
1219 cmd
= "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ";
1221 cmd
+= this->EscapeForShell(line
.c_str());
1223 commands
.push_back(cmd
);
1226 // Reset the line to emtpy.
1229 // Terminate on end-of-string.
1237 // Append this character to the current line.
1243 //----------------------------------------------------------------------------
1245 cmLocalUnixMakefileGenerator3
1246 ::CreateMakeVariable(const char* sin
, const char* s2in
)
1248 std::string s
= sin
;
1249 std::string s2
= s2in
;
1250 std::string unmodified
= s
;
1252 // if there is no restriction on the length of make variables
1253 // and there are no "." charactors in the string, then return the
1254 // unmodified combination.
1255 if((!this->MakefileVariableSize
&& unmodified
.find('.') == s
.npos
)
1256 && (!this->MakefileVariableSize
&& unmodified
.find('-') == s
.npos
))
1261 // see if the variable has been defined before and return
1262 // the modified version of the variable
1263 std::map
<cmStdString
, cmStdString
>::iterator i
=
1264 this->MakeVariableMap
.find(unmodified
);
1265 if(i
!= this->MakeVariableMap
.end())
1269 // start with the unmodified variable
1270 std::string ret
= unmodified
;
1271 // if this there is no value for this->MakefileVariableSize then
1272 // the string must have bad characters in it
1273 if(!this->MakefileVariableSize
)
1275 cmSystemTools::ReplaceString(ret
, ".", "_");
1276 cmSystemTools::ReplaceString(ret
, "-", "__");
1279 // make sure the _ version is not already used, if
1280 // it is used then add number to the end of the variable
1281 while(this->ShortMakeVariableMap
.count(ret
) && ni
< 1000)
1284 sprintf(buffer
, "%04d", ni
);
1285 ret
= unmodified
+ buffer
;
1287 this->ShortMakeVariableMap
[ret
] = "1";
1288 this->MakeVariableMap
[unmodified
] = ret
;
1292 // if the string is greater the 32 chars it is an invalid vairable name
1294 if(static_cast<int>(ret
.size()) > this->MakefileVariableSize
)
1296 int keep
= this->MakefileVariableSize
- 8;
1297 int size
= keep
+ 3;
1298 std::string str1
= s
;
1299 std::string str2
= s2
;
1300 // we must shorten the combined string by 4 charactors
1301 // keep no more than 24 charactors from the second string
1302 if(static_cast<int>(str2
.size()) > keep
)
1304 str2
= str2
.substr(0, keep
);
1306 if(static_cast<int>(str1
.size()) + static_cast<int>(str2
.size()) > size
)
1308 str1
= str1
.substr(0, size
- str2
.size());
1312 sprintf(buffer
, "%04d", ni
);
1313 ret
= str1
+ str2
+ buffer
;
1314 while(this->ShortMakeVariableMap
.count(ret
) && ni
< 1000)
1317 sprintf(buffer
, "%04d", ni
);
1318 ret
= str1
+ str2
+ buffer
;
1322 cmSystemTools::Error("Borland makefile variable length too long");
1325 // once an unused variable is found
1326 this->ShortMakeVariableMap
[ret
] = "1";
1328 // always make an entry into the unmodified to variable map
1329 this->MakeVariableMap
[unmodified
] = ret
;
1333 //----------------------------------------------------------------------------
1334 bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo
,
1338 // read in the target info file
1339 if(!this->Makefile
->ReadListFile(0, tgtInfo
) ||
1340 cmSystemTools::GetErrorOccuredFlag())
1342 cmSystemTools::Error("Target DependInfo.cmake file not found");
1345 // Check if any multiple output pairs have a missing file.
1346 this->CheckMultipleOutputs(verbose
);
1348 std::string dir
= cmSystemTools::GetFilenamePath(tgtInfo
);
1349 std::string internalDependFile
= dir
+ "/depend.internal";
1350 std::string dependFile
= dir
+ "/depend.make";
1352 // If the target DependInfo.cmake file has changed since the last
1353 // time dependencies were scanned then force rescanning. This may
1354 // happen when a new source file is added and CMake regenerates the
1355 // project but no other sources were touched.
1356 bool needRescanDependInfo
= false;
1357 cmFileTimeComparison
* ftc
=
1358 this->GlobalGenerator
->GetCMakeInstance()->GetFileComparison();
1361 if(!ftc
->FileTimeCompare(internalDependFile
.c_str(), tgtInfo
, &result
) ||
1366 cmOStringStream msg
;
1367 msg
<< "Dependee \"" << tgtInfo
1368 << "\" is newer than depender \""
1369 << internalDependFile
<< "\"." << std::endl
;
1370 cmSystemTools::Stdout(msg
.str().c_str());
1372 needRescanDependInfo
= true;
1376 // If the directory information is newer than depend.internal, include dirs
1377 // may have changed. In this case discard all old dependencies.
1378 bool needRescanDirInfo
= false;
1379 std::string dirInfoFile
= this->Makefile
->GetStartOutputDirectory();
1380 dirInfoFile
+= cmake::GetCMakeFilesDirectory();
1381 dirInfoFile
+= "/CMakeDirectoryInformation.cmake";
1384 if(!ftc
->FileTimeCompare(internalDependFile
.c_str(),
1385 dirInfoFile
.c_str(), &result
) || result
< 0)
1389 cmOStringStream msg
;
1390 msg
<< "Dependee \"" << internalDependFile
1391 << "\" is newer than depender \""
1392 << dirInfoFile
<< "\"." << std::endl
;
1393 cmSystemTools::Stdout(msg
.str().c_str());
1395 needRescanDirInfo
= true;
1399 // Check the implicit dependencies to see if they are up to date.
1400 // The build.make file may have explicit dependencies for the object
1401 // files but these will not affect the scanning process so they need
1402 // not be considered.
1403 bool needRescanDependencies
= false;
1404 if (needRescanDirInfo
== false)
1407 checker
.SetVerbose(verbose
);
1408 checker
.SetFileComparison(ftc
);
1409 needRescanDependencies
= !checker
.Check(dependFile
.c_str(),
1410 internalDependFile
.c_str());
1413 if(needRescanDependInfo
|| needRescanDirInfo
|| needRescanDependencies
)
1415 // The dependencies must be regenerated.
1416 std::string targetName
= cmSystemTools::GetFilenameName(dir
);
1417 targetName
= targetName
.substr(0, targetName
.length()-4);
1418 std::string message
= "Scanning dependencies of target ";
1419 message
+= targetName
;
1420 #ifdef CMAKE_BUILD_WITH_CMAKE
1421 cmSystemTools::MakefileColorEcho(
1422 cmsysTerminal_Color_ForegroundMagenta
|
1423 cmsysTerminal_Color_ForegroundBold
,
1424 message
.c_str(), true, color
);
1426 fprintf(stdout
, "%s\n", message
.c_str());
1429 return this->ScanDependencies(dir
.c_str());
1433 // The dependencies are already up-to-date.
1438 //----------------------------------------------------------------------------
1440 cmLocalUnixMakefileGenerator3
1441 ::ScanDependencies(const char* targetDir
)
1443 // Read the directory information file.
1444 cmMakefile
* mf
= this->Makefile
;
1445 bool haveDirectoryInfo
= false;
1446 std::string dirInfoFile
= this->Makefile
->GetStartOutputDirectory();
1447 dirInfoFile
+= cmake::GetCMakeFilesDirectory();
1448 dirInfoFile
+= "/CMakeDirectoryInformation.cmake";
1449 if(mf
->ReadListFile(0, dirInfoFile
.c_str()) &&
1450 !cmSystemTools::GetErrorOccuredFlag())
1452 haveDirectoryInfo
= true;
1455 // Lookup useful directory information.
1456 if(haveDirectoryInfo
)
1458 // Test whether we need to force Unix paths.
1459 if(const char* force
= mf
->GetDefinition("CMAKE_FORCE_UNIX_PATHS"))
1461 if(!cmSystemTools::IsOff(force
))
1463 cmSystemTools::SetForceUnixPaths(true);
1467 // Setup relative path top directories.
1468 this->RelativePathsConfigured
= true;
1469 if(const char* relativePathTopSource
=
1470 mf
->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
1472 this->RelativePathTopSource
= relativePathTopSource
;
1474 if(const char* relativePathTopBinary
=
1475 mf
->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
1477 this->RelativePathTopBinary
= relativePathTopBinary
;
1482 cmSystemTools::Error("Directory Information file not found");
1485 // create the file stream for the depends file
1486 std::string dir
= targetDir
;
1488 // Open the make depends file. This should be copy-if-different
1489 // because the make tool may try to reload it needlessly otherwise.
1490 std::string ruleFileNameFull
= dir
;
1491 ruleFileNameFull
+= "/depend.make";
1492 cmGeneratedFileStream
ruleFileStream(ruleFileNameFull
.c_str());
1493 ruleFileStream
.SetCopyIfDifferent(true);
1499 // Open the cmake dependency tracking file. This should not be
1500 // copy-if-different because dependencies are re-scanned when it is
1501 // older than the DependInfo.cmake.
1502 std::string internalRuleFileNameFull
= dir
;
1503 internalRuleFileNameFull
+= "/depend.internal";
1504 cmGeneratedFileStream
1505 internalRuleFileStream(internalRuleFileNameFull
.c_str());
1506 if(!internalRuleFileStream
)
1511 this->WriteDisclaimer(ruleFileStream
);
1512 this->WriteDisclaimer(internalRuleFileStream
);
1514 // for each language we need to scan, scan it
1515 const char *langStr
= mf
->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
1516 std::vector
<std::string
> langs
;
1517 cmSystemTools::ExpandListArgument(langStr
, langs
);
1518 for (std::vector
<std::string
>::iterator li
=
1519 langs
.begin(); li
!= langs
.end(); ++li
)
1521 // construct the checker
1522 std::string lang
= li
->c_str();
1524 // Create the scanner for this language
1525 cmDepends
*scanner
= 0;
1526 if(lang
== "C" || lang
== "CXX" || lang
== "RC")
1528 // TODO: Handle RC (resource files) dependencies correctly.
1529 scanner
= new cmDependsC(this, targetDir
, lang
.c_str());
1531 #ifdef CMAKE_BUILD_WITH_CMAKE
1532 else if(lang
== "Fortran")
1534 scanner
= new cmDependsFortran(this);
1536 else if(lang
== "Java")
1538 scanner
= new cmDependsJava();
1544 scanner
->SetLocalGenerator(this);
1545 scanner
->SetFileComparison
1546 (this->GlobalGenerator
->GetCMakeInstance()->GetFileComparison());
1547 scanner
->SetLanguage(lang
.c_str());
1548 scanner
->SetTargetDirectory(dir
.c_str());
1549 scanner
->Write(ruleFileStream
, internalRuleFileStream
);
1551 // free the scanner for this language
1559 //----------------------------------------------------------------------------
1560 void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose
)
1562 cmMakefile
* mf
= this->Makefile
;
1564 // Get the string listing the multiple output pairs.
1565 const char* pairs_string
= mf
->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
1571 // Convert the string to a list and preserve empty entries.
1572 std::vector
<std::string
> pairs
;
1573 cmSystemTools::ExpandListArgument(pairs_string
, pairs
, true);
1574 for(std::vector
<std::string
>::const_iterator i
= pairs
.begin();
1575 i
!= pairs
.end() && (i
+1) != pairs
.end();)
1577 const std::string
& depender
= *i
++;
1578 const std::string
& dependee
= *i
++;
1580 // If the depender is missing then delete the dependee to make
1581 // sure both will be regenerated.
1582 if(cmSystemTools::FileExists(dependee
.c_str()) &&
1583 !cmSystemTools::FileExists(depender
.c_str()))
1587 cmOStringStream msg
;
1588 msg
<< "Deleting primary custom command output \"" << dependee
1589 << "\" because another output \""
1590 << depender
<< "\" does not exist." << std::endl
;
1591 cmSystemTools::Stdout(msg
.str().c_str());
1593 cmSystemTools::RemoveFile(dependee
.c_str());
1598 //----------------------------------------------------------------------------
1599 void cmLocalUnixMakefileGenerator3
1600 ::WriteLocalAllRules(std::ostream
& ruleFileStream
)
1602 this->WriteDisclaimer(ruleFileStream
);
1604 // Write the main entry point target. This must be the VERY first
1605 // target so that make with no arguments will run it.
1607 // Just depend on the all target to drive the build.
1608 std::vector
<std::string
> depends
;
1609 std::vector
<std::string
> no_commands
;
1610 depends
.push_back("all");
1613 this->WriteMakeRule(ruleFileStream
,
1614 "Default target executed when no arguments are "
1621 this->WriteSpecialTargetsTop(ruleFileStream
);
1623 // Include the progress variables for the target.
1624 // Write all global targets
1625 this->WriteDivider(ruleFileStream
);
1627 << "# Targets provided globally by CMake.\n"
1629 cmTargets
* targets
= &(this->Makefile
->GetTargets());
1630 cmTargets::iterator glIt
;
1631 for ( glIt
= targets
->begin(); glIt
!= targets
->end(); ++ glIt
)
1633 if ( glIt
->second
.GetType() == cmTarget::GLOBAL_TARGET
)
1635 std::string targetString
= "Special rule for the target " + glIt
->first
;
1636 std::vector
<std::string
> commands
;
1637 std::vector
<std::string
> depends
;
1639 const char* text
= glIt
->second
.GetProperty("EchoString");
1642 text
= "Running external command ...";
1644 std::set
<cmStdString
>::const_iterator dit
;
1645 for ( dit
= glIt
->second
.GetUtilities().begin();
1646 dit
!= glIt
->second
.GetUtilities().end();
1649 depends
.push_back(dit
->c_str());
1651 this->AppendEcho(commands
, text
,
1652 cmLocalUnixMakefileGenerator3::EchoGlobal
);
1654 // Global targets store their rules in pre- and post-build commands.
1655 this->AppendCustomDepends(depends
,
1656 glIt
->second
.GetPreBuildCommands());
1657 this->AppendCustomDepends(depends
,
1658 glIt
->second
.GetPostBuildCommands());
1659 this->AppendCustomCommands(commands
,
1660 glIt
->second
.GetPreBuildCommands(),
1662 cmLocalGenerator::START_OUTPUT
);
1663 this->AppendCustomCommands(commands
,
1664 glIt
->second
.GetPostBuildCommands(),
1666 cmLocalGenerator::START_OUTPUT
);
1667 std::string targetName
= glIt
->second
.GetName();
1668 this->WriteMakeRule(ruleFileStream
, targetString
.c_str(),
1669 targetName
.c_str(), depends
, commands
, true);
1671 // Provide a "/fast" version of the target.
1673 if((targetName
== "install")
1674 || (targetName
== "install_local")
1675 || (targetName
== "install_strip"))
1677 // Provide a fast install target that does not depend on all
1678 // but has the same command.
1679 depends
.push_back("preinstall/fast");
1683 // Just forward to the real target so at least it will work.
1684 depends
.push_back(targetName
);
1687 targetName
+= "/fast";
1688 this->WriteMakeRule(ruleFileStream
, targetString
.c_str(),
1689 targetName
.c_str(), depends
, commands
, true);
1693 std::vector
<std::string
> depends
;
1694 std::vector
<std::string
> commands
;
1696 // Write the all rule.
1698 std::string recursiveTarget
= this->Makefile
->GetStartOutputDirectory();
1699 recursiveTarget
+= "/all";
1701 depends
.push_back("cmake_check_build_system");
1703 std::string progressDir
= this->Makefile
->GetHomeOutputDirectory();
1704 progressDir
+= cmake::GetCMakeFilesDirectory();
1706 cmOStringStream progCmd
;
1708 "$(CMAKE_COMMAND) -E cmake_progress_start ";
1709 progCmd
<< this->Convert(progressDir
.c_str(),
1710 cmLocalGenerator::FULL
,
1711 cmLocalGenerator::SHELL
);
1713 std::string progressFile
= cmake::GetCMakeFilesDirectory();
1714 progressFile
+= "/progress.marks";
1715 std::string progressFileNameFull
=
1716 this->ConvertToFullPath(progressFile
.c_str());
1717 progCmd
<< " " << this->Convert(progressFileNameFull
.c_str(),
1718 cmLocalGenerator::FULL
,
1719 cmLocalGenerator::SHELL
);
1720 commands
.push_back(progCmd
.str());
1722 std::string mf2Dir
= cmake::GetCMakeFilesDirectoryPostSlash();
1723 mf2Dir
+= "Makefile2";
1724 commands
.push_back(this->GetRecursiveMakeCall(mf2Dir
.c_str(),
1725 recursiveTarget
.c_str()));
1726 this->CreateCDCommand(commands
,
1727 this->Makefile
->GetHomeOutputDirectory(),
1728 cmLocalGenerator::START_OUTPUT
);
1730 cmOStringStream progCmd
;
1731 progCmd
<< "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
1732 progCmd
<< this->Convert(progressDir
.c_str(),
1733 cmLocalGenerator::FULL
,
1734 cmLocalGenerator::SHELL
);
1736 commands
.push_back(progCmd
.str());
1738 this->WriteMakeRule(ruleFileStream
, "The main all target", "all",
1739 depends
, commands
, true);
1741 // Write the clean rule.
1742 recursiveTarget
= this->Makefile
->GetStartOutputDirectory();
1743 recursiveTarget
+= "/clean";
1746 commands
.push_back(this->GetRecursiveMakeCall(mf2Dir
.c_str(),
1747 recursiveTarget
.c_str()));
1748 this->CreateCDCommand(commands
,
1749 this->Makefile
->GetHomeOutputDirectory(),
1750 cmLocalGenerator::START_OUTPUT
);
1751 this->WriteMakeRule(ruleFileStream
, "The main clean target", "clean",
1752 depends
, commands
, true);
1755 depends
.push_back("clean");
1756 this->WriteMakeRule(ruleFileStream
, "The main clean target", "clean/fast",
1757 depends
, commands
, true);
1759 // Write the preinstall rule.
1760 recursiveTarget
= this->Makefile
->GetStartOutputDirectory();
1761 recursiveTarget
+= "/preinstall";
1765 this->Makefile
->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1766 if(!noall
|| cmSystemTools::IsOff(noall
))
1768 // Drive the build before installing.
1769 depends
.push_back("all");
1773 // At least make sure the build system is up to date.
1774 depends
.push_back("cmake_check_build_system");
1777 (this->GetRecursiveMakeCall(mf2Dir
.c_str(), recursiveTarget
.c_str()));
1778 this->CreateCDCommand(commands
,
1779 this->Makefile
->GetHomeOutputDirectory(),
1780 cmLocalGenerator::START_OUTPUT
);
1781 this->WriteMakeRule(ruleFileStream
, "Prepare targets for installation.",
1782 "preinstall", depends
, commands
, true);
1784 this->WriteMakeRule(ruleFileStream
, "Prepare targets for installation.",
1785 "preinstall/fast", depends
, commands
, true);
1787 // write the depend rule, really a recompute depends rule
1790 std::string cmakefileName
= cmake::GetCMakeFilesDirectoryPostSlash();
1791 cmakefileName
+= "Makefile.cmake";
1792 std::string runRule
=
1793 "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
1794 runRule
+= " --check-build-system ";
1795 runRule
+= this->Convert(cmakefileName
.c_str(),cmLocalGenerator::NONE
,
1796 cmLocalGenerator::SHELL
);
1798 commands
.push_back(runRule
);
1799 this->CreateCDCommand(commands
,
1800 this->Makefile
->GetHomeOutputDirectory(),
1801 cmLocalGenerator::START_OUTPUT
);
1802 this->WriteMakeRule(ruleFileStream
, "clear depends",
1804 depends
, commands
, true);
1808 //----------------------------------------------------------------------------
1809 void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile
* mf
,
1812 // Get the list of target files to check
1813 const char* infoDef
= mf
->GetDefinition("CMAKE_DEPEND_INFO_FILES");
1818 std::vector
<std::string
> files
;
1819 cmSystemTools::ExpandListArgument(infoDef
, files
);
1821 // Each depend information file corresponds to a target. Clear the
1822 // dependencies for that target.
1824 clearer
.SetVerbose(verbose
);
1825 for(std::vector
<std::string
>::iterator l
= files
.begin();
1826 l
!= files
.end(); ++l
)
1828 std::string dir
= cmSystemTools::GetFilenamePath(l
->c_str());
1830 // Clear the implicit dependency makefile.
1831 std::string dependFile
= dir
+ "/depend.make";
1832 clearer
.Clear(dependFile
.c_str());
1834 // Remove the internal dependency check file to force
1836 std::string internalDependFile
= dir
+ "/depend.internal";
1837 cmSystemTools::RemoveFile(internalDependFile
.c_str());
1842 void cmLocalUnixMakefileGenerator3
1843 ::WriteDependLanguageInfo(std::ostream
& cmakefileStream
, cmTarget
&target
)
1845 ImplicitDependLanguageMap
const& implicitLangs
=
1846 this->GetImplicitDepends(target
);
1848 // list the languages
1850 << "# The set of languages for which implicit dependencies are needed:\n";
1852 << "SET(CMAKE_DEPENDS_LANGUAGES\n";
1853 for(ImplicitDependLanguageMap::const_iterator
1854 l
= implicitLangs
.begin(); l
!= implicitLangs
.end(); ++l
)
1856 cmakefileStream
<< " \"" << l
->first
.c_str() << "\"\n";
1858 cmakefileStream
<< " )\n";
1860 // now list the files for each language
1862 << "# The set of files for implicit dependencies of each language:\n";
1863 for(ImplicitDependLanguageMap::const_iterator
1864 l
= implicitLangs
.begin(); l
!= implicitLangs
.end(); ++l
)
1867 << "SET(CMAKE_DEPENDS_CHECK_" << l
->first
.c_str() << "\n";
1868 ImplicitDependFileMap
const& implicitPairs
= l
->second
;
1870 // for each file pair
1871 for(ImplicitDependFileMap::const_iterator pi
= implicitPairs
.begin();
1872 pi
!= implicitPairs
.end(); ++pi
)
1874 cmakefileStream
<< " \"" << pi
->second
<< "\" ";
1875 cmakefileStream
<< "\"" << pi
->first
<< "\"\n";
1877 cmakefileStream
<< " )\n";
1879 // Tell the dependency scanner what compiler is used.
1880 std::string cidVar
= "CMAKE_";
1882 cidVar
+= "_COMPILER_ID";
1883 const char* cid
= this->Makefile
->GetDefinition(cidVar
.c_str());
1887 << "SET(CMAKE_" << l
->first
.c_str() << "_COMPILER_ID \""
1892 // Build a list of preprocessor definitions for the target.
1893 std::vector
<std::string
> defines
;
1895 std::string defPropName
= "COMPILE_DEFINITIONS_";
1896 defPropName
+= cmSystemTools::UpperCase(this->ConfigurationName
);
1897 if(const char* ddefs
= this->Makefile
->GetProperty("COMPILE_DEFINITIONS"))
1899 cmSystemTools::ExpandListArgument(ddefs
, defines
);
1901 if(const char* cdefs
= target
.GetProperty("COMPILE_DEFINITIONS"))
1903 cmSystemTools::ExpandListArgument(cdefs
, defines
);
1905 if(const char* dcdefs
= this->Makefile
->GetProperty(defPropName
.c_str()))
1907 cmSystemTools::ExpandListArgument(dcdefs
, defines
);
1909 if(const char* ccdefs
= target
.GetProperty(defPropName
.c_str()))
1911 cmSystemTools::ExpandListArgument(ccdefs
, defines
);
1914 if(!defines
.empty())
1918 << "# Preprocessor definitions for this target.\n"
1919 << "SET(CMAKE_TARGET_DEFINITIONS\n";
1920 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
1921 di
!= defines
.end(); ++di
)
1924 << " " << this->EscapeForCMake(di
->c_str()) << "\n";
1930 // Store include transform rule properties. Write the directory
1931 // rules first because they may be overridden by later target rules.
1932 std::vector
<std::string
> transformRules
;
1933 if(const char* xform
=
1934 this->Makefile
->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"))
1936 cmSystemTools::ExpandListArgument(xform
, transformRules
);
1938 if(const char* xform
=
1939 target
.GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"))
1941 cmSystemTools::ExpandListArgument(xform
, transformRules
);
1943 if(!transformRules
.empty())
1946 << "SET(CMAKE_INCLUDE_TRANSFORMS\n";
1947 for(std::vector
<std::string
>::const_iterator tri
= transformRules
.begin();
1948 tri
!= transformRules
.end(); ++tri
)
1950 cmakefileStream
<< " " << this->EscapeForCMake(tri
->c_str()) << "\n";
1957 //----------------------------------------------------------------------------
1959 cmLocalUnixMakefileGenerator3
1960 ::GetObjectFileName(cmTarget
& target
,
1961 const cmSourceFile
& source
,
1962 std::string
* nameWithoutTargetDir
,
1963 bool* hasSourceExtension
)
1965 // Make sure we never hit this old case.
1966 if(source
.GetProperty("MACOSX_PACKAGE_LOCATION"))
1968 std::string msg
= "MACOSX_PACKAGE_LOCATION set on source file: ";
1969 msg
+= source
.GetFullPath();
1970 this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR
,
1974 // Start with the target directory.
1975 std::string obj
= this->GetTargetDirectory(target
);
1978 // Get the object file name without the target directory.
1979 std::string dir_max
;
1980 dir_max
+= this->Makefile
->GetCurrentOutputDirectory();
1983 std::string objectName
=
1984 this->GetObjectFileNameWithoutTarget(source
, dir_max
,
1985 hasSourceExtension
);
1986 if(nameWithoutTargetDir
)
1988 *nameWithoutTargetDir
= objectName
;
1991 // Append the object name to the target directory.
1996 //----------------------------------------------------------------------------
1997 void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream
& os
)
2000 << "# CMAKE generated file: DO NOT EDIT!\n"
2001 << "# Generated by \"" << this->GlobalGenerator
->GetName() << "\""
2002 << " Generator, CMake Version "
2003 << cmVersion::GetMajorVersion() << "."
2004 << cmVersion::GetMinorVersion() << "\n\n";
2007 //----------------------------------------------------------------------------
2009 cmLocalUnixMakefileGenerator3
2010 ::GetRecursiveMakeCall(const char *makefile
, const char* tgt
)
2012 // Call make on the given file.
2014 cmd
+= "$(MAKE) -f ";
2015 cmd
+= this->Convert(makefile
,NONE
,SHELL
);
2018 // Pass down verbosity level.
2019 if(this->GetMakeSilentFlag().size())
2021 cmd
+= this->GetMakeSilentFlag();
2025 // Most unix makes will pass the command line flags to make down to
2026 // sub-invoked makes via an environment variable. However, some
2027 // makes do not support that, so you have to pass the flags
2029 if(this->GetPassMakeflags())
2031 cmd
+= "-$(MAKEFLAGS) ";
2035 if (tgt
&& tgt
[0] != '\0')
2037 // The make target is always relative to the top of the build tree.
2038 std::string tgt2
= this->Convert(tgt
, HOME_OUTPUT
);
2040 // The target may have been written with windows paths.
2041 cmSystemTools::ConvertToOutputSlashes(tgt2
);
2043 // Escape one extra time if the make tool requires it.
2044 if(this->MakeCommandEscapeTargetTwice
)
2046 tgt2
= this->EscapeForShell(tgt2
.c_str(), true, false);
2049 // The target name is now a string that should be passed verbatim
2050 // on the command line.
2051 cmd
+= this->EscapeForShell(tgt2
.c_str(), true, false);
2056 //----------------------------------------------------------------------------
2057 void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream
& os
)
2060 << "#======================================"
2061 << "=======================================\n";
2064 //----------------------------------------------------------------------------
2066 cmLocalUnixMakefileGenerator3
2067 ::WriteCMakeArgument(std::ostream
& os
, const char* s
)
2069 // Write the given string to the stream with escaping to get it back
2070 // into CMake through the lexical scanner.
2072 for(const char* c
= s
; *c
; ++c
)
2090 //----------------------------------------------------------------------------
2092 cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(const char* p
)
2095 // Split the path into its components.
2096 std::vector
<std::string
> components
;
2097 cmSystemTools::SplitPath(p
, components
);
2099 // Return an empty path if there are no components.
2100 if(components
.empty())
2105 // Choose a slash direction and fix root component.
2106 const char* slash
= "/";
2107 #if defined(_WIN32) && !defined(__CYGWIN__)
2108 if(!cmSystemTools::GetForceUnixPaths())
2111 for(std::string::iterator i
= components
[0].begin();
2112 i
!= components
[0].end(); ++i
)
2122 // Begin the quoted result with the root component.
2123 std::string result
= "\"";
2124 result
+= components
[0];
2126 // Now add the rest of the components separated by the proper slash
2127 // direction for this platform.
2129 for(unsigned int i
=1; i
< components
.size(); ++i
)
2131 // Only the last component can be empty to avoid double slashes.
2132 if(components
[i
].length() > 0 || (i
== (components
.size()-1)))
2138 result
+= components
[i
];
2143 // Close the quoted result.
2149 //----------------------------------------------------------------------------
2151 cmLocalUnixMakefileGenerator3
2152 ::GetTargetDirectory(cmTarget
const& target
) const
2154 std::string dir
= cmake::GetCMakeFilesDirectoryPostSlash();
2155 dir
+= target
.GetName();
2164 //----------------------------------------------------------------------------
2165 cmLocalUnixMakefileGenerator3::ImplicitDependLanguageMap
const&
2166 cmLocalUnixMakefileGenerator3::GetImplicitDepends(cmTarget
const& tgt
)
2168 return this->ImplicitDepends
[tgt
.GetName()];
2171 //----------------------------------------------------------------------------
2173 cmLocalUnixMakefileGenerator3::AddImplicitDepends(cmTarget
const& tgt
,
2178 this->ImplicitDepends
[tgt
.GetName()][lang
][obj
] = src
;
2181 //----------------------------------------------------------------------------
2182 void cmLocalUnixMakefileGenerator3
2183 ::CreateCDCommand(std::vector
<std::string
>& commands
, const char *tgtDir
,
2184 cmLocalGenerator::RelativeRoot relRetDir
)
2186 const char* retDir
= this->GetRelativeRootPath(relRetDir
);
2188 // do we need to cd?
2189 if (!strcmp(tgtDir
,retDir
))
2196 // On Windows we must perform each step separately and then change
2197 // back because the shell keeps the working directory between
2199 std::string cmd
= "cd ";
2200 cmd
+= this->ConvertToOutputForExisting(tgtDir
, relRetDir
);
2201 commands
.insert(commands
.begin(),cmd
);
2203 // Change back to the starting directory.
2205 cmd
+= this->ConvertToOutputForExisting(relRetDir
, tgtDir
);
2206 commands
.push_back(cmd
);
2210 // On UNIX we must construct a single shell command to change
2211 // directory and build because make resets the directory between
2213 std::vector
<std::string
>::iterator i
= commands
.begin();
2214 for (; i
!= commands
.end(); ++i
)
2216 std::string cmd
= "cd ";
2217 cmd
+= this->ConvertToOutputForExisting(tgtDir
, relRetDir
);
2226 void cmLocalUnixMakefileGenerator3
2227 ::GetTargetObjectFileDirectories(cmTarget
* target
,
2228 std::vector
<std::string
>& dirs
)
2230 std::string dir
= this->Makefile
->GetCurrentOutputDirectory();
2232 dir
+= this->GetTargetDirectory(*target
);
2233 dirs
.push_back(dir
);