STYLE: Fix typo in GetFilenameLastExtension docs
[cmake.git] / Source / cmLocalGenerator.cxx
blob6e53d4fecc6f1d4d8e754111b7f68e5d77ba78b0
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-10-09 19:30:07 $
7 Version: $Revision: 1.286 $
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 "cmLocalGenerator.h"
19 #include "cmComputeLinkInformation.h"
20 #include "cmGeneratedFileStream.h"
21 #include "cmGlobalGenerator.h"
22 #include "cmInstallGenerator.h"
23 #include "cmInstallFilesGenerator.h"
24 #include "cmInstallScriptGenerator.h"
25 #include "cmInstallTargetGenerator.h"
26 #include "cmMakefile.h"
27 #include "cmSourceFile.h"
28 #include "cmTest.h"
29 #include "cmake.h"
31 #if defined(CMAKE_BUILD_WITH_CMAKE)
32 # define CM_LG_ENCODE_OBJECT_NAMES
33 # include <cmsys/MD5.h>
34 #endif
36 #include <cmsys/System.h>
38 #include <ctype.h> // for isalpha
40 #include <assert.h>
42 cmLocalGenerator::cmLocalGenerator()
44 this->Makefile = new cmMakefile;
45 this->Makefile->SetLocalGenerator(this);
46 this->Parent = 0;
47 this->WindowsShell = false;
48 this->WindowsVSIDE = false;
49 this->WatcomWMake = false;
50 this->MinGWMake = false;
51 this->NMake = false;
52 this->MSYSShell = false;
53 this->LinkScriptShell = false;
54 this->IgnoreLibPrefix = false;
55 this->UseRelativePaths = false;
56 this->Configured = false;
57 this->EmitUniversalBinaryFlags = true;
58 this->IsMakefileGenerator = false;
59 this->RelativePathsConfigured = false;
60 this->PathConversionsSetup = false;
61 this->BackwardsCompatibility = 0;
62 this->BackwardsCompatibilityFinal = false;
65 cmLocalGenerator::~cmLocalGenerator()
67 delete this->Makefile;
70 void cmLocalGenerator::Configure()
72 cmLocalGenerator* previousLg =
73 this->GetGlobalGenerator()->GetCurrentLocalGenerator();
74 this->GetGlobalGenerator()->SetCurrentLocalGenerator(this);
76 // make sure the CMakeFiles dir is there
77 std::string filesDir = this->Makefile->GetStartOutputDirectory();
78 filesDir += cmake::GetCMakeFilesDirectory();
79 cmSystemTools::MakeDirectory(filesDir.c_str());
81 // find & read the list file
82 std::string currentStart = this->Makefile->GetStartDirectory();
83 currentStart += "/CMakeLists.txt";
84 this->Makefile->ReadListFile(currentStart.c_str());
86 // at the end of the ReadListFile handle any old style subdirs
87 // first get all the subdirectories
88 std::vector<cmLocalGenerator *> subdirs = this->GetChildren();
90 // for each subdir recurse
91 std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
92 for (; sdi != subdirs.end(); ++sdi)
94 if (!(*sdi)->Configured)
96 this->Makefile->ConfigureSubDirectory(*sdi);
100 // Check whether relative paths should be used for optionally
101 // relative paths.
102 this->UseRelativePaths = this->Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
104 // Choose a maximum object file name length.
106 #if defined(_WIN32) || defined(__CYGWIN__)
107 this->ObjectPathMax = 250;
108 #else
109 this->ObjectPathMax = 1000;
110 #endif
111 const char* plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX");
112 if(plen && *plen)
114 unsigned int pmax;
115 if(sscanf(plen, "%u", &pmax) == 1)
117 if(pmax >= 128)
119 this->ObjectPathMax = pmax;
121 else
123 cmOStringStream w;
124 w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax
125 << ", which is less than the minimum of 128. "
126 << "The value will be ignored.";
127 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
130 else
132 cmOStringStream w;
133 w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen
134 << "\", which fails to parse as a positive integer. "
135 << "The value will be ignored.";
136 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
141 this->Configured = true;
143 this->GetGlobalGenerator()->SetCurrentLocalGenerator(previousLg);
146 void cmLocalGenerator::SetupPathConversions()
148 // Setup the current output directory components for use by
149 // Convert
150 std::string outdir;
151 outdir =
152 cmSystemTools::CollapseFullPath(this->Makefile->GetHomeDirectory());
153 cmSystemTools::SplitPath(outdir.c_str(), this->HomeDirectoryComponents);
154 outdir =
155 cmSystemTools::CollapseFullPath(this->Makefile->GetStartDirectory());
156 cmSystemTools::SplitPath(outdir.c_str(), this->StartDirectoryComponents);
158 outdir = cmSystemTools::CollapseFullPath
159 (this->Makefile->GetHomeOutputDirectory());
160 cmSystemTools::SplitPath(outdir.c_str(),
161 this->HomeOutputDirectoryComponents);
163 outdir = cmSystemTools::CollapseFullPath
164 (this->Makefile->GetStartOutputDirectory());
165 cmSystemTools::SplitPath(outdir.c_str(),
166 this->StartOutputDirectoryComponents);
170 void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
172 this->GlobalGenerator = gg;
174 // setup the home directories
175 this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance());
176 this->Makefile->SetHomeDirectory(
177 gg->GetCMakeInstance()->GetHomeDirectory());
178 this->Makefile->SetHomeOutputDirectory(
179 gg->GetCMakeInstance()->GetHomeOutputDirectory());
182 void cmLocalGenerator::ConfigureFinalPass()
184 this->Makefile->ConfigureFinalPass();
187 void cmLocalGenerator::TraceDependencies()
189 // Generate the rule files for each target.
190 cmTargets& targets = this->Makefile->GetTargets();
191 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
193 // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
194 // so don't build a projectfile for it
195 if (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
197 const char* projectFilename = 0;
198 if (this->IsMakefileGenerator == false) // only use of this variable
200 projectFilename = t->second.GetName();
202 t->second.TraceDependencies(projectFilename);
207 void cmLocalGenerator::GenerateTestFiles()
209 if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") )
211 return;
213 std::string file = this->Makefile->GetStartOutputDirectory();
214 file += "/";
215 file += "CTestTestfile.cmake";
217 cmGeneratedFileStream fout(file.c_str());
218 fout.SetCopyIfDifferent(true);
220 fout << "# CMake generated Testfile for " << std::endl
221 << "# Source directory: "
222 << this->Makefile->GetStartDirectory() << std::endl
223 << "# Build directory: "
224 << this->Makefile->GetStartOutputDirectory() << std::endl
225 << "# " << std::endl
226 << "# This file replicates the SUBDIRS() and ADD_TEST() commands "
227 << "from the source" << std::endl
228 << "# tree CMakeLists.txt file, skipping any SUBDIRS() or "
229 << "ADD_TEST() commands" << std::endl
230 << "# that are excluded by CMake control structures, i.e. IF() "
231 << "commands." << std::endl;
233 const char* testIncludeFile =
234 this->Makefile->GetProperty("TEST_INCLUDE_FILE");
235 if ( testIncludeFile )
237 fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
240 const std::vector<cmTest*> *tests = this->Makefile->GetTests();
241 std::vector<cmTest*>::const_iterator it;
242 for ( it = tests->begin(); it != tests->end(); ++ it )
244 cmTest* test = *it;
245 fout << "ADD_TEST(";
246 fout << test->GetName() << " \"" << test->GetCommand() << "\"";
248 std::vector<cmStdString>::const_iterator argit;
249 for (argit = test->GetArguments().begin();
250 argit != test->GetArguments().end(); ++argit)
252 // Just double-quote all arguments so they are re-parsed
253 // correctly by the test system.
254 fout << " \"";
255 for(std::string::const_iterator c = argit->begin();
256 c != argit->end(); ++c)
258 // Escape quotes within arguments. We should escape
259 // backslashes too but we cannot because it makes the result
260 // inconsistent with previous behavior of this command.
261 if((*c == '"'))
263 fout << '\\';
265 fout << *c;
267 fout << "\"";
269 fout << ")" << std::endl;
270 cmPropertyMap::const_iterator pit;
271 cmPropertyMap* mpit = &test->GetProperties();
272 if ( mpit->size() )
274 fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
275 for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
277 fout << " " << pit->first.c_str() << " \"";
278 const char* value = pit->second.GetValue();
279 for ( ; *value; ++ value )
281 switch ( *value )
283 case '\\':
284 case '"':
285 case ' ':
286 case '#':
287 case '(':
288 case ')':
289 case '$':
290 case '^':
291 fout << "\\" << *value;
292 break;
293 case '\t':
294 fout << "\\t";
295 break;
296 case '\n':
297 fout << "\\n";
298 break;
299 case '\r':
300 fout << "\\r";
301 break;
302 default:
303 fout << *value;
306 fout << "\"";
308 fout << ")" << std::endl;
311 if ( this->Children.size())
313 size_t i;
314 for(i = 0; i < this->Children.size(); ++i)
316 fout << "SUBDIRS(";
317 std::string outP =
318 this->Children[i]->GetMakefile()->GetStartOutputDirectory();
319 fout << this->Convert(outP.c_str(),START_OUTPUT);
320 fout << ")" << std::endl;
325 //----------------------------------------------------------------------------
326 void cmLocalGenerator::GenerateInstallRules()
328 // Compute the install prefix.
329 const char* prefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX");
330 #if defined(_WIN32) && !defined(__CYGWIN__)
331 std::string prefix_win32;
332 if(!prefix)
334 if(!cmSystemTools::GetEnv("SystemDrive", prefix_win32))
336 prefix_win32 = "C:";
338 const char* project_name = this->Makefile->GetDefinition("PROJECT_NAME");
339 if(project_name && project_name[0])
341 prefix_win32 += "/Program Files/";
342 prefix_win32 += project_name;
344 else
346 prefix_win32 += "/InstalledCMakeProject";
348 prefix = prefix_win32.c_str();
350 #else
351 if (!prefix)
353 prefix = "/usr/local";
355 #endif
357 // Compute the set of configurations.
358 std::vector<std::string> configurationTypes;
359 if(const char* types =
360 this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
362 cmSystemTools::ExpandListArgument(types, configurationTypes);
364 const char* config = 0;
365 if(configurationTypes.empty())
367 config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
370 // Choose a default install configuration.
371 const char* default_config = config;
372 const char* default_order[] = {"RELEASE", "MINSIZEREL",
373 "RELWITHDEBINFO", "DEBUG", 0};
374 for(const char** c = default_order; *c && !default_config; ++c)
376 for(std::vector<std::string>::iterator i = configurationTypes.begin();
377 i != configurationTypes.end(); ++i)
379 if(cmSystemTools::UpperCase(*i) == *c)
381 default_config = i->c_str();
385 if(!default_config && !configurationTypes.empty())
387 default_config = configurationTypes[0].c_str();
389 if(!default_config)
391 default_config = "Release";
394 // Create the install script file.
395 std::string file = this->Makefile->GetStartOutputDirectory();
396 std::string homedir = this->Makefile->GetHomeOutputDirectory();
397 std::string currdir = this->Makefile->GetCurrentOutputDirectory();
398 cmSystemTools::ConvertToUnixSlashes(file);
399 cmSystemTools::ConvertToUnixSlashes(homedir);
400 cmSystemTools::ConvertToUnixSlashes(currdir);
401 int toplevel_install = 0;
402 if ( currdir == homedir )
404 toplevel_install = 1;
406 file += "/cmake_install.cmake";
407 cmGeneratedFileStream fout(file.c_str());
408 fout.SetCopyIfDifferent(true);
410 // Write the header.
411 fout << "# Install script for directory: "
412 << this->Makefile->GetCurrentDirectory() << std::endl << std::endl;
413 fout << "# Set the install prefix" << std::endl
414 << "IF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
415 << " SET(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
416 << "ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
417 << "STRING(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
418 << "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
419 << std::endl;
421 // Write support code for generating per-configuration install rules.
422 fout <<
423 "# Set the install configuration name.\n"
424 "IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
425 " IF(BUILD_TYPE)\n"
426 " STRING(REGEX REPLACE \"^[^A-Za-z0-9_]+\" \"\"\n"
427 " CMAKE_INSTALL_CONFIG_NAME \"${BUILD_TYPE}\")\n"
428 " ELSE(BUILD_TYPE)\n"
429 " SET(CMAKE_INSTALL_CONFIG_NAME \"" << default_config << "\")\n"
430 " ENDIF(BUILD_TYPE)\n"
431 " MESSAGE(STATUS \"Install configuration: "
432 "\\\"${CMAKE_INSTALL_CONFIG_NAME}\\\"\")\n"
433 "ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
434 "\n";
436 // Write support code for dealing with component-specific installs.
437 fout <<
438 "# Set the component getting installed.\n"
439 "IF(NOT CMAKE_INSTALL_COMPONENT)\n"
440 " IF(COMPONENT)\n"
441 " MESSAGE(STATUS \"Install component: \\\"${COMPONENT}\\\"\")\n"
442 " SET(CMAKE_INSTALL_COMPONENT \"${COMPONENT}\")\n"
443 " ELSE(COMPONENT)\n"
444 " SET(CMAKE_INSTALL_COMPONENT)\n"
445 " ENDIF(COMPONENT)\n"
446 "ENDIF(NOT CMAKE_INSTALL_COMPONENT)\n"
447 "\n";
449 // Copy user-specified install options to the install code.
450 if(const char* so_no_exe =
451 this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE"))
453 fout <<
454 "# Install shared libraries without execute permission?\n"
455 "IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
456 " SET(CMAKE_INSTALL_SO_NO_EXE \"" << so_no_exe << "\")\n"
457 "ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
458 "\n";
461 // Ask each install generator to write its code.
462 std::vector<cmInstallGenerator*> const& installers =
463 this->Makefile->GetInstallGenerators();
464 for(std::vector<cmInstallGenerator*>::const_iterator
465 gi = installers.begin();
466 gi != installers.end(); ++gi)
468 (*gi)->Generate(fout, config, configurationTypes);
471 // Write rules from old-style specification stored in targets.
472 this->GenerateTargetInstallRules(fout, config, configurationTypes);
474 // Include install scripts from subdirectories.
475 if(!this->Children.empty())
477 fout << "IF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
478 fout << " # Include the install script for each subdirectory.\n";
479 for(std::vector<cmLocalGenerator*>::const_iterator
480 ci = this->Children.begin(); ci != this->Children.end(); ++ci)
482 if(!(*ci)->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
484 std::string odir = (*ci)->GetMakefile()->GetStartOutputDirectory();
485 cmSystemTools::ConvertToUnixSlashes(odir);
486 fout << " INCLUDE(\"" << odir.c_str()
487 << "/cmake_install.cmake\")" << std::endl;
490 fout << "\n";
491 fout << "ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n\n";
494 // Record the install manifest.
495 if ( toplevel_install )
497 fout <<
498 "IF(CMAKE_INSTALL_COMPONENT)\n"
499 " SET(CMAKE_INSTALL_MANIFEST \"install_manifest_"
500 "${CMAKE_INSTALL_COMPONENT}.txt\")\n"
501 "ELSE(CMAKE_INSTALL_COMPONENT)\n"
502 " SET(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
503 "ENDIF(CMAKE_INSTALL_COMPONENT)\n\n";
504 fout
505 << "FILE(WRITE \""
506 << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
507 << "\"\")" << std::endl;
508 fout
509 << "FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})" << std::endl
510 << " FILE(APPEND \""
511 << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
512 << "\"${file}\\n\")" << std::endl
513 << "ENDFOREACH(file)" << std::endl;
517 //----------------------------------------------------------------------------
518 void cmLocalGenerator::GenerateTargetManifest()
520 // Collect the set of configuration types.
521 std::vector<std::string> configNames;
522 if(const char* configurationTypes =
523 this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
525 cmSystemTools::ExpandListArgument(configurationTypes, configNames);
527 else if(const char* buildType =
528 this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"))
530 if(*buildType)
532 configNames.push_back(buildType);
536 // Add our targets to the manifest for each configuration.
537 cmTargets& targets = this->Makefile->GetTargets();
538 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
540 cmTarget& target = t->second;
541 if(configNames.empty())
543 target.GenerateTargetManifest(0);
545 else
547 for(std::vector<std::string>::iterator ci = configNames.begin();
548 ci != configNames.end(); ++ci)
550 const char* config = ci->c_str();
551 target.GenerateTargetManifest(config);
557 void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
558 const char* lang,
559 cmSourceFile& source,
560 cmTarget& )
562 std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname));
563 objectDir = this->Convert(objectDir.c_str(),START_OUTPUT,SHELL);
564 std::string objectFile = this->Convert(ofname,START_OUTPUT,SHELL);
565 std::string sourceFile =
566 this->Convert(source.GetFullPath().c_str(),START_OUTPUT,SHELL,true);
567 std::string varString = "CMAKE_";
568 varString += lang;
569 varString += "_COMPILE_OBJECT";
570 std::vector<std::string> rules;
571 rules.push_back(this->Makefile->GetRequiredDefinition(varString.c_str()));
572 varString = "CMAKE_";
573 varString += lang;
574 varString += "_FLAGS";
575 std::string flags;
576 flags += this->Makefile->GetSafeDefinition(varString.c_str());
577 flags += " ";
578 flags += this->GetIncludeFlags(lang);
580 // Construct the command lines.
581 cmCustomCommandLines commandLines;
582 std::vector<std::string> commands;
583 cmSystemTools::ExpandList(rules, commands);
584 cmLocalGenerator::RuleVariables vars;
585 vars.Language = lang;
586 vars.Source = sourceFile.c_str();
587 vars.Object = objectFile.c_str();
588 vars.ObjectDir = objectDir.c_str();
589 vars.Flags = flags.c_str();
590 for(std::vector<std::string>::iterator i = commands.begin();
591 i != commands.end(); ++i)
593 // Expand the full command line string.
594 this->ExpandRuleVariables(*i, vars);
596 // Parse the string to get the custom command line.
597 cmCustomCommandLine commandLine;
598 std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
599 for(std::vector<cmStdString>::iterator a = cmd.begin();
600 a != cmd.end(); ++a)
602 commandLine.push_back(*a);
605 // Store this command line.
606 commandLines.push_back(commandLine);
609 // Check for extra object-file dependencies.
610 std::vector<std::string> depends;
611 const char* additionalDeps = source.GetProperty("OBJECT_DEPENDS");
612 if(additionalDeps)
614 cmSystemTools::ExpandListArgument(additionalDeps, depends);
617 // Generate a meaningful comment for the command.
618 std::string comment = "Building ";
619 comment += lang;
620 comment += " object ";
621 comment += this->Convert(ofname, START_OUTPUT);
623 // Add the custom command to build the object file.
624 this->Makefile->AddCustomCommandToOutput(
625 ofname,
626 depends,
627 source.GetFullPath().c_str(),
628 commandLines,
629 comment.c_str(),
630 this->Makefile->GetStartOutputDirectory()
634 void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target)
636 cmStdString objs;
637 std::vector<std::string> objVector;
638 // Add all the sources outputs to the depends of the target
639 std::vector<cmSourceFile*> const& classes = target.GetSourceFiles();
640 for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
641 i != classes.end(); ++i)
643 cmSourceFile* sf = *i;
644 if(!sf->GetCustomCommand() &&
645 !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
646 !sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
648 std::string::size_type dir_len = 0;
649 dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
650 dir_len += 1;
651 std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_len);
652 if(!obj.empty())
654 std::string ofname = this->Makefile->GetCurrentOutputDirectory();
655 ofname += "/";
656 ofname += obj;
657 objVector.push_back(ofname);
658 this->AddCustomCommandToCreateObject(ofname.c_str(),
659 llang, *(*i), target);
660 objs += this->Convert(ofname.c_str(),START_OUTPUT,MAKEFILE);
661 objs += " ";
665 std::string createRule = "CMAKE_";
666 createRule += llang;
667 createRule += target.GetCreateRuleVariable();
668 std::string targetName = target.GetFullName();
669 // Executable :
670 // Shared Library:
671 // Static Library:
672 // Shared Module:
673 std::string linkLibs; // should be set
674 std::string flags; // should be set
675 std::string linkFlags; // should be set
676 this->GetTargetFlags(linkLibs, flags, linkFlags, target);
677 cmLocalGenerator::RuleVariables vars;
678 vars.Language = llang;
679 vars.Objects = objs.c_str();
680 vars.ObjectDir = ".";
681 vars.Target = targetName.c_str();
682 vars.LinkLibraries = linkLibs.c_str();
683 vars.Flags = flags.c_str();
684 vars.LinkFlags = linkFlags.c_str();
686 std::string langFlags;
687 this->AddLanguageFlags(langFlags, llang, 0);
688 vars.LanguageCompileFlags = langFlags.c_str();
690 cmCustomCommandLines commandLines;
691 std::vector<std::string> rules;
692 rules.push_back(this->Makefile->GetRequiredDefinition(createRule.c_str()));
693 std::vector<std::string> commands;
694 cmSystemTools::ExpandList(rules, commands);
695 for(std::vector<std::string>::iterator i = commands.begin();
696 i != commands.end(); ++i)
698 // Expand the full command line string.
699 this->ExpandRuleVariables(*i, vars);
700 // Parse the string to get the custom command line.
701 cmCustomCommandLine commandLine;
702 std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
703 for(std::vector<cmStdString>::iterator a = cmd.begin();
704 a != cmd.end(); ++a)
706 commandLine.push_back(*a);
709 // Store this command line.
710 commandLines.push_back(commandLine);
712 std::string targetFullPath = target.GetFullPath();
713 // Generate a meaningful comment for the command.
714 std::string comment = "Linking ";
715 comment += llang;
716 comment += " target ";
717 comment += this->Convert(targetFullPath.c_str(), START_OUTPUT);
718 this->Makefile->AddCustomCommandToOutput(
719 targetFullPath.c_str(),
720 objVector,
722 commandLines,
723 comment.c_str(),
724 this->Makefile->GetStartOutputDirectory()
726 target.AddSourceFile
727 (this->Makefile->GetSource(targetFullPath.c_str()));
731 void cmLocalGenerator
732 ::CreateCustomTargetsAndCommands(std::set<cmStdString> const& lang)
734 cmTargets &tgts = this->Makefile->GetTargets();
735 for(cmTargets::iterator l = tgts.begin();
736 l != tgts.end(); l++)
738 cmTarget& target = l->second;
739 switch(target.GetType())
741 case cmTarget::STATIC_LIBRARY:
742 case cmTarget::SHARED_LIBRARY:
743 case cmTarget::MODULE_LIBRARY:
744 case cmTarget::EXECUTABLE:
746 const char* llang =
747 target.GetLinkerLanguage(this->GetGlobalGenerator());
748 if(!llang)
750 cmSystemTools::Error
751 ("CMake can not determine linker language for target:",
752 target.GetName());
753 return;
755 // if the language is not in the set lang then create custom
756 // commands to build the target
757 if(lang.count(llang) == 0)
759 this->AddBuildTargetRule(llang, target);
762 break;
763 default:
764 break;
769 // List of variables that are replaced when
770 // rules are expanced. These variables are
771 // replaced in the form <var> with GetSafeDefinition(var).
772 // ${LANG} is replaced in the variable first with all enabled
773 // languages.
774 static const char* ruleReplaceVars[] =
776 "CMAKE_${LANG}_COMPILER",
777 "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
778 "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
779 "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
780 "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
781 "CMAKE_${LANG}_LINK_FLAGS",
782 "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
783 "CMAKE_${LANG}_ARCHIVE",
784 "CMAKE_AR",
785 "CMAKE_CURRENT_SOURCE_DIR",
786 "CMAKE_CURRENT_BINARY_DIR",
787 "CMAKE_RANLIB",
788 "CMAKE_LINKER",
792 std::string
793 cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
794 const RuleVariables& replaceValues)
796 if(replaceValues.LinkFlags)
798 if(variable == "LINK_FLAGS")
800 return replaceValues.LinkFlags;
803 if(replaceValues.Flags)
805 if(variable == "FLAGS")
807 return replaceValues.Flags;
811 if(replaceValues.Source)
813 if(variable == "SOURCE")
815 return replaceValues.Source;
818 if(replaceValues.PreprocessedSource)
820 if(variable == "PREPROCESSED_SOURCE")
822 return replaceValues.PreprocessedSource;
825 if(replaceValues.AssemblySource)
827 if(variable == "ASSEMBLY_SOURCE")
829 return replaceValues.AssemblySource;
832 if(replaceValues.Object)
834 if(variable == "OBJECT")
836 return replaceValues.Object;
839 if(replaceValues.ObjectDir)
841 if(variable == "OBJECT_DIR")
843 return replaceValues.ObjectDir;
846 if(replaceValues.Objects)
848 if(variable == "OBJECTS")
850 return replaceValues.Objects;
853 if(replaceValues.ObjectsQuoted)
855 if(variable == "OBJECTS_QUOTED")
857 return replaceValues.ObjectsQuoted;
860 if(replaceValues.Defines && variable == "DEFINES")
862 return replaceValues.Defines;
864 if(replaceValues.TargetPDB )
866 if(variable == "TARGET_PDB")
868 return replaceValues.TargetPDB;
872 if(replaceValues.Target)
874 if(variable == "TARGET_QUOTED")
876 std::string targetQuoted = replaceValues.Target;
877 if(targetQuoted.size() && targetQuoted[0] != '\"')
879 targetQuoted = '\"';
880 targetQuoted += replaceValues.Target;
881 targetQuoted += '\"';
883 return targetQuoted;
885 if(replaceValues.LanguageCompileFlags)
887 if(variable == "LANGUAGE_COMPILE_FLAGS")
889 return replaceValues.LanguageCompileFlags;
892 if(replaceValues.Target)
894 if(variable == "TARGET")
896 return replaceValues.Target;
899 if(variable == "TARGET_IMPLIB")
901 return this->TargetImplib;
903 if(variable == "TARGET_VERSION_MAJOR")
905 if(replaceValues.TargetVersionMajor)
907 return replaceValues.TargetVersionMajor;
909 else
911 return "0";
914 if(variable == "TARGET_VERSION_MINOR")
916 if(replaceValues.TargetVersionMinor)
918 return replaceValues.TargetVersionMinor;
920 else
922 return "0";
925 if(replaceValues.Target)
927 if(variable == "TARGET_BASE")
929 // Strip the last extension off the target name.
930 std::string targetBase = replaceValues.Target;
931 std::string::size_type pos = targetBase.rfind(".");
932 if(pos != targetBase.npos)
934 return targetBase.substr(0, pos);
936 else
938 return targetBase;
943 if(replaceValues.TargetSOName)
945 if(variable == "TARGET_SONAME")
947 if(replaceValues.Language)
949 std::string name = "CMAKE_SHARED_LIBRARY_SONAME_";
950 name += replaceValues.Language;
951 name += "_FLAG";
952 if(this->Makefile->GetDefinition(name.c_str()))
954 return replaceValues.TargetSOName;
957 return "";
960 if(replaceValues.TargetInstallNameDir)
962 if(variable == "TARGET_INSTALLNAME_DIR")
964 return replaceValues.TargetInstallNameDir;
967 if(replaceValues.LinkLibraries)
969 if(variable == "LINK_LIBRARIES")
971 return replaceValues.LinkLibraries;
974 if(variable == "CMAKE_COMMAND")
976 const char* cmcommand =
977 this->GetMakefile()->GetDefinition("CMAKE_COMMAND");
978 return this->Convert(cmcommand, FULL, SHELL);
980 std::vector<std::string> enabledLanguages;
981 this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
982 // loop over language specific replace variables
983 int pos = 0;
984 while(ruleReplaceVars[pos])
986 for(std::vector<std::string>::iterator i = enabledLanguages.begin();
987 i != enabledLanguages.end(); ++i)
989 const char* lang = i->c_str();
990 std::string actualReplace = ruleReplaceVars[pos];
991 // If this is the compiler then look for the extra variable
992 // _COMPILER_ARG1 which must be the first argument to the compiler
993 const char* compilerArg1 = 0;
994 if(actualReplace == "CMAKE_${LANG}_COMPILER")
996 std::string arg1 = actualReplace + "_ARG1";
997 cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
998 compilerArg1 = this->Makefile->GetDefinition(arg1.c_str());
1000 if(actualReplace.find("${LANG}") != actualReplace.npos)
1002 cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
1004 if(actualReplace == variable)
1006 std::string replace =
1007 this->Makefile->GetSafeDefinition(variable.c_str());
1008 // if the variable is not a FLAG then treat it like a path
1009 if(variable.find("_FLAG") == variable.npos)
1011 std::string ret = this->ConvertToOutputForExisting(replace.c_str());
1012 // if there is a required first argument to the compiler add it
1013 // to the compiler string
1014 if(compilerArg1)
1016 ret += " ";
1017 ret += compilerArg1;
1019 return ret;
1021 return replace;
1024 pos++;
1026 return variable;
1030 void
1031 cmLocalGenerator::ExpandRuleVariables(std::string& s,
1032 const RuleVariables& replaceValues)
1034 std::vector<std::string> enabledLanguages;
1035 this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
1036 std::string::size_type start = s.find('<');
1037 // no variables to expand
1038 if(start == s.npos)
1040 return;
1042 std::string::size_type pos = 0;
1043 std::string expandedInput;
1044 while(start != s.npos && start < s.size()-2)
1046 std::string::size_type end = s.find('>', start);
1047 // if we find a < with no > we are done
1048 if(end == s.npos)
1050 return;
1052 char c = s[start+1];
1053 // if the next char after the < is not A-Za-z then
1054 // skip it and try to find the next < in the string
1055 if(!isalpha(c))
1057 start = s.find('<', start+1);
1059 else
1061 // extract the var
1062 std::string var = s.substr(start+1, end - start-1);
1063 std::string replace = this->ExpandRuleVariable(var,
1064 replaceValues);
1065 expandedInput += s.substr(pos, start-pos);
1066 expandedInput += replace;
1067 // move to next one
1068 start = s.find('<', start+var.size()+2);
1069 pos = end+1;
1072 // add the rest of the input
1073 expandedInput += s.substr(pos, s.size()-pos);
1074 s = expandedInput;
1077 //----------------------------------------------------------------------------
1078 std::string
1079 cmLocalGenerator::ConvertToOutputForExistingCommon(const char* remote,
1080 std::string const& result)
1082 // If this is a windows shell, the result has a space, and the path
1083 // already exists, we can use a short-path to reference it without a
1084 // space.
1085 if(this->WindowsShell && result.find(' ') != result.npos &&
1086 cmSystemTools::FileExists(remote))
1088 std::string tmp;
1089 if(cmSystemTools::GetShortPath(remote, tmp))
1091 return this->Convert(tmp.c_str(), NONE, SHELL, true);
1095 // Otherwise, leave it unchanged.
1096 return result;
1099 //----------------------------------------------------------------------------
1100 std::string
1101 cmLocalGenerator::ConvertToOutputForExisting(const char* remote,
1102 RelativeRoot local)
1104 // Perform standard conversion.
1105 std::string result = this->Convert(remote, local, SHELL, true);
1107 // Consider short-path.
1108 return this->ConvertToOutputForExistingCommon(remote, result);
1111 //----------------------------------------------------------------------------
1112 std::string
1113 cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote,
1114 const char* local)
1116 // Perform standard conversion.
1117 std::string result = this->Convert(remote, local, SHELL, true);
1119 // Consider short-path.
1120 const char* remotePath = this->GetRelativeRootPath(remote);
1121 return this->ConvertToOutputForExistingCommon(remotePath, result);
1124 //----------------------------------------------------------------------------
1125 const char* cmLocalGenerator::GetIncludeFlags(const char* lang)
1127 if(!lang)
1129 return "";
1131 if(this->LanguageToIncludeFlags.count(lang))
1133 return this->LanguageToIncludeFlags[lang].c_str();
1135 cmOStringStream includeFlags;
1136 std::vector<std::string> includes;
1137 this->GetIncludeDirectories(includes);
1138 std::vector<std::string>::iterator i;
1140 std::string flagVar = "CMAKE_INCLUDE_FLAG_";
1141 flagVar += lang;
1142 const char* includeFlag =
1143 this->Makefile->GetSafeDefinition(flagVar.c_str());
1144 flagVar = "CMAKE_INCLUDE_FLAG_SEP_";
1145 flagVar += lang;
1146 const char* sep = this->Makefile->GetDefinition(flagVar.c_str());
1147 bool quotePaths = false;
1148 if(this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS"))
1150 quotePaths = true;
1152 bool repeatFlag = true;
1153 // should the include flag be repeated like ie. -IA -IB
1154 if(!sep)
1156 sep = " ";
1158 else
1160 // if there is a separator then the flag is not repeated but is only
1161 // given once i.e. -classpath a:b:c
1162 repeatFlag = false;
1165 // Support special system include flag if it is available and the
1166 // normal flag is repeated for each directory.
1167 std::string sysFlagVar = "CMAKE_INCLUDE_SYSTEM_FLAG_";
1168 sysFlagVar += lang;
1169 const char* sysIncludeFlag = 0;
1170 if(repeatFlag)
1172 sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar.c_str());
1175 bool flagUsed = false;
1176 std::set<cmStdString> emitted;
1177 #ifdef __APPLE__
1178 emitted.insert("/System/Library/Frameworks");
1179 #endif
1180 for(i = includes.begin(); i != includes.end(); ++i)
1182 #ifdef __APPLE__
1183 if(cmSystemTools::IsPathToFramework(i->c_str()))
1185 std::string frameworkDir = *i;
1186 frameworkDir += "/../";
1187 frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1188 if(emitted.insert(frameworkDir).second)
1190 includeFlags
1191 << "-F" << this->Convert(frameworkDir.c_str(),
1192 cmLocalGenerator::START_OUTPUT,
1193 cmLocalGenerator::SHELL, true)
1194 << " ";
1196 continue;
1198 #endif
1199 std::string include = *i;
1200 if(!flagUsed || repeatFlag)
1202 if(sysIncludeFlag &&
1203 this->Makefile->IsSystemIncludeDirectory(i->c_str()))
1205 includeFlags << sysIncludeFlag;
1207 else
1209 includeFlags << includeFlag;
1211 flagUsed = true;
1213 std::string includePath = this->ConvertToOutputForExisting(i->c_str());
1214 if(quotePaths && includePath.size() && includePath[0] != '\"')
1216 includeFlags << "\"";
1218 includeFlags << includePath;
1219 if(quotePaths && includePath.size() && includePath[0] != '\"')
1221 includeFlags << "\"";
1223 includeFlags << sep;
1225 std::string flags = includeFlags.str();
1226 // remove trailing separators
1227 if((sep[0] != ' ') && flags[flags.size()-1] == sep[0])
1229 flags[flags.size()-1] = ' ';
1231 std::string defineFlags = this->Makefile->GetDefineFlags();
1232 flags += defineFlags;
1233 this->LanguageToIncludeFlags[lang] = flags;
1235 // Use this temorary variable for the return value to work-around a
1236 // bogus GCC 2.95 warning.
1237 const char* ret = this->LanguageToIncludeFlags[lang].c_str();
1238 return ret;
1241 //----------------------------------------------------------------------------
1242 void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
1243 bool filter_system_dirs)
1245 // Need to decide whether to automatically include the source and
1246 // binary directories at the beginning of the include path.
1247 bool includeSourceDir = false;
1248 bool includeBinaryDir = false;
1250 // When automatic include directories are requested for a build then
1251 // include the source and binary directories at the beginning of the
1252 // include path to approximate include file behavior for an
1253 // in-source build. This does not account for the case of a source
1254 // file in a subdirectory of the current source directory but we
1255 // cannot fix this because not all native build tools support
1256 // per-source-file include paths.
1257 if(this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR"))
1259 includeSourceDir = true;
1260 includeBinaryDir = true;
1263 // CMake versions below 2.0 would add the source tree to the -I path
1264 // automatically. Preserve compatibility.
1265 if(this->NeedBackwardsCompatibility(1,9))
1267 includeSourceDir = true;
1270 // Hack for VTK 4.0 - 4.4 which depend on the old behavior but do
1271 // not set the backwards compatibility level automatically.
1272 const char* vtkSourceDir =
1273 this->Makefile->GetDefinition("VTK_SOURCE_DIR");
1274 if(vtkSourceDir)
1276 const char* vtk_major =
1277 this->Makefile->GetDefinition("VTK_MAJOR_VERSION");
1278 const char* vtk_minor =
1279 this->Makefile->GetDefinition("VTK_MINOR_VERSION");
1280 vtk_major = vtk_major? vtk_major : "4";
1281 vtk_minor = vtk_minor? vtk_minor : "4";
1282 int vmajor = 0;
1283 int vminor = 0;
1284 if(sscanf(vtk_major, "%d", &vmajor) &&
1285 sscanf(vtk_minor, "%d", &vminor) && vmajor == 4 && vminor <= 4)
1287 includeSourceDir = true;
1291 // Do not repeat an include path.
1292 std::set<cmStdString> emitted;
1294 // Store the automatic include paths.
1295 if(includeBinaryDir)
1297 dirs.push_back(this->Makefile->GetStartOutputDirectory());
1298 emitted.insert(this->Makefile->GetStartOutputDirectory());
1300 if(includeSourceDir)
1302 if(emitted.find(this->Makefile->GetStartDirectory()) == emitted.end())
1304 dirs.push_back(this->Makefile->GetStartDirectory());
1305 emitted.insert(this->Makefile->GetStartDirectory());
1309 if(filter_system_dirs)
1311 // Do not explicitly add the standard include path "/usr/include".
1312 // This can cause problems with certain standard library
1313 // implementations because the wrong headers may be found first.
1314 emitted.insert("/usr/include");
1315 if(const char* implicitIncludes = this->Makefile->GetDefinition
1316 ("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES"))
1318 std::vector<std::string> implicitIncludeVec;
1319 cmSystemTools::ExpandListArgument(implicitIncludes, implicitIncludeVec);
1320 for(unsigned int k = 0; k < implicitIncludeVec.size(); ++k)
1322 emitted.insert(implicitIncludeVec[k]);
1327 // Get the project-specified include directories.
1328 std::vector<std::string>& includes =
1329 this->Makefile->GetIncludeDirectories();
1331 // Support putting all the in-project include directories first if
1332 // it is requested by the project.
1333 if(this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"))
1335 const char* topSourceDir = this->Makefile->GetHomeDirectory();
1336 const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
1337 for(std::vector<std::string>::iterator i = includes.begin();
1338 i != includes.end(); ++i)
1340 // Emit this directory only if it is a subdirectory of the
1341 // top-level source or binary tree.
1342 if(cmSystemTools::ComparePath(i->c_str(), topSourceDir) ||
1343 cmSystemTools::ComparePath(i->c_str(), topBinaryDir) ||
1344 cmSystemTools::IsSubDirectory(i->c_str(), topSourceDir) ||
1345 cmSystemTools::IsSubDirectory(i->c_str(), topBinaryDir))
1347 if(emitted.insert(*i).second)
1349 dirs.push_back(*i);
1355 // Construct the final ordered include directory list.
1356 for(std::vector<std::string>::iterator i = includes.begin();
1357 i != includes.end(); ++i)
1359 if(emitted.insert(*i).second)
1361 dirs.push_back(*i);
1366 void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
1367 std::string& flags,
1368 std::string& linkFlags,
1369 cmTarget& target)
1371 std::string buildType =
1372 this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
1373 buildType = cmSystemTools::UpperCase(buildType);
1374 const char* libraryLinkVariable =
1375 "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
1377 switch(target.GetType())
1379 case cmTarget::STATIC_LIBRARY:
1381 const char* targetLinkFlags =
1382 target.GetProperty("STATIC_LIBRARY_FLAGS");
1383 if(targetLinkFlags)
1385 linkFlags += targetLinkFlags;
1386 linkFlags += " ";
1389 break;
1390 case cmTarget::MODULE_LIBRARY:
1391 libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
1392 case cmTarget::SHARED_LIBRARY:
1394 linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
1395 linkFlags += " ";
1396 if(buildType.size())
1398 std::string build = libraryLinkVariable;
1399 build += "_";
1400 build += buildType;
1401 linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
1402 linkFlags += " ";
1404 if(this->Makefile->IsOn("WIN32") &&
1405 !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
1407 const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
1408 for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
1409 i != sources.end(); ++i)
1411 cmSourceFile* sf = *i;
1412 if(sf->GetExtension() == "def")
1414 linkFlags +=
1415 this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
1416 linkFlags += this->Convert(sf->GetFullPath().c_str(),
1417 START_OUTPUT, SHELL);
1418 linkFlags += " ";
1422 const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
1423 if(targetLinkFlags)
1425 linkFlags += targetLinkFlags;
1426 linkFlags += " ";
1427 std::string configLinkFlags = targetLinkFlags;
1428 configLinkFlags += buildType;
1429 targetLinkFlags = target.GetProperty(configLinkFlags.c_str());
1430 if(targetLinkFlags)
1432 linkFlags += targetLinkFlags;
1433 linkFlags += " ";
1436 cmOStringStream linklibsStr;
1437 this->OutputLinkLibraries(linklibsStr, target, false);
1438 linkLibs = linklibsStr.str();
1440 break;
1441 case cmTarget::EXECUTABLE:
1443 linkFlags +=
1444 this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
1445 linkFlags += " ";
1446 if(buildType.size())
1448 std::string build = "CMAKE_EXE_LINKER_FLAGS_";
1449 build += buildType;
1450 linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
1451 linkFlags += " ";
1453 const char* linkLanguage =
1454 target.GetLinkerLanguage(this->GetGlobalGenerator());
1455 if(!linkLanguage)
1457 cmSystemTools::Error
1458 ("CMake can not determine linker language for target:",
1459 target.GetName());
1460 return;
1462 std::string langVar = "CMAKE_";
1463 langVar += linkLanguage;
1464 std::string flagsVar = langVar + "_FLAGS";
1465 std::string sharedFlagsVar = "CMAKE_SHARED_LIBRARY_";
1466 sharedFlagsVar += linkLanguage;
1467 sharedFlagsVar += "_FLAGS";
1468 flags += this->Makefile->GetSafeDefinition(flagsVar.c_str());
1469 flags += " ";
1470 flags += this->Makefile->GetSafeDefinition(sharedFlagsVar.c_str());
1471 flags += " ";
1472 cmOStringStream linklibs;
1473 this->OutputLinkLibraries(linklibs, target, false);
1474 linkLibs = linklibs.str();
1475 if(cmSystemTools::IsOn
1476 (this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
1478 std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_")
1479 + linkLanguage + std::string("_FLAGS");
1480 linkFlags += this->Makefile->GetSafeDefinition(sFlagVar.c_str());
1481 linkFlags += " ";
1483 if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
1485 linkFlags +=
1486 this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
1487 linkFlags += " ";
1489 else
1491 linkFlags +=
1492 this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
1493 linkFlags += " ";
1495 const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
1496 if(targetLinkFlags)
1498 linkFlags += targetLinkFlags;
1499 linkFlags += " ";
1500 std::string configLinkFlags = targetLinkFlags;
1501 configLinkFlags += buildType;
1502 targetLinkFlags = target.GetProperty(configLinkFlags.c_str());
1503 if(targetLinkFlags)
1505 linkFlags += targetLinkFlags;
1506 linkFlags += " ";
1510 break;
1511 default:
1512 break;
1516 std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
1518 #if defined(_WIN32) && !defined(__CYGWIN__)
1519 // Work-ardound command line parsing limitations in MSVC 6.0 and
1520 // Watcom.
1521 if(this->Makefile->IsOn("MSVC60") || this->Makefile->IsOn("WATCOM"))
1523 // Search for the last space.
1524 std::string::size_type pos = lib.rfind(' ');
1525 if(pos != lib.npos)
1527 // Find the slash after the last space, if any.
1528 pos = lib.find('/', pos);
1530 // Convert the portion of the path with a space to a short path.
1531 std::string sp;
1532 if(cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp))
1534 // Append the rest of the path with no space.
1535 sp += lib.substr(pos);
1537 // Convert to an output path.
1538 return this->Convert(sp.c_str(), NONE, SHELL);
1542 #endif
1544 // Normal behavior.
1545 return this->Convert(lib.c_str(), START_OUTPUT, SHELL);
1549 * Output the linking rules on a command line. For executables,
1550 * targetLibrary should be a NULL pointer. For libraries, it should point
1551 * to the name of the library. This will not link a library against itself.
1553 void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
1554 cmTarget& tgt,
1555 bool relink)
1557 const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
1558 cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
1559 if(!pcli)
1561 return;
1563 cmComputeLinkInformation& cli = *pcli;
1565 // Collect library linking flags command line options.
1566 std::string linkLibs;
1568 const char* linkLanguage = cli.GetLinkLanguage();
1570 std::string libPathFlag =
1571 this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
1572 std::string libPathTerminator =
1573 this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
1575 // Flags to link an executable to shared libraries.
1576 std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
1577 linkFlagsVar += linkLanguage;
1578 linkFlagsVar += "_FLAGS";
1579 if( tgt.GetType() == cmTarget::EXECUTABLE )
1581 linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar.c_str());
1582 linkLibs += " ";
1585 // Append the framework search path flags.
1586 std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
1587 for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
1588 fdi != fwDirs.end(); ++fdi)
1590 linkLibs += "-F";
1591 linkLibs += this->Convert(fdi->c_str(), NONE, SHELL, false);
1592 linkLibs += " ";
1595 // Append the library search path flags.
1596 std::vector<std::string> const& libDirs = cli.GetDirectories();
1597 for(std::vector<std::string>::const_iterator libDir = libDirs.begin();
1598 libDir != libDirs.end(); ++libDir)
1600 std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
1601 linkLibs += libPathFlag;
1602 linkLibs += libpath;
1603 linkLibs += libPathTerminator;
1604 linkLibs += " ";
1607 // Append the link items.
1608 typedef cmComputeLinkInformation::ItemVector ItemVector;
1609 ItemVector const& items = cli.GetItems();
1610 for(ItemVector::const_iterator li = items.begin(); li != items.end(); ++li)
1612 if(li->IsPath)
1614 linkLibs += this->ConvertToLinkReference(li->Value);
1616 else
1618 linkLibs += li->Value;
1620 linkLibs += " ";
1623 // Write the library flags to the build rule.
1624 fout << linkLibs;
1626 // Get the RPATH entries.
1627 std::vector<std::string> runtimeDirs;
1628 cli.GetRPath(runtimeDirs, relink);
1630 // Check what kind of rpath flags to use.
1631 if(cli.GetRuntimeSep().empty())
1633 // Each rpath entry gets its own option ("-R a -R b -R c")
1634 std::string rpath;
1635 for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
1636 ri != runtimeDirs.end(); ++ri)
1638 rpath += cli.GetRuntimeFlag();
1639 rpath += this->Convert(ri->c_str(), NONE, SHELL, false);
1640 rpath += " ";
1642 fout << rpath;
1644 else
1646 // All rpath entries are combined ("-Wl,-rpath,a:b:c").
1647 std::string rpath = cli.GetRPathString(relink);
1649 // Store the rpath option in the stream.
1650 if(!rpath.empty())
1652 fout << cli.GetRuntimeFlag();
1653 fout << this->EscapeForShell(rpath.c_str(), true);
1654 fout << " ";
1658 // Add the linker runtime search path if any.
1659 std::string rpath_link = cli.GetRPathLinkString();
1660 if(!cli.GetRPathLinkFlag().empty() && !rpath_link.empty())
1662 fout << cli.GetRPathLinkFlag();
1663 fout << this->EscapeForShell(rpath_link.c_str(), true);
1664 fout << " ";
1667 // Add standard libraries for this language.
1668 std::string standardLibsVar = "CMAKE_";
1669 standardLibsVar += cli.GetLinkLanguage();
1670 standardLibsVar += "_STANDARD_LIBRARIES";
1671 if(const char* stdLibs =
1672 this->Makefile->GetDefinition(standardLibsVar.c_str()))
1674 fout << stdLibs << " ";
1678 //----------------------------------------------------------------------------
1679 void cmLocalGenerator::AddLanguageFlags(std::string& flags,
1680 const char* lang,
1681 const char* config)
1683 // Add language-specific flags.
1684 std::string flagsVar = "CMAKE_";
1685 flagsVar += lang;
1686 flagsVar += "_FLAGS";
1687 if(this->EmitUniversalBinaryFlags)
1689 const char* osxArch =
1690 this->Makefile->GetDefinition("CMAKE_OSX_ARCHITECTURES");
1691 const char* sysroot =
1692 this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
1693 const char* sysrootDefault =
1694 this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
1695 bool flagsUsed = false;
1696 if(osxArch && sysroot && lang && (lang[0] =='C' || lang[0] == 'F'))
1698 std::vector<std::string> archs;
1699 cmSystemTools::ExpandListArgument(std::string(osxArch),
1700 archs);
1701 bool addArchFlag = true;
1702 if(archs.size() == 1)
1704 const char* archOrig =
1705 this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
1706 if(archs[0] == archOrig)
1708 addArchFlag = false;
1711 // if there is more than one arch add the -arch and
1712 // -isysroot flags, or if there is one arch flag, but
1713 // it is not the default -arch flag for the system, then
1714 // add it. Otherwize do not add -arch and -isysroot
1715 if(addArchFlag)
1717 for( std::vector<std::string>::iterator i = archs.begin();
1718 i != archs.end(); ++i)
1720 flags += " -arch ";
1721 flags += *i;
1723 flags += " -isysroot ";
1724 flags += sysroot;
1725 flagsUsed = true;
1728 if(!flagsUsed && sysroot && sysrootDefault &&
1729 strcmp(sysroot, sysrootDefault) != 0)
1731 flags += " -isysroot ";
1732 flags += sysroot;
1735 this->AddConfigVariableFlags(flags, flagsVar.c_str(), config);
1738 //----------------------------------------------------------------------------
1739 std::string cmLocalGenerator::GetRealDependency(const char* inName,
1740 const char* config)
1742 // Older CMake code may specify the dependency using the target
1743 // output file rather than the target name. Such code would have
1744 // been written before there was support for target properties that
1745 // modify the name so stripping down to just the file name should
1746 // produce the target name in this case.
1747 std::string name = cmSystemTools::GetFilenameName(inName);
1748 if(cmSystemTools::GetFilenameLastExtension(name) == ".exe")
1750 name = cmSystemTools::GetFilenameWithoutLastExtension(name);
1753 // Look for a CMake target with the given name.
1754 if(cmTarget* target = this->Makefile->FindTargetToUse(name.c_str()))
1756 // make sure it is not just a coincidence that the target name
1757 // found is part of the inName
1758 if(cmSystemTools::FileIsFullPath(inName))
1760 std::string tLocation = target->GetLocation(config);
1761 tLocation = cmSystemTools::GetFilenamePath(tLocation);
1762 std::string depLocation = cmSystemTools::GetFilenamePath(
1763 std::string(inName));
1764 depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
1765 tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
1766 if(depLocation != tLocation)
1768 // it is a full path to a depend that has the same name
1769 // as a target but is in a different location so do not use
1770 // the target as the depend
1771 return inName;
1774 switch (target->GetType())
1776 case cmTarget::EXECUTABLE:
1777 case cmTarget::STATIC_LIBRARY:
1778 case cmTarget::SHARED_LIBRARY:
1779 case cmTarget::MODULE_LIBRARY:
1780 case cmTarget::UNKNOWN_LIBRARY:
1782 // Get the location of the target's output file and depend on it.
1783 if(const char* location = target->GetLocation(config))
1785 return location;
1788 break;
1789 case cmTarget::UTILITY:
1790 case cmTarget::GLOBAL_TARGET:
1791 // Depending on a utility target may not work but just trust
1792 // the user to have given a valid name.
1793 return inName;
1794 case cmTarget::INSTALL_FILES:
1795 case cmTarget::INSTALL_PROGRAMS:
1796 case cmTarget::INSTALL_DIRECTORY:
1797 break;
1801 // The name was not that of a CMake target. It must name a file.
1802 if(cmSystemTools::FileIsFullPath(inName))
1804 // This is a full path. Return it as given.
1805 return inName;
1808 // Check for a source file in this directory that matches the
1809 // dependency.
1810 if(cmSourceFile* sf = this->Makefile->GetSource(inName))
1812 name = sf->GetFullPath();
1813 return name;
1816 // Treat the name as relative to the source directory in which it
1817 // was given.
1818 name = this->Makefile->GetCurrentDirectory();
1819 name += "/";
1820 name += inName;
1821 return name;
1824 //----------------------------------------------------------------------------
1825 std::string cmLocalGenerator::GetRealLocation(const char* inName,
1826 const char* config)
1828 std::string outName=inName;
1829 // Look for a CMake target with the given name, which is an executable
1830 // and which can be run
1831 cmTarget* target = this->Makefile->FindTargetToUse(inName);
1832 if ((target != 0)
1833 && (target->GetType() == cmTarget::EXECUTABLE)
1834 && ((this->Makefile->IsOn("CMAKE_CROSSCOMPILING") == false)
1835 || (target->IsImported() == true)))
1837 outName = target->GetLocation( config );
1839 return outName;
1842 //----------------------------------------------------------------------------
1843 void cmLocalGenerator::AddSharedFlags(std::string& flags,
1844 const char* lang,
1845 bool shared)
1847 std::string flagsVar;
1849 // Add flags for dealing with shared libraries for this language.
1850 if(shared)
1852 flagsVar = "CMAKE_SHARED_LIBRARY_";
1853 flagsVar += lang;
1854 flagsVar += "_FLAGS";
1855 this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1858 // Add flags specific to shared builds.
1859 if(cmSystemTools::IsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
1861 flagsVar = "CMAKE_SHARED_BUILD_";
1862 flagsVar += lang;
1863 flagsVar += "_FLAGS";
1864 this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1868 //----------------------------------------------------------------------------
1869 void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
1870 const char* var,
1871 const char* config)
1873 // Add the flags from the variable itself.
1874 std::string flagsVar = var;
1875 this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1876 // Add the flags from the build-type specific variable.
1877 if(config && *config)
1879 flagsVar += "_";
1880 flagsVar += cmSystemTools::UpperCase(config);
1881 this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1885 //----------------------------------------------------------------------------
1886 void cmLocalGenerator::AppendFlags(std::string& flags,
1887 const char* newFlags)
1889 if(newFlags && *newFlags)
1891 std::string newf = newFlags;
1892 if(flags.size())
1894 flags += " ";
1896 flags += newFlags;
1900 //----------------------------------------------------------------------------
1901 void cmLocalGenerator::AppendDefines(std::string& defines,
1902 const char* defines_list,
1903 const char* lang)
1905 // Short-circuit if there are no definitions.
1906 if(!defines_list)
1908 return;
1911 // Expand the list of definitions.
1912 std::vector<std::string> defines_vec;
1913 cmSystemTools::ExpandListArgument(defines_list, defines_vec);
1915 // Short-circuit if there are no definitions.
1916 if(defines_vec.empty())
1918 return;
1921 // Lookup the define flag for the current language.
1922 std::string dflag = "-D";
1923 if(lang)
1925 std::string defineFlagVar = "CMAKE_";
1926 defineFlagVar += lang;
1927 defineFlagVar += "_DEFINE_FLAG";
1928 const char* df = this->Makefile->GetDefinition(defineFlagVar.c_str());
1929 if(df && *df)
1931 dflag = df;
1935 // Add each definition to the command line with appropriate escapes.
1936 const char* dsep = defines.empty()? "" : " ";
1937 for(std::vector<std::string>::const_iterator di = defines_vec.begin();
1938 di != defines_vec.end(); ++di)
1940 // Skip unsupported definitions.
1941 if(!this->CheckDefinition(*di))
1943 continue;
1946 // Separate from previous definitions.
1947 defines += dsep;
1948 dsep = " ";
1950 // Append the definition with proper escaping.
1951 defines += dflag;
1952 if(this->WatcomWMake)
1954 // The Watcom compiler does its own command line parsing instead
1955 // of using the windows shell rules. Definitions are one of
1956 // -DNAME
1957 // -DNAME=<cpp-token>
1958 // -DNAME="c-string with spaces and other characters(?@#$)"
1960 // Watcom will properly parse each of these cases from the
1961 // command line without any escapes. However we still have to
1962 // get the '$' and '#' characters through WMake as '$$' and
1963 // '$#'.
1964 for(const char* c = di->c_str(); *c; ++c)
1966 if(*c == '$' || *c == '#')
1968 defines += '$';
1970 defines += *c;
1973 else
1975 // Make the definition appear properly on the command line.
1976 defines += this->EscapeForShell(di->c_str(), true);
1981 //----------------------------------------------------------------------------
1982 std::string
1983 cmLocalGenerator::ConstructComment(const cmCustomCommand& cc,
1984 const char* default_comment)
1986 // Check for a comment provided with the command.
1987 if(cc.GetComment())
1989 return cc.GetComment();
1992 // Construct a reasonable default comment if possible.
1993 if(!cc.GetOutputs().empty())
1995 std::string comment;
1996 comment = "Generating ";
1997 const char* sep = "";
1998 for(std::vector<std::string>::const_iterator o = cc.GetOutputs().begin();
1999 o != cc.GetOutputs().end(); ++o)
2001 comment += sep;
2002 comment += this->Convert(o->c_str(), cmLocalGenerator::START_OUTPUT);
2003 sep = ", ";
2005 return comment;
2008 // Otherwise use the provided default.
2009 return default_comment;
2012 //----------------------------------------------------------------------------
2013 std::string
2014 cmLocalGenerator::ConvertToOptionallyRelativeOutputPath(const char* remote)
2016 return this->Convert(remote, START_OUTPUT, SHELL, true);
2019 //----------------------------------------------------------------------------
2020 const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot)
2022 switch (relroot)
2024 case HOME: return this->Makefile->GetHomeDirectory();
2025 case START: return this->Makefile->GetStartDirectory();
2026 case HOME_OUTPUT: return this->Makefile->GetHomeOutputDirectory();
2027 case START_OUTPUT: return this->Makefile->GetStartOutputDirectory();
2028 default: break;
2030 return 0;
2033 //----------------------------------------------------------------------------
2034 std::string cmLocalGenerator::Convert(const char* source,
2035 RelativeRoot relative,
2036 OutputFormat output,
2037 bool optional)
2039 // Make sure the relative path conversion components are set.
2040 if(!this->PathConversionsSetup)
2042 this->SetupPathConversions();
2043 this->PathConversionsSetup = true;
2046 // Convert the path to a relative path.
2047 std::string result = source;
2049 if (!optional || this->UseRelativePaths)
2051 switch (relative)
2053 case HOME:
2054 //result = cmSystemTools::CollapseFullPath(result.c_str());
2055 result = this->ConvertToRelativePath(this->HomeDirectoryComponents,
2056 result.c_str());
2057 break;
2058 case START:
2059 //result = cmSystemTools::CollapseFullPath(result.c_str());
2060 result = this->ConvertToRelativePath(this->StartDirectoryComponents,
2061 result.c_str());
2062 break;
2063 case HOME_OUTPUT:
2064 //result = cmSystemTools::CollapseFullPath(result.c_str());
2065 result =
2066 this->ConvertToRelativePath(this->HomeOutputDirectoryComponents,
2067 result.c_str());
2068 break;
2069 case START_OUTPUT:
2070 //result = cmSystemTools::CollapseFullPath(result.c_str());
2071 result =
2072 this->ConvertToRelativePath(this->StartOutputDirectoryComponents,
2073 result.c_str());
2074 break;
2075 case FULL:
2076 result = cmSystemTools::CollapseFullPath(result.c_str());
2077 break;
2078 case NONE:
2079 break;
2082 return this->ConvertToOutputFormat(result.c_str(), output);
2085 //----------------------------------------------------------------------------
2086 std::string cmLocalGenerator::ConvertToOutputFormat(const char* source,
2087 OutputFormat output)
2089 std::string result = source;
2090 // Convert it to an output path.
2091 if (output == MAKEFILE)
2093 result = cmSystemTools::ConvertToOutputPath(result.c_str());
2095 else if( output == SHELL)
2097 // For the MSYS shell convert drive letters to posix paths, so
2098 // that c:/some/path becomes /c/some/path. This is needed to
2099 // avoid problems with the shell path translation.
2100 if(this->MSYSShell && !this->LinkScriptShell)
2102 if(result.size() > 2 && result[1] == ':')
2104 result[1] = result[0];
2105 result[0] = '/';
2108 if(this->WindowsShell)
2110 std::string::size_type pos = 0;
2111 while((pos = result.find('/', pos)) != std::string::npos)
2113 result[pos] = '\\';
2114 pos++;
2117 result = this->EscapeForShell(result.c_str(), true, false);
2119 return result;
2122 //----------------------------------------------------------------------------
2123 std::string cmLocalGenerator::Convert(RelativeRoot remote,
2124 const char* local,
2125 OutputFormat output,
2126 bool optional)
2128 const char* remotePath = this->GetRelativeRootPath(remote);
2129 if(local && (!optional || this->UseRelativePaths))
2131 std::vector<std::string> components;
2132 std::string result;
2133 switch(remote)
2135 case HOME:
2136 case HOME_OUTPUT:
2137 case START:
2138 case START_OUTPUT:
2139 cmSystemTools::SplitPath(local, components);
2140 result = this->ConvertToRelativePath(components, remotePath);
2141 break;
2142 case FULL:
2143 result = remotePath;
2144 break;
2145 case NONE:
2146 break;
2148 return this->ConvertToOutputFormat(result.c_str(), output);
2150 else
2152 return this->ConvertToOutputFormat(remotePath, output);
2156 //----------------------------------------------------------------------------
2157 std::string cmLocalGenerator::FindRelativePathTopSource()
2159 // Relative path conversion within a single tree managed by CMake is
2160 // safe. We can use our parent relative path top if and only if
2161 // this is a subdirectory of that top.
2162 if(cmLocalGenerator* parent = this->GetParent())
2164 std::string parentTop = parent->FindRelativePathTopSource();
2165 if(cmSystemTools::IsSubDirectory(
2166 this->Makefile->GetStartDirectory(), parentTop.c_str()))
2168 return parentTop;
2172 // Otherwise this directory itself is the new top.
2173 return this->Makefile->GetStartDirectory();
2176 //----------------------------------------------------------------------------
2177 std::string cmLocalGenerator::FindRelativePathTopBinary()
2179 // Relative path conversion within a single tree managed by CMake is
2180 // safe. We can use our parent relative path top if and only if
2181 // this is a subdirectory of that top.
2182 if(cmLocalGenerator* parent = this->GetParent())
2184 std::string parentTop = parent->FindRelativePathTopBinary();
2185 if(cmSystemTools::IsSubDirectory(
2186 this->Makefile->GetStartOutputDirectory(), parentTop.c_str()))
2188 return parentTop;
2192 // Otherwise this directory itself is the new top.
2193 return this->Makefile->GetStartOutputDirectory();
2196 //----------------------------------------------------------------------------
2197 void cmLocalGenerator::ConfigureRelativePaths()
2199 // Relative path conversion inside the source tree is not used to
2200 // construct relative paths passed to build tools so it is safe to
2201 // even when the source is a network path.
2202 std::string source = this->FindRelativePathTopSource();
2203 this->RelativePathTopSource = source;
2205 // The current working directory on Windows cannot be a network
2206 // path. Therefore relative paths cannot work when the binary tree
2207 // is a network path.
2208 std::string binary = this->FindRelativePathTopBinary();
2209 if(binary.size() < 2 || binary.substr(0, 2) != "//")
2211 this->RelativePathTopBinary = binary;
2213 else
2215 this->RelativePathTopBinary = "";
2219 //----------------------------------------------------------------------------
2220 static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
2222 return (cmSystemTools::ComparePath(a, b) ||
2223 cmSystemTools::IsSubDirectory(a, b));
2226 //----------------------------------------------------------------------------
2227 std::string
2228 cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
2229 const char* in_remote)
2231 // The path should never be quoted.
2232 assert(in_remote[0] != '\"');
2234 // The local path should never have a trailing slash.
2235 assert(local.size() > 0 && !(local[local.size()-1] == ""));
2237 // If the path is already relative then just return the path.
2238 if(!cmSystemTools::FileIsFullPath(in_remote))
2240 return in_remote;
2243 // Make sure relative path conversion is configured.
2244 if(!this->RelativePathsConfigured)
2246 this->ConfigureRelativePaths();
2247 this->RelativePathsConfigured = true;
2250 // Skip conversion if the path and local are not both in the source
2251 // or both in the binary tree.
2252 std::string local_path = cmSystemTools::JoinPath(local);
2253 if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
2254 this->RelativePathTopBinary.c_str()) &&
2255 cmLocalGeneratorNotAbove(in_remote,
2256 this->RelativePathTopBinary.c_str())) ||
2257 (cmLocalGeneratorNotAbove(local_path.c_str(),
2258 this->RelativePathTopSource.c_str()) &&
2259 cmLocalGeneratorNotAbove(in_remote,
2260 this->RelativePathTopSource.c_str()))))
2262 return in_remote;
2265 // Identify the longest shared path component between the remote
2266 // path and the local path.
2267 std::vector<std::string> remote;
2268 cmSystemTools::SplitPath(in_remote, remote);
2269 unsigned int common=0;
2270 while(common < remote.size() &&
2271 common < local.size() &&
2272 cmSystemTools::ComparePath(remote[common].c_str(),
2273 local[common].c_str()))
2275 ++common;
2278 // If no part of the path is in common then return the full path.
2279 if(common == 0)
2281 return in_remote;
2284 // If the entire path is in common then just return a ".".
2285 if(common == remote.size() &&
2286 common == local.size())
2288 return ".";
2291 // If the entire path is in common except for a trailing slash then
2292 // just return a "./".
2293 if(common+1 == remote.size() &&
2294 remote[common].size() == 0 &&
2295 common == local.size())
2297 return "./";
2300 // Construct the relative path.
2301 std::string relative;
2303 // First add enough ../ to get up to the level of the shared portion
2304 // of the path. Leave off the trailing slash. Note that the last
2305 // component of local will never be empty because local should never
2306 // have a trailing slash.
2307 for(unsigned int i=common; i < local.size(); ++i)
2309 relative += "..";
2310 if(i < local.size()-1)
2312 relative += "/";
2316 // Now add the portion of the destination path that is not included
2317 // in the shared portion of the path. Add a slash the first time
2318 // only if there was already something in the path. If there was a
2319 // trailing slash in the input then the last iteration of the loop
2320 // will add a slash followed by an empty string which will preserve
2321 // the trailing slash in the output.
2322 for(unsigned int i=common; i < remote.size(); ++i)
2324 if(relative.size() > 0)
2326 relative += "/";
2328 relative += remote[i];
2331 // Finally return the path.
2332 return relative;
2335 //----------------------------------------------------------------------------
2336 void
2337 cmLocalGenerator
2338 ::GenerateTargetInstallRules(
2339 std::ostream& os, const char* config,
2340 std::vector<std::string> const& configurationTypes)
2342 // Convert the old-style install specification from each target to
2343 // an install generator and run it.
2344 cmTargets& tgts = this->Makefile->GetTargets();
2345 for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
2347 // Include the user-specified pre-install script for this target.
2348 if(const char* preinstall = l->second.GetProperty("PRE_INSTALL_SCRIPT"))
2350 cmInstallScriptGenerator g(preinstall, false, 0);
2351 g.Generate(os, config, configurationTypes);
2354 // Install this target if a destination is given.
2355 if(l->second.GetInstallPath() != "")
2357 // Compute the full install destination. Note that converting
2358 // to unix slashes also removes any trailing slash.
2359 // We also skip over the leading slash given by the user.
2360 std::string destination = l->second.GetInstallPath().substr(1);
2361 cmSystemTools::ConvertToUnixSlashes(destination);
2363 // Generate the proper install generator for this target type.
2364 switch(l->second.GetType())
2366 case cmTarget::EXECUTABLE:
2367 case cmTarget::STATIC_LIBRARY:
2368 case cmTarget::MODULE_LIBRARY:
2370 // Use a target install generator.
2371 cmInstallTargetGenerator g(l->second, destination.c_str(), false);
2372 g.Generate(os, config, configurationTypes);
2374 break;
2375 case cmTarget::SHARED_LIBRARY:
2377 #if defined(_WIN32) || defined(__CYGWIN__)
2378 // Special code to handle DLL. Install the import library
2379 // to the normal destination and the DLL to the runtime
2380 // destination.
2381 cmInstallTargetGenerator g1(l->second, destination.c_str(), true);
2382 g1.Generate(os, config, configurationTypes);
2383 // We also skip over the leading slash given by the user.
2384 destination = l->second.GetRuntimeInstallPath().substr(1);
2385 cmSystemTools::ConvertToUnixSlashes(destination);
2386 cmInstallTargetGenerator g2(l->second, destination.c_str(), false);
2387 g2.Generate(os, config, configurationTypes);
2388 #else
2389 // Use a target install generator.
2390 cmInstallTargetGenerator g(l->second, destination.c_str(), false);
2391 g.Generate(os, config, configurationTypes);
2392 #endif
2394 break;
2395 default:
2396 break;
2400 // Include the user-specified post-install script for this target.
2401 if(const char* postinstall = l->second.GetProperty("POST_INSTALL_SCRIPT"))
2403 cmInstallScriptGenerator g(postinstall, false, 0);
2404 g.Generate(os, config, configurationTypes);
2409 #if defined(CM_LG_ENCODE_OBJECT_NAMES)
2410 static std::string cmLocalGeneratorMD5(const char* input)
2412 char md5out[32];
2413 cmsysMD5* md5 = cmsysMD5_New();
2414 cmsysMD5_Initialize(md5);
2415 cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1);
2416 cmsysMD5_FinalizeHex(md5, md5out);
2417 cmsysMD5_Delete(md5);
2418 return std::string(md5out, 32);
2421 static bool
2422 cmLocalGeneratorShortenObjectName(std::string& objName,
2423 std::string::size_type max_len)
2425 // Replace the beginning of the path portion of the object name with
2426 // its own md5 sum.
2427 std::string::size_type pos = objName.find('/', objName.size()-max_len+32);
2428 if(pos != objName.npos)
2430 std::string md5name = cmLocalGeneratorMD5(objName.substr(0, pos).c_str());
2431 md5name += objName.substr(pos);
2432 objName = md5name;
2434 // The object name is now short enough.
2435 return true;
2437 else
2439 // The object name could not be shortened enough.
2440 return false;
2444 static
2445 bool cmLocalGeneratorCheckObjectName(std::string& objName,
2446 std::string::size_type dir_len,
2447 std::string::size_type max_total_len)
2449 // Enforce the maximum file name length if possible.
2450 std::string::size_type max_obj_len = max_total_len;
2451 if(dir_len < max_total_len)
2453 max_obj_len = max_total_len - dir_len;
2454 if(objName.size() > max_obj_len)
2456 // The current object file name is too long. Try to shorten it.
2457 return cmLocalGeneratorShortenObjectName(objName, max_obj_len);
2459 else
2461 // The object file name is short enough.
2462 return true;
2465 else
2467 // The build directory in which the object will be stored is
2468 // already too deep.
2469 return false;
2472 #endif
2474 //----------------------------------------------------------------------------
2475 std::string&
2476 cmLocalGenerator
2477 ::CreateSafeUniqueObjectFileName(const char* sin,
2478 std::string::size_type dir_len)
2480 // Look for an existing mapped name for this object file.
2481 std::map<cmStdString,cmStdString>::iterator it =
2482 this->UniqueObjectNamesMap.find(sin);
2484 // If no entry exists create one.
2485 if(it == this->UniqueObjectNamesMap.end())
2487 // Start with the original name.
2488 std::string ssin = sin;
2490 // Avoid full paths by removing leading slashes.
2491 std::string::size_type pos = 0;
2492 for(;pos < ssin.size() && ssin[pos] == '/'; ++pos)
2495 ssin = ssin.substr(pos);
2497 // Avoid full paths by removing colons.
2498 cmSystemTools::ReplaceString(ssin, ":", "_");
2500 // Avoid relative paths that go up the tree.
2501 cmSystemTools::ReplaceString(ssin, "../", "__/");
2503 // Avoid spaces.
2504 cmSystemTools::ReplaceString(ssin, " ", "_");
2506 // Mangle the name if necessary.
2507 if(this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES"))
2509 bool done;
2510 int cc = 0;
2511 char rpstr[100];
2512 sprintf(rpstr, "_p_");
2513 cmSystemTools::ReplaceString(ssin, "+", rpstr);
2514 std::string sssin = sin;
2517 done = true;
2518 for ( it = this->UniqueObjectNamesMap.begin();
2519 it != this->UniqueObjectNamesMap.end();
2520 ++ it )
2522 if ( it->second == ssin )
2524 done = false;
2527 if ( done )
2529 break;
2531 sssin = ssin;
2532 cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
2533 sprintf(rpstr, "_p%d_", cc++);
2535 while ( !done );
2538 #if defined(CM_LG_ENCODE_OBJECT_NAMES)
2539 cmLocalGeneratorCheckObjectName(ssin, dir_len, this->ObjectPathMax);
2540 #else
2541 (void)dir_len;
2542 #endif
2544 // Insert the newly mapped object file name.
2545 std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
2546 it = this->UniqueObjectNamesMap.insert(e).first;
2549 // Return the map entry.
2550 return it->second;
2553 //----------------------------------------------------------------------------
2554 std::string
2555 cmLocalGenerator
2556 ::GetObjectFileNameWithoutTarget(const cmSourceFile& source,
2557 std::string::size_type dir_len,
2558 bool* hasSourceExtension)
2560 // Construct the object file name using the full path to the source
2561 // file which is its only unique identification.
2562 const char* fullPath = source.GetFullPath().c_str();
2564 // Try referencing the source relative to the source tree.
2565 std::string relFromSource = this->Convert(fullPath, START);
2566 assert(!relFromSource.empty());
2567 bool relSource = !cmSystemTools::FileIsFullPath(relFromSource.c_str());
2568 bool subSource = relSource && relFromSource[0] != '.';
2570 // Try referencing the source relative to the binary tree.
2571 std::string relFromBinary = this->Convert(fullPath, START_OUTPUT);
2572 assert(!relFromBinary.empty());
2573 bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary.c_str());
2574 bool subBinary = relBinary && relFromBinary[0] != '.';
2576 // Select a nice-looking reference to the source file to construct
2577 // the object file name.
2578 std::string objectName;
2579 if((relSource && !relBinary) || (subSource && !subBinary))
2581 objectName = relFromSource;
2583 else if((relBinary && !relSource) || (subBinary && !subSource))
2585 objectName = relFromBinary;
2587 else if(relFromBinary.length() < relFromSource.length())
2589 objectName = relFromBinary;
2591 else
2593 objectName = relFromSource;
2596 // if it is still a full path check for the try compile case
2597 // try compile never have in source sources, and should not
2598 // have conflicting source file names in the same target
2599 if(cmSystemTools::FileIsFullPath(objectName.c_str()))
2601 if(this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile())
2603 objectName = cmSystemTools::GetFilenameName(source.GetFullPath());
2607 // Replace the original source file extension with the object file
2608 // extension.
2609 bool keptSourceExtension = true;
2610 if(!source.GetPropertyAsBool("KEEP_EXTENSION"))
2612 // Decide whether this language wants to replace the source
2613 // extension with the object extension. For CMake 2.4
2614 // compatibility do this by default.
2615 bool replaceExt = this->NeedBackwardsCompatibility(2, 4);
2616 if(!replaceExt)
2618 std::string repVar = "CMAKE_";
2619 repVar += source.GetLanguage();
2620 repVar += "_OUTPUT_EXTENSION_REPLACE";
2621 replaceExt = this->Makefile->IsOn(repVar.c_str());
2624 // Remove the source extension if it is to be replaced.
2625 if(replaceExt)
2627 keptSourceExtension = false;
2628 std::string::size_type dot_pos = objectName.rfind(".");
2629 if(dot_pos != std::string::npos)
2631 objectName = objectName.substr(0, dot_pos);
2635 // Store the new extension.
2636 objectName +=
2637 this->GlobalGenerator->GetLanguageOutputExtension(source);
2639 if(hasSourceExtension)
2641 *hasSourceExtension = keptSourceExtension;
2644 // Convert to a safe name.
2645 return this->CreateSafeUniqueObjectFileName(objectName.c_str(), dir_len);
2648 //----------------------------------------------------------------------------
2649 const char*
2650 cmLocalGenerator
2651 ::GetSourceFileLanguage(const cmSourceFile& source)
2653 return source.GetLanguage();
2656 //----------------------------------------------------------------------------
2657 std::string cmLocalGenerator::EscapeForShellOldStyle(const char* str)
2659 std::string result;
2660 bool forceOn = cmSystemTools::GetForceUnixPaths();
2661 if(forceOn && this->WindowsShell)
2663 cmSystemTools::SetForceUnixPaths(false);
2665 result = cmSystemTools::EscapeSpaces(str);
2666 if(forceOn && this->WindowsShell)
2668 cmSystemTools::SetForceUnixPaths(true);
2670 return result;
2673 //----------------------------------------------------------------------------
2674 static bool cmLocalGeneratorIsShellOperator(const char* str)
2676 if(strcmp(str, "<") == 0 ||
2677 strcmp(str, ">") == 0 ||
2678 strcmp(str, "<<") == 0 ||
2679 strcmp(str, ">>") == 0 ||
2680 strcmp(str, "|") == 0 ||
2681 strcmp(str, "&>") == 0 ||
2682 strcmp(str, "2>&1") == 0 ||
2683 strcmp(str, "1>&2") == 0)
2685 return true;
2687 return false;
2690 //----------------------------------------------------------------------------
2691 std::string cmLocalGenerator::EscapeForShell(const char* str, bool makeVars,
2692 bool forEcho)
2694 // Do not escape shell operators.
2695 if(cmLocalGeneratorIsShellOperator(str))
2697 return str;
2700 // Compute the flags for the target shell environment.
2701 int flags = 0;
2702 if(this->WindowsVSIDE)
2704 flags |= cmsysSystem_Shell_Flag_VSIDE;
2706 else if(!this->LinkScriptShell)
2708 flags |= cmsysSystem_Shell_Flag_Make;
2710 if(makeVars)
2712 flags |= cmsysSystem_Shell_Flag_AllowMakeVariables;
2714 if(forEcho)
2716 flags |= cmsysSystem_Shell_Flag_EchoWindows;
2718 if(this->WatcomWMake)
2720 flags |= cmsysSystem_Shell_Flag_WatcomWMake;
2722 if(this->MinGWMake)
2724 flags |= cmsysSystem_Shell_Flag_MinGWMake;
2726 if(this->NMake)
2728 flags |= cmsysSystem_Shell_Flag_NMake;
2731 // Compute the buffer size needed.
2732 int size = (this->WindowsShell ?
2733 cmsysSystem_Shell_GetArgumentSizeForWindows(str, flags) :
2734 cmsysSystem_Shell_GetArgumentSizeForUnix(str, flags));
2736 // Compute the shell argument itself.
2737 std::vector<char> arg(size);
2738 if(this->WindowsShell)
2740 cmsysSystem_Shell_GetArgumentForWindows(str, &arg[0], flags);
2742 else
2744 cmsysSystem_Shell_GetArgumentForUnix(str, &arg[0], flags);
2746 return std::string(&arg[0]);
2749 //----------------------------------------------------------------------------
2750 std::string cmLocalGenerator::EscapeForCMake(const char* str)
2752 // Always double-quote the argument to take care of most escapes.
2753 std::string result = "\"";
2754 for(const char* c = str; *c; ++c)
2756 if(*c == '"')
2758 // Escape the double quote to avoid ending the argument.
2759 result += "\\\"";
2761 else if(*c == '$')
2763 // Escape the dollar to avoid expanding variables.
2764 result += "\\$";
2766 else if(*c == '\\')
2768 // Escape the backslash to avoid other escapes.
2769 result += "\\\\";
2771 else
2773 // Other characters will be parsed correctly.
2774 result += *c;
2777 result += "\"";
2778 return result;
2781 //----------------------------------------------------------------------------
2782 std::string
2783 cmLocalGenerator::GetTargetDirectory(cmTarget const&) const
2785 cmSystemTools::Error("GetTargetDirectory"
2786 " called on cmLocalGenerator");
2787 return "";
2791 //----------------------------------------------------------------------------
2792 void
2793 cmLocalGenerator::GetTargetObjectFileDirectories(cmTarget* ,
2794 std::vector<std::string>&
2797 cmSystemTools::Error("GetTargetObjectFileDirectories"
2798 " called on cmLocalGenerator");
2801 //----------------------------------------------------------------------------
2802 unsigned int cmLocalGenerator::GetBackwardsCompatibility()
2804 // The computed version may change until the project is fully
2805 // configured.
2806 if(!this->BackwardsCompatibilityFinal)
2808 unsigned int major = 0;
2809 unsigned int minor = 0;
2810 unsigned int patch = 0;
2811 if(const char* value
2812 = this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"))
2814 switch(sscanf(value, "%u.%u.%u", &major, &minor, &patch))
2816 case 2: patch = 0; break;
2817 case 1: minor = 0; patch = 0; break;
2818 default: break;
2821 this->BackwardsCompatibility = CMake_VERSION_ENCODE(major, minor, patch);
2822 this->BackwardsCompatibilityFinal = this->Configured;
2825 return this->BackwardsCompatibility;
2828 //----------------------------------------------------------------------------
2829 bool cmLocalGenerator::NeedBackwardsCompatibility(unsigned int major,
2830 unsigned int minor,
2831 unsigned int patch)
2833 // Check the policy to decide whether to pay attention to this
2834 // variable.
2835 switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0001))
2837 case cmPolicies::WARN:
2838 // WARN is just OLD without warning because user code does not
2839 // always affect whether this check is done.
2840 case cmPolicies::OLD:
2841 // Old behavior is to check the variable.
2842 break;
2843 case cmPolicies::NEW:
2844 // New behavior is to ignore the variable.
2845 return false;
2846 case cmPolicies::REQUIRED_IF_USED:
2847 case cmPolicies::REQUIRED_ALWAYS:
2848 // This will never be the case because the only way to require
2849 // the setting is to require the user to specify version policy
2850 // 2.6 or higher. Once we add that requirement then this whole
2851 // method can be removed anyway.
2852 return false;
2855 // Compatibility is needed if CMAKE_BACKWARDS_COMPATIBILITY is set
2856 // equal to or lower than the given version.
2857 unsigned int actual_compat = this->GetBackwardsCompatibility();
2858 return (actual_compat &&
2859 actual_compat <= CMake_VERSION_ENCODE(major, minor, patch));
2862 //----------------------------------------------------------------------------
2863 bool cmLocalGenerator::CheckDefinition(std::string const& define) const
2865 // Many compilers do not support -DNAME(arg)=sdf so we disable it.
2866 bool function_style = false;
2867 for(const char* c = define.c_str(); *c && *c != '='; ++c)
2869 if(*c == '(')
2871 function_style = true;
2872 break;
2875 if(function_style)
2877 cmOStringStream e;
2878 e << "WARNING: Function-style preprocessor definitions may not be "
2879 << "passed on the compiler command line because many compilers "
2880 << "do not support it.\n"
2881 << "CMake is dropping a preprocessor definition: " << define << "\n"
2882 << "Consider defining the macro in a (configured) header file.\n";
2883 cmSystemTools::Message(e.str().c_str());
2884 return false;
2887 // Many compilers do not support # in the value so we disable it.
2888 if(define.find_first_of("#") != define.npos)
2890 cmOStringStream e;
2891 e << "WARNING: Peprocessor definitions containing '#' may not be "
2892 << "passed on the compiler command line because many compilers "
2893 << "do not support it.\n"
2894 << "CMake is dropping a preprocessor definition: " << define << "\n"
2895 << "Consider defining the macro in a (configured) header file.\n";
2896 cmSystemTools::Message(e.str().c_str());
2897 return false;
2900 // Assume it is supported.
2901 return true;
2904 //----------------------------------------------------------------------------
2905 static void cmLGInfoProp(cmMakefile* mf, cmTarget* target, const char* prop)
2907 if(const char* val = target->GetProperty(prop))
2909 mf->AddDefinition(prop, val);
2913 //----------------------------------------------------------------------------
2914 void cmLocalGenerator::GenerateAppleInfoPList(cmTarget* target,
2915 const char* targetName,
2916 const char* fname)
2918 // Find the Info.plist template.
2919 const char* in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
2920 std::string inFile = (in && *in)? in : "MacOSXBundleInfo.plist.in";
2921 if(!cmSystemTools::FileIsFullPath(inFile.c_str()))
2923 std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
2924 if(!inMod.empty())
2926 inFile = inMod;
2929 if(!cmSystemTools::FileExists(inFile.c_str(), true))
2931 cmOStringStream e;
2932 e << "Target " << target->GetName() << " Info.plist template \""
2933 << inFile << "\" could not be found.";
2934 cmSystemTools::Error(e.str().c_str());
2935 return;
2938 // Convert target properties to variables in an isolated makefile
2939 // scope to configure the file. If properties are set they will
2940 // override user make variables. If not the configuration will fall
2941 // back to the directory-level values set by the user.
2942 cmMakefile* mf = this->Makefile;
2943 mf->PushScope();
2944 mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName);
2945 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_INFO_STRING");
2946 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_ICON_FILE");
2947 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_GUI_IDENTIFIER");
2948 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_LONG_VERSION_STRING");
2949 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_NAME");
2950 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
2951 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
2952 cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
2953 mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
2954 mf->PopScope();
2957 //----------------------------------------------------------------------------
2958 void cmLocalGenerator::GenerateFrameworkInfoPList(cmTarget* target,
2959 const char* targetName,
2960 const char* fname)
2962 // Find the Info.plist template.
2963 const char* in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
2964 std::string inFile = (in && *in)? in : "MacOSXFrameworkInfo.plist.in";
2965 if(!cmSystemTools::FileIsFullPath(inFile.c_str()))
2967 std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
2968 if(!inMod.empty())
2970 inFile = inMod;
2973 if(!cmSystemTools::FileExists(inFile.c_str(), true))
2975 cmOStringStream e;
2976 e << "Target " << target->GetName() << " Info.plist template \""
2977 << inFile << "\" could not be found.";
2978 cmSystemTools::Error(e.str().c_str());
2979 return;
2982 // Convert target properties to variables in an isolated makefile
2983 // scope to configure the file. If properties are set they will
2984 // override user make variables. If not the configuration will fall
2985 // back to the directory-level values set by the user.
2986 cmMakefile* mf = this->Makefile;
2987 mf->PushScope();
2988 mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName);
2989 cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_ICON_FILE");
2990 cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
2991 cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
2992 cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
2993 mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
2994 mf->PopScope();