You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2810 lines
88 KiB

23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
21 years ago
20 years ago
20 years ago
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmLocalGenerator.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmGlobalGenerator.h"
  16. #include "cmInstallGenerator.h"
  17. #include "cmInstallFilesGenerator.h"
  18. #include "cmInstallScriptGenerator.h"
  19. #include "cmInstallTargetGenerator.h"
  20. #include "cmMakefile.h"
  21. #include "cmOrderLinkDirectories.h"
  22. #include "cmSourceFile.h"
  23. #include "cmTest.h"
  24. #include "cmake.h"
  25. #if defined(CMAKE_BUILD_WITH_CMAKE)
  26. # define CM_LG_ENCODE_OBJECT_NAMES
  27. # include <cmsys/MD5.h>
  28. #endif
  29. #include <cmsys/System.h>
  30. #include <ctype.h> // for isalpha
  31. #include <assert.h>
  32. cmLocalGenerator::cmLocalGenerator()
  33. {
  34. this->Makefile = new cmMakefile;
  35. this->Makefile->SetLocalGenerator(this);
  36. this->Parent = 0;
  37. this->WindowsShell = false;
  38. this->WindowsVSIDE = false;
  39. this->WatcomWMake = false;
  40. this->MinGWMake = false;
  41. this->MSYSShell = false;
  42. this->IgnoreLibPrefix = false;
  43. this->UseRelativePaths = false;
  44. this->Configured = false;
  45. this->EmitUniversalBinaryFlags = true;
  46. this->IsMakefileGenerator = false;
  47. this->RelativePathsConfigured = false;
  48. this->PathConversionsSetup = false;
  49. }
  50. cmLocalGenerator::~cmLocalGenerator()
  51. {
  52. delete this->Makefile;
  53. }
  54. void cmLocalGenerator::Configure()
  55. {
  56. cmLocalGenerator* previousLg =
  57. this->GetGlobalGenerator()->GetCurrentLocalGenerator();
  58. this->GetGlobalGenerator()->SetCurrentLocalGenerator(this);
  59. // make sure the CMakeFiles dir is there
  60. std::string filesDir = this->Makefile->GetStartOutputDirectory();
  61. filesDir += cmake::GetCMakeFilesDirectory();
  62. cmSystemTools::MakeDirectory(filesDir.c_str());
  63. // find & read the list file
  64. std::string currentStart = this->Makefile->GetStartDirectory();
  65. currentStart += "/CMakeLists.txt";
  66. this->Makefile->ReadListFile(currentStart.c_str());
  67. // at the end of the ReadListFile handle any old style subdirs
  68. // first get all the subdirectories
  69. std::vector<cmLocalGenerator *> subdirs = this->GetChildren();
  70. // for each subdir recurse
  71. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  72. for (; sdi != subdirs.end(); ++sdi)
  73. {
  74. if (!(*sdi)->Configured)
  75. {
  76. this->Makefile->ConfigureSubDirectory(*sdi);
  77. }
  78. }
  79. // Check whether relative paths should be used for optionally
  80. // relative paths.
  81. this->UseRelativePaths = this->Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
  82. this->Configured = true;
  83. this->GetGlobalGenerator()->SetCurrentLocalGenerator(previousLg);
  84. }
  85. void cmLocalGenerator::SetupPathConversions()
  86. {
  87. // Setup the current output directory components for use by
  88. // Convert
  89. std::string outdir;
  90. outdir =
  91. cmSystemTools::CollapseFullPath(this->Makefile->GetHomeDirectory());
  92. cmSystemTools::SplitPath(outdir.c_str(), this->HomeDirectoryComponents);
  93. outdir =
  94. cmSystemTools::CollapseFullPath(this->Makefile->GetStartDirectory());
  95. cmSystemTools::SplitPath(outdir.c_str(), this->StartDirectoryComponents);
  96. outdir = cmSystemTools::CollapseFullPath
  97. (this->Makefile->GetHomeOutputDirectory());
  98. cmSystemTools::SplitPath(outdir.c_str(),
  99. this->HomeOutputDirectoryComponents);
  100. outdir = cmSystemTools::CollapseFullPath
  101. (this->Makefile->GetStartOutputDirectory());
  102. cmSystemTools::SplitPath(outdir.c_str(),
  103. this->StartOutputDirectoryComponents);
  104. }
  105. void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
  106. {
  107. this->GlobalGenerator = gg;
  108. // setup the home directories
  109. this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance());
  110. this->Makefile->SetHomeDirectory(
  111. gg->GetCMakeInstance()->GetHomeDirectory());
  112. this->Makefile->SetHomeOutputDirectory(
  113. gg->GetCMakeInstance()->GetHomeOutputDirectory());
  114. }
  115. void cmLocalGenerator::ConfigureFinalPass()
  116. {
  117. this->Makefile->ConfigureFinalPass();
  118. }
  119. void cmLocalGenerator::TraceDependencies()
  120. {
  121. // Generate the rule files for each target.
  122. cmTargets& targets = this->Makefile->GetTargets();
  123. for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
  124. {
  125. // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
  126. // so don't build a projectfile for it
  127. if (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
  128. {
  129. const char* projectFilename = 0;
  130. if (this->IsMakefileGenerator == false) // only use of this variable
  131. {
  132. projectFilename = t->second.GetName();
  133. }
  134. t->second.TraceDependencies(projectFilename);
  135. }
  136. }
  137. }
  138. void cmLocalGenerator::GenerateTestFiles()
  139. {
  140. if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") )
  141. {
  142. return;
  143. }
  144. std::string file = this->Makefile->GetStartOutputDirectory();
  145. file += "/";
  146. if ( this->Makefile->IsSet("CTEST_NEW_FORMAT") )
  147. {
  148. file += "CTestTestfile.cmake";
  149. }
  150. else
  151. {
  152. file += "DartTestfile.txt";
  153. }
  154. cmGeneratedFileStream fout(file.c_str());
  155. fout.SetCopyIfDifferent(true);
  156. fout << "# CMake generated Testfile for " << std::endl
  157. << "# Source directory: "
  158. << this->Makefile->GetStartDirectory() << std::endl
  159. << "# Build directory: "
  160. << this->Makefile->GetStartOutputDirectory() << std::endl
  161. << "# " << std::endl
  162. << "# This file replicates the SUBDIRS() and ADD_TEST() commands "
  163. << "from the source" << std::endl
  164. << "# tree CMakeLists.txt file, skipping any SUBDIRS() or "
  165. << "ADD_TEST() commands" << std::endl
  166. << "# that are excluded by CMake control structures, i.e. IF() "
  167. << "commands." << std::endl
  168. << "#" << std::endl
  169. << "# The next line is critical for Dart to work" << std::endl
  170. << "# Duh :-)" << std::endl << std::endl;
  171. const char* testIncludeFile =
  172. this->Makefile->GetProperty("TEST_INCLUDE_FILE");
  173. if ( testIncludeFile )
  174. {
  175. fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
  176. }
  177. const std::vector<cmTest*> *tests = this->Makefile->GetTests();
  178. std::vector<cmTest*>::const_iterator it;
  179. for ( it = tests->begin(); it != tests->end(); ++ it )
  180. {
  181. cmTest* test = *it;
  182. fout << "ADD_TEST(";
  183. fout << test->GetName() << " \"" << test->GetCommand() << "\"";
  184. std::vector<cmStdString>::const_iterator argit;
  185. for (argit = test->GetArguments().begin();
  186. argit != test->GetArguments().end(); ++argit)
  187. {
  188. // Just double-quote all arguments so they are re-parsed
  189. // correctly by the test system.
  190. fout << " \"";
  191. for(std::string::const_iterator c = argit->begin();
  192. c != argit->end(); ++c)
  193. {
  194. // Escape quotes within arguments. We should escape
  195. // backslashes too but we cannot because it makes the result
  196. // inconsistent with previous behavior of this command.
  197. if((*c == '"'))
  198. {
  199. fout << '\\';
  200. }
  201. fout << *c;
  202. }
  203. fout << "\"";
  204. }
  205. fout << ")" << std::endl;
  206. cmPropertyMap::const_iterator pit;
  207. cmPropertyMap* mpit = &test->GetProperties();
  208. if ( mpit->size() )
  209. {
  210. fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
  211. for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
  212. {
  213. fout << " " << pit->first.c_str() << " \"";
  214. const char* value = pit->second.GetValue();
  215. for ( ; *value; ++ value )
  216. {
  217. switch ( *value )
  218. {
  219. case '\\':
  220. case '"':
  221. case ' ':
  222. case '#':
  223. case '(':
  224. case ')':
  225. case '$':
  226. case '^':
  227. fout << "\\" << *value;
  228. break;
  229. case '\t':
  230. fout << "\\t";
  231. break;
  232. case '\n':
  233. fout << "\\n";
  234. break;
  235. case '\r':
  236. fout << "\\r";
  237. break;
  238. default:
  239. fout << *value;
  240. }
  241. }
  242. fout << "\"";
  243. }
  244. fout << ")" << std::endl;
  245. }
  246. }
  247. if ( this->Children.size())
  248. {
  249. fout << "SUBDIRS(";
  250. size_t i;
  251. std::string outDir = this->Makefile->GetStartOutputDirectory();
  252. outDir += "/";
  253. for(i = 0; i < this->Children.size(); ++i)
  254. {
  255. std::string binP =
  256. this->Children[i]->GetMakefile()->GetStartOutputDirectory();
  257. cmSystemTools::ReplaceString(binP, outDir.c_str(), "");
  258. if ( i > 0 )
  259. {
  260. fout << " ";
  261. }
  262. fout << binP.c_str();
  263. }
  264. fout << ")" << std::endl << std::endl;;
  265. }
  266. }
  267. //----------------------------------------------------------------------------
  268. void cmLocalGenerator::GenerateInstallRules()
  269. {
  270. // Compute the install prefix.
  271. const char* prefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX");
  272. #if defined(_WIN32) && !defined(__CYGWIN__)
  273. std::string prefix_win32;
  274. if(!prefix)
  275. {
  276. if(!cmSystemTools::GetEnv("SystemDrive", prefix_win32))
  277. {
  278. prefix_win32 = "C:";
  279. }
  280. const char* project_name = this->Makefile->GetDefinition("PROJECT_NAME");
  281. if(project_name && project_name[0])
  282. {
  283. prefix_win32 += "/Program Files/";
  284. prefix_win32 += project_name;
  285. }
  286. else
  287. {
  288. prefix_win32 += "/InstalledCMakeProject";
  289. }
  290. prefix = prefix_win32.c_str();
  291. }
  292. #else
  293. if (!prefix)
  294. {
  295. prefix = "/usr/local";
  296. }
  297. #endif
  298. // Compute the set of configurations.
  299. std::vector<std::string> configurationTypes;
  300. if(const char* types =
  301. this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
  302. {
  303. cmSystemTools::ExpandListArgument(types, configurationTypes);
  304. }
  305. const char* config = 0;
  306. if(configurationTypes.empty())
  307. {
  308. config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
  309. }
  310. // Choose a default install configuration.
  311. const char* default_config = config;
  312. const char* default_order[] = {"RELEASE", "MINSIZEREL",
  313. "RELWITHDEBINFO", "DEBUG", 0};
  314. for(const char** c = default_order; *c && !default_config; ++c)
  315. {
  316. for(std::vector<std::string>::iterator i = configurationTypes.begin();
  317. i != configurationTypes.end(); ++i)
  318. {
  319. if(cmSystemTools::UpperCase(*i) == *c)
  320. {
  321. default_config = i->c_str();
  322. }
  323. }
  324. }
  325. if(!default_config && !configurationTypes.empty())
  326. {
  327. default_config = configurationTypes[0].c_str();
  328. }
  329. if(!default_config)
  330. {
  331. default_config = "Release";
  332. }
  333. // Create the install script file.
  334. std::string file = this->Makefile->GetStartOutputDirectory();
  335. std::string homedir = this->Makefile->GetHomeOutputDirectory();
  336. std::string currdir = this->Makefile->GetCurrentOutputDirectory();
  337. cmSystemTools::ConvertToUnixSlashes(file);
  338. cmSystemTools::ConvertToUnixSlashes(homedir);
  339. cmSystemTools::ConvertToUnixSlashes(currdir);
  340. int toplevel_install = 0;
  341. if ( currdir == homedir )
  342. {
  343. toplevel_install = 1;
  344. }
  345. file += "/cmake_install.cmake";
  346. cmGeneratedFileStream fout(file.c_str());
  347. fout.SetCopyIfDifferent(true);
  348. // Write the header.
  349. fout << "# Install script for directory: "
  350. << this->Makefile->GetCurrentDirectory() << std::endl << std::endl;
  351. fout << "# Set the install prefix" << std::endl
  352. << "IF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
  353. << " SET(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
  354. << "ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
  355. << "STRING(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
  356. << "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
  357. << std::endl;
  358. // Write support code for generating per-configuration install rules.
  359. fout <<
  360. "# Set the install configuration name.\n"
  361. "IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
  362. " IF(BUILD_TYPE)\n"
  363. " STRING(REGEX REPLACE \"^[^A-Za-z0-9_]+\" \"\"\n"
  364. " CMAKE_INSTALL_CONFIG_NAME \"${BUILD_TYPE}\")\n"
  365. " ELSE(BUILD_TYPE)\n"
  366. " SET(CMAKE_INSTALL_CONFIG_NAME \"" << default_config << "\")\n"
  367. " ENDIF(BUILD_TYPE)\n"
  368. " MESSAGE(STATUS \"Install configuration: "
  369. "\\\"${CMAKE_INSTALL_CONFIG_NAME}\\\"\")\n"
  370. "ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)\n"
  371. "\n";
  372. // Write support code for dealing with component-specific installs.
  373. fout <<
  374. "# Set the component getting installed.\n"
  375. "IF(NOT CMAKE_INSTALL_COMPONENT)\n"
  376. " IF(COMPONENT)\n"
  377. " MESSAGE(STATUS \"Install component: \\\"${COMPONENT}\\\"\")\n"
  378. " SET(CMAKE_INSTALL_COMPONENT \"${COMPONENT}\")\n"
  379. " ELSE(COMPONENT)\n"
  380. " SET(CMAKE_INSTALL_COMPONENT)\n"
  381. " ENDIF(COMPONENT)\n"
  382. "ENDIF(NOT CMAKE_INSTALL_COMPONENT)\n"
  383. "\n";
  384. // Copy user-specified install options to the install code.
  385. if(const char* so_no_exe =
  386. this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE"))
  387. {
  388. fout <<
  389. "# Install shared libraries without execute permission?\n"
  390. "IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
  391. " SET(CMAKE_INSTALL_SO_NO_EXE \"" << so_no_exe << "\")\n"
  392. "ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n"
  393. "\n";
  394. }
  395. // Ask each install generator to write its code.
  396. std::vector<cmInstallGenerator*> const& installers =
  397. this->Makefile->GetInstallGenerators();
  398. for(std::vector<cmInstallGenerator*>::const_iterator
  399. gi = installers.begin();
  400. gi != installers.end(); ++gi)
  401. {
  402. (*gi)->Generate(fout, config, configurationTypes);
  403. }
  404. // Write rules from old-style specification stored in targets.
  405. this->GenerateTargetInstallRules(fout, config, configurationTypes);
  406. // Include install scripts from subdirectories.
  407. if(!this->Children.empty())
  408. {
  409. fout << "IF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
  410. fout << " # Include the install script for each subdirectory.\n";
  411. for(std::vector<cmLocalGenerator*>::const_iterator
  412. ci = this->Children.begin(); ci != this->Children.end(); ++ci)
  413. {
  414. if(!(*ci)->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
  415. {
  416. std::string odir = (*ci)->GetMakefile()->GetStartOutputDirectory();
  417. cmSystemTools::ConvertToUnixSlashes(odir);
  418. fout << " INCLUDE(\"" << odir.c_str()
  419. << "/cmake_install.cmake\")" << std::endl;
  420. }
  421. }
  422. fout << "\n";
  423. fout << "ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY)\n\n";
  424. }
  425. // Record the install manifest.
  426. if ( toplevel_install )
  427. {
  428. fout <<
  429. "IF(CMAKE_INSTALL_COMPONENT)\n"
  430. " SET(CMAKE_INSTALL_MANIFEST \"install_manifest_"
  431. "${CMAKE_INSTALL_COMPONENT}.txt\")\n"
  432. "ELSE(CMAKE_INSTALL_COMPONENT)\n"
  433. " SET(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
  434. "ENDIF(CMAKE_INSTALL_COMPONENT)\n\n";
  435. fout
  436. << "FILE(WRITE \""
  437. << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
  438. << "\"\")" << std::endl;
  439. fout
  440. << "FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})" << std::endl
  441. << " FILE(APPEND \""
  442. << homedir.c_str() << "/${CMAKE_INSTALL_MANIFEST}\" "
  443. << "\"${file}\\n\")" << std::endl
  444. << "ENDFOREACH(file)" << std::endl;
  445. }
  446. }
  447. //----------------------------------------------------------------------------
  448. void cmLocalGenerator::GenerateTargetManifest(cmTargetManifest& manifest)
  449. {
  450. // Collect the set of configuration types.
  451. std::vector<std::string> configNames;
  452. if(const char* configurationTypes =
  453. this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
  454. {
  455. cmSystemTools::ExpandListArgument(configurationTypes, configNames);
  456. }
  457. else if(const char* buildType =
  458. this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"))
  459. {
  460. if(*buildType)
  461. {
  462. configNames.push_back(buildType);
  463. }
  464. }
  465. // Add our targets to the manifest for each configuration.
  466. cmTargets& targets = this->Makefile->GetTargets();
  467. for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
  468. {
  469. cmTarget& target = t->second;
  470. cmTarget::TargetType type = target.GetType();
  471. if(type == cmTarget::STATIC_LIBRARY ||
  472. type == cmTarget::SHARED_LIBRARY ||
  473. type == cmTarget::MODULE_LIBRARY ||
  474. type == cmTarget::EXECUTABLE)
  475. {
  476. if(configNames.empty())
  477. {
  478. manifest[""].insert(target.GetFullPath(0, false));
  479. if(type == cmTarget::SHARED_LIBRARY &&
  480. this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
  481. {
  482. manifest[""].insert(target.GetFullPath(0, true));
  483. }
  484. }
  485. else
  486. {
  487. for(std::vector<std::string>::iterator ci = configNames.begin();
  488. ci != configNames.end(); ++ci)
  489. {
  490. const char* config = ci->c_str();
  491. manifest[config].insert(target.GetFullPath(config, false));
  492. if(type == cmTarget::SHARED_LIBRARY &&
  493. this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
  494. {
  495. manifest[config].insert(target.GetFullPath(config, true));
  496. }
  497. }
  498. }
  499. }
  500. }
  501. }
  502. void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
  503. const char* lang,
  504. cmSourceFile& source,
  505. cmTarget& )
  506. {
  507. std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname));
  508. objectDir = this->Convert(objectDir.c_str(),START_OUTPUT,SHELL);
  509. std::string objectFile = this->Convert(ofname,START_OUTPUT,SHELL);
  510. std::string sourceFile =
  511. this->Convert(source.GetFullPath().c_str(),START_OUTPUT,SHELL,true);
  512. std::string varString = "CMAKE_";
  513. varString += lang;
  514. varString += "_COMPILE_OBJECT";
  515. std::vector<std::string> rules;
  516. rules.push_back(this->Makefile->GetRequiredDefinition(varString.c_str()));
  517. varString = "CMAKE_";
  518. varString += lang;
  519. varString += "_FLAGS";
  520. std::string flags;
  521. flags += this->Makefile->GetSafeDefinition(varString.c_str());
  522. flags += " ";
  523. flags += this->GetIncludeFlags(lang);
  524. // Construct the command lines.
  525. cmCustomCommandLines commandLines;
  526. std::vector<std::string> commands;
  527. cmSystemTools::ExpandList(rules, commands);
  528. cmLocalGenerator::RuleVariables vars;
  529. vars.Language = lang;
  530. vars.Source = sourceFile.c_str();
  531. vars.Object = objectFile.c_str();
  532. vars.ObjectDir = objectDir.c_str();
  533. vars.Flags = flags.c_str();
  534. for(std::vector<std::string>::iterator i = commands.begin();
  535. i != commands.end(); ++i)
  536. {
  537. // Expand the full command line string.
  538. this->ExpandRuleVariables(*i, vars);
  539. // Parse the string to get the custom command line.
  540. cmCustomCommandLine commandLine;
  541. std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
  542. for(std::vector<cmStdString>::iterator a = cmd.begin();
  543. a != cmd.end(); ++a)
  544. {
  545. commandLine.push_back(*a);
  546. }
  547. // Store this command line.
  548. commandLines.push_back(commandLine);
  549. }
  550. // Check for extra object-file dependencies.
  551. std::vector<std::string> depends;
  552. const char* additionalDeps = source.GetProperty("OBJECT_DEPENDS");
  553. if(additionalDeps)
  554. {
  555. cmSystemTools::ExpandListArgument(additionalDeps, depends);
  556. }
  557. // Generate a meaningful comment for the command.
  558. std::string comment = "Building ";
  559. comment += lang;
  560. comment += " object ";
  561. comment += this->Convert(ofname, START_OUTPUT);
  562. // Add the custom command to build the object file.
  563. this->Makefile->AddCustomCommandToOutput(
  564. ofname,
  565. depends,
  566. source.GetFullPath().c_str(),
  567. commandLines,
  568. comment.c_str(),
  569. this->Makefile->GetStartOutputDirectory()
  570. );
  571. }
  572. void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target)
  573. {
  574. cmStdString objs;
  575. std::vector<std::string> objVector;
  576. // Add all the sources outputs to the depends of the target
  577. std::vector<cmSourceFile*> const& classes = target.GetSourceFiles();
  578. for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
  579. i != classes.end(); ++i)
  580. {
  581. cmSourceFile* sf = *i;
  582. if(!sf->GetCustomCommand() &&
  583. !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
  584. !sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
  585. {
  586. std::string::size_type dir_len = 0;
  587. dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
  588. dir_len += 1;
  589. std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_len);
  590. if(!obj.empty())
  591. {
  592. std::string ofname = this->Makefile->GetCurrentOutputDirectory();
  593. ofname += "/";
  594. ofname += obj;
  595. objVector.push_back(ofname);
  596. this->AddCustomCommandToCreateObject(ofname.c_str(),
  597. llang, *(*i), target);
  598. objs += this->Convert(ofname.c_str(),START_OUTPUT,MAKEFILE);
  599. objs += " ";
  600. }
  601. }
  602. }
  603. std::string createRule = "CMAKE_";
  604. createRule += llang;
  605. createRule += target.GetCreateRuleVariable();
  606. std::string targetName = target.GetFullName();
  607. // Executable :
  608. // Shared Library:
  609. // Static Library:
  610. // Shared Module:
  611. std::string linkLibs; // should be set
  612. std::string flags; // should be set
  613. std::string linkFlags; // should be set
  614. this->GetTargetFlags(linkLibs, flags, linkFlags, target);
  615. cmLocalGenerator::RuleVariables vars;
  616. vars.Language = llang;
  617. vars.Objects = objs.c_str();
  618. vars.ObjectDir = ".";
  619. vars.Target = targetName.c_str();
  620. vars.LinkLibraries = linkLibs.c_str();
  621. vars.Flags = flags.c_str();
  622. vars.LinkFlags = linkFlags.c_str();
  623. std::string langFlags;
  624. this->AddLanguageFlags(langFlags, llang, 0);
  625. vars.LanguageCompileFlags = langFlags.c_str();
  626. cmCustomCommandLines commandLines;
  627. std::vector<std::string> rules;
  628. rules.push_back(this->Makefile->GetRequiredDefinition(createRule.c_str()));
  629. std::vector<std::string> commands;
  630. cmSystemTools::ExpandList(rules, commands);
  631. for(std::vector<std::string>::iterator i = commands.begin();
  632. i != commands.end(); ++i)
  633. {
  634. // Expand the full command line string.
  635. this->ExpandRuleVariables(*i, vars);
  636. // Parse the string to get the custom command line.
  637. cmCustomCommandLine commandLine;
  638. std::vector<cmStdString> cmd = cmSystemTools::ParseArguments(i->c_str());
  639. for(std::vector<cmStdString>::iterator a = cmd.begin();
  640. a != cmd.end(); ++a)
  641. {
  642. commandLine.push_back(*a);
  643. }
  644. // Store this command line.
  645. commandLines.push_back(commandLine);
  646. }
  647. std::string targetFullPath = target.GetFullPath();
  648. // Generate a meaningful comment for the command.
  649. std::string comment = "Linking ";
  650. comment += llang;
  651. comment += " target ";
  652. comment += this->Convert(targetFullPath.c_str(), START_OUTPUT);
  653. this->Makefile->AddCustomCommandToOutput(
  654. targetFullPath.c_str(),
  655. objVector,
  656. 0,
  657. commandLines,
  658. comment.c_str(),
  659. this->Makefile->GetStartOutputDirectory()
  660. );
  661. target.AddSourceFile
  662. (this->Makefile->GetSource(targetFullPath.c_str()));
  663. }
  664. void cmLocalGenerator
  665. ::CreateCustomTargetsAndCommands(std::set<cmStdString> const& lang)
  666. {
  667. cmTargets &tgts = this->Makefile->GetTargets();
  668. for(cmTargets::iterator l = tgts.begin();
  669. l != tgts.end(); l++)
  670. {
  671. cmTarget& target = l->second;
  672. switch(target.GetType())
  673. {
  674. case cmTarget::STATIC_LIBRARY:
  675. case cmTarget::SHARED_LIBRARY:
  676. case cmTarget::MODULE_LIBRARY:
  677. case cmTarget::EXECUTABLE:
  678. {
  679. const char* llang =
  680. target.GetLinkerLanguage(this->GetGlobalGenerator());
  681. if(!llang)
  682. {
  683. cmSystemTools::Error
  684. ("CMake can not determine linker language for target:",
  685. target.GetName());
  686. return;
  687. }
  688. // if the language is not in the set lang then create custom
  689. // commands to build the target
  690. if(lang.count(llang) == 0)
  691. {
  692. this->AddBuildTargetRule(llang, target);
  693. }
  694. }
  695. break;
  696. case cmTarget::UTILITY:
  697. case cmTarget::GLOBAL_TARGET:
  698. case cmTarget::INSTALL_FILES:
  699. case cmTarget::INSTALL_PROGRAMS:
  700. case cmTarget::INSTALL_DIRECTORY:
  701. break;
  702. }
  703. }
  704. }
  705. // List of variables that are replaced when
  706. // rules are expanced. These variables are
  707. // replaced in the form <var> with GetSafeDefinition(var).
  708. // ${LANG} is replaced in the variable first with all enabled
  709. // languages.
  710. static const char* ruleReplaceVars[] =
  711. {
  712. "CMAKE_${LANG}_COMPILER",
  713. "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
  714. "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
  715. "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
  716. "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
  717. "CMAKE_${LANG}_LINK_FLAGS",
  718. "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
  719. "CMAKE_${LANG}_ARCHIVE",
  720. "CMAKE_AR",
  721. "CMAKE_CURRENT_SOURCE_DIR",
  722. "CMAKE_CURRENT_BINARY_DIR",
  723. "CMAKE_RANLIB",
  724. "CMAKE_LINKER",
  725. 0
  726. };
  727. std::string
  728. cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
  729. const RuleVariables& replaceValues)
  730. {
  731. if(replaceValues.LinkFlags)
  732. {
  733. if(variable == "LINK_FLAGS")
  734. {
  735. return replaceValues.LinkFlags;
  736. }
  737. }
  738. if(replaceValues.Flags)
  739. {
  740. if(variable == "FLAGS")
  741. {
  742. return replaceValues.Flags;
  743. }
  744. }
  745. if(replaceValues.Source)
  746. {
  747. if(variable == "SOURCE")
  748. {
  749. return replaceValues.Source;
  750. }
  751. }
  752. if(replaceValues.PreprocessedSource)
  753. {
  754. if(variable == "PREPROCESSED_SOURCE")
  755. {
  756. return replaceValues.PreprocessedSource;
  757. }
  758. }
  759. if(replaceValues.AssemblySource)
  760. {
  761. if(variable == "ASSEMBLY_SOURCE")
  762. {
  763. return replaceValues.AssemblySource;
  764. }
  765. }
  766. if(replaceValues.Object)
  767. {
  768. if(variable == "OBJECT")
  769. {
  770. return replaceValues.Object;
  771. }
  772. }
  773. if(replaceValues.ObjectDir)
  774. {
  775. if(variable == "OBJECT_DIR")
  776. {
  777. return replaceValues.ObjectDir;
  778. }
  779. }
  780. if(replaceValues.Objects)
  781. {
  782. if(variable == "OBJECTS")
  783. {
  784. return replaceValues.Objects;
  785. }
  786. }
  787. if(replaceValues.ObjectsQuoted)
  788. {
  789. if(variable == "OBJECTS_QUOTED")
  790. {
  791. return replaceValues.ObjectsQuoted;
  792. }
  793. }
  794. if(replaceValues.TargetPDB )
  795. {
  796. if(variable == "TARGET_PDB")
  797. {
  798. return replaceValues.TargetPDB;
  799. }
  800. }
  801. if(replaceValues.Target)
  802. {
  803. if(variable == "TARGET_QUOTED")
  804. {
  805. std::string targetQuoted = replaceValues.Target;
  806. if(targetQuoted.size() && targetQuoted[0] != '\"')
  807. {
  808. targetQuoted = '\"';
  809. targetQuoted += replaceValues.Target;
  810. targetQuoted += '\"';
  811. }
  812. return targetQuoted;
  813. }
  814. if(replaceValues.LanguageCompileFlags)
  815. {
  816. if(variable == "LANGUAGE_COMPILE_FLAGS")
  817. {
  818. return replaceValues.LanguageCompileFlags;
  819. }
  820. }
  821. if(replaceValues.Target)
  822. {
  823. if(variable == "TARGET")
  824. {
  825. return replaceValues.Target;
  826. }
  827. }
  828. if(variable == "TARGET_IMPLIB")
  829. {
  830. return this->TargetImplib;
  831. }
  832. if(variable == "TARGET_VERSION_MAJOR")
  833. {
  834. if(replaceValues.TargetVersionMajor)
  835. {
  836. return replaceValues.TargetVersionMajor;
  837. }
  838. else
  839. {
  840. return "0";
  841. }
  842. }
  843. if(variable == "TARGET_VERSION_MINOR")
  844. {
  845. if(replaceValues.TargetVersionMinor)
  846. {
  847. return replaceValues.TargetVersionMinor;
  848. }
  849. else
  850. {
  851. return "0";
  852. }
  853. }
  854. if(replaceValues.Target)
  855. {
  856. if(variable == "TARGET_BASE")
  857. {
  858. // Strip the last extension off the target name.
  859. std::string targetBase = replaceValues.Target;
  860. std::string::size_type pos = targetBase.rfind(".");
  861. if(pos != targetBase.npos)
  862. {
  863. return targetBase.substr(0, pos);
  864. }
  865. else
  866. {
  867. return targetBase;
  868. }
  869. }
  870. }
  871. }
  872. if(replaceValues.TargetSOName)
  873. {
  874. if(variable == "TARGET_SONAME")
  875. {
  876. if(replaceValues.Language)
  877. {
  878. std::string name = "CMAKE_SHARED_LIBRARY_SONAME_";
  879. name += replaceValues.Language;
  880. name += "_FLAG";
  881. if(this->Makefile->GetDefinition(name.c_str()))
  882. {
  883. return replaceValues.TargetSOName;
  884. }
  885. }
  886. return "";
  887. }
  888. }
  889. if(replaceValues.TargetInstallNameDir)
  890. {
  891. if(variable == "TARGET_INSTALLNAME_DIR")
  892. {
  893. return replaceValues.TargetInstallNameDir;
  894. }
  895. }
  896. if(replaceValues.LinkLibraries)
  897. {
  898. if(variable == "LINK_LIBRARIES")
  899. {
  900. return replaceValues.LinkLibraries;
  901. }
  902. }
  903. std::vector<std::string> enabledLanguages;
  904. this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
  905. // loop over language specific replace variables
  906. int pos = 0;
  907. while(ruleReplaceVars[pos])
  908. {
  909. for(std::vector<std::string>::iterator i = enabledLanguages.begin();
  910. i != enabledLanguages.end(); ++i)
  911. {
  912. const char* lang = i->c_str();
  913. std::string actualReplace = ruleReplaceVars[pos];
  914. // If this is the compiler then look for the extra variable
  915. // _COMPILER_ARG1 which must be the first argument to the compiler
  916. const char* compilerArg1 = 0;
  917. if(actualReplace == "CMAKE_${LANG}_COMPILER")
  918. {
  919. std::string arg1 = actualReplace + "_ARG1";
  920. cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
  921. compilerArg1 = this->Makefile->GetDefinition(arg1.c_str());
  922. }
  923. if(actualReplace.find("${LANG}") != actualReplace.npos)
  924. {
  925. cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
  926. }
  927. if(actualReplace == variable)
  928. {
  929. std::string replace =
  930. this->Makefile->GetSafeDefinition(variable.c_str());
  931. // if the variable is not a FLAG then treat it like a path
  932. if(variable.find("_FLAG") == variable.npos)
  933. {
  934. std::string ret = this->ConvertToOutputForExisting(replace.c_str());
  935. // if there is a required first argument to the compiler add it
  936. // to the compiler string
  937. if(compilerArg1)
  938. {
  939. ret += " ";
  940. ret += compilerArg1;
  941. }
  942. return ret;
  943. }
  944. return replace;
  945. }
  946. }
  947. pos++;
  948. }
  949. return variable;
  950. }
  951. void
  952. cmLocalGenerator::ExpandRuleVariables(std::string& s,
  953. const RuleVariables& replaceValues)
  954. {
  955. std::vector<std::string> enabledLanguages;
  956. this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
  957. std::string::size_type start = s.find('<');
  958. // no variables to expand
  959. if(start == s.npos)
  960. {
  961. return;
  962. }
  963. std::string::size_type pos = 0;
  964. std::string expandedInput;
  965. while(start != s.npos && start < s.size()-2)
  966. {
  967. std::string::size_type end = s.find('>', start);
  968. // if we find a < with no > we are done
  969. if(end == s.npos)
  970. {
  971. return;
  972. }
  973. char c = s[start+1];
  974. // if the next char after the < is not A-Za-z then
  975. // skip it and try to find the next < in the string
  976. if(!isalpha(c))
  977. {
  978. start = s.find('<', start+1);
  979. }
  980. else
  981. {
  982. // extract the var
  983. std::string var = s.substr(start+1, end - start-1);
  984. std::string replace = this->ExpandRuleVariable(var,
  985. replaceValues);
  986. expandedInput += s.substr(pos, start-pos);
  987. expandedInput += replace;
  988. // move to next one
  989. start = s.find('<', start+var.size()+2);
  990. pos = end+1;
  991. }
  992. }
  993. // add the rest of the input
  994. expandedInput += s.substr(pos, s.size()-pos);
  995. s = expandedInput;
  996. }
  997. std::string
  998. cmLocalGenerator::ConvertToOutputForExisting(const char* p)
  999. {
  1000. std::string ret = p;
  1001. if(this->WindowsShell && ret.find(' ') != ret.npos
  1002. && cmSystemTools::FileExists(p))
  1003. {
  1004. if(cmSystemTools::GetShortPath(p, ret))
  1005. {
  1006. return this->Convert(ret.c_str(), NONE, SHELL, true);
  1007. }
  1008. }
  1009. return this->Convert(p, START_OUTPUT, SHELL, true);
  1010. }
  1011. const char* cmLocalGenerator::GetIncludeFlags(const char* lang)
  1012. {
  1013. if(!lang)
  1014. {
  1015. return "";
  1016. }
  1017. if(this->LanguageToIncludeFlags.count(lang))
  1018. {
  1019. return this->LanguageToIncludeFlags[lang].c_str();
  1020. }
  1021. cmOStringStream includeFlags;
  1022. std::vector<std::string> includes;
  1023. this->GetIncludeDirectories(includes);
  1024. std::vector<std::string>::iterator i;
  1025. std::string flagVar = "CMAKE_INCLUDE_FLAG_";
  1026. flagVar += lang;
  1027. const char* includeFlag =
  1028. this->Makefile->GetSafeDefinition(flagVar.c_str());
  1029. flagVar = "CMAKE_INCLUDE_FLAG_SEP_";
  1030. flagVar += lang;
  1031. const char* sep = this->Makefile->GetDefinition(flagVar.c_str());
  1032. bool quotePaths = false;
  1033. if(this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS"))
  1034. {
  1035. quotePaths = true;
  1036. }
  1037. bool repeatFlag = true;
  1038. // should the include flag be repeated like ie. -IA -IB
  1039. if(!sep)
  1040. {
  1041. sep = " ";
  1042. }
  1043. else
  1044. {
  1045. // if there is a separator then the flag is not repeated but is only
  1046. // given once i.e. -classpath a:b:c
  1047. repeatFlag = false;
  1048. }
  1049. // Support special system include flag if it is available and the
  1050. // normal flag is repeated for each directory.
  1051. std::string sysFlagVar = "CMAKE_INCLUDE_SYSTEM_FLAG_";
  1052. sysFlagVar += lang;
  1053. const char* sysIncludeFlag = 0;
  1054. if(repeatFlag)
  1055. {
  1056. sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar.c_str());
  1057. }
  1058. bool flagUsed = false;
  1059. std::set<cmStdString> emitted;
  1060. #ifdef __APPLE__
  1061. emitted.insert("/System/Library/Frameworks");
  1062. #endif
  1063. for(i = includes.begin(); i != includes.end(); ++i)
  1064. {
  1065. #ifdef __APPLE__
  1066. if(cmSystemTools::IsPathToFramework(i->c_str()))
  1067. {
  1068. std::string frameworkDir = *i;
  1069. frameworkDir += "/../";
  1070. frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
  1071. if(emitted.insert(frameworkDir).second)
  1072. {
  1073. includeFlags
  1074. << "-F"
  1075. << this->ConvertToOutputForExisting(frameworkDir.c_str()) << " ";
  1076. }
  1077. continue;
  1078. }
  1079. #endif
  1080. std::string include = *i;
  1081. if(!flagUsed || repeatFlag)
  1082. {
  1083. if(sysIncludeFlag &&
  1084. this->Makefile->IsSystemIncludeDirectory(i->c_str()))
  1085. {
  1086. includeFlags << sysIncludeFlag;
  1087. }
  1088. else
  1089. {
  1090. includeFlags << includeFlag;
  1091. }
  1092. flagUsed = true;
  1093. }
  1094. std::string includePath = this->ConvertToOutputForExisting(i->c_str());
  1095. if(quotePaths && includePath.size() && includePath[0] != '\"')
  1096. {
  1097. includeFlags << "\"";
  1098. }
  1099. includeFlags << includePath;
  1100. if(quotePaths && includePath.size() && includePath[0] != '\"')
  1101. {
  1102. includeFlags << "\"";
  1103. }
  1104. includeFlags << sep;
  1105. }
  1106. std::string flags = includeFlags.str();
  1107. // remove trailing separators
  1108. if((sep[0] != ' ') && flags[flags.size()-1] == sep[0])
  1109. {
  1110. flags[flags.size()-1] = ' ';
  1111. }
  1112. flags += this->Makefile->GetDefineFlags();
  1113. this->LanguageToIncludeFlags[lang] = flags;
  1114. // Use this temorary variable for the return value to work-around a
  1115. // bogus GCC 2.95 warning.
  1116. const char* ret = this->LanguageToIncludeFlags[lang].c_str();
  1117. return ret;
  1118. }
  1119. //----------------------------------------------------------------------------
  1120. void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
  1121. bool filter_system_dirs)
  1122. {
  1123. // Need to decide whether to automatically include the source and
  1124. // binary directories at the beginning of the include path.
  1125. bool includeSourceDir = false;
  1126. bool includeBinaryDir = false;
  1127. // When automatic include directories are requested for a build then
  1128. // include the source and binary directories at the beginning of the
  1129. // include path to approximate include file behavior for an
  1130. // in-source build. This does not account for the case of a source
  1131. // file in a subdirectory of the current source directory but we
  1132. // cannot fix this because not all native build tools support
  1133. // per-source-file include paths.
  1134. if(this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR"))
  1135. {
  1136. includeSourceDir = true;
  1137. includeBinaryDir = true;
  1138. }
  1139. // CMake versions below 2.0 would add the source tree to the -I path
  1140. // automatically. Preserve compatibility.
  1141. const char* versionValue =
  1142. this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
  1143. int major = 0;
  1144. int minor = 0;
  1145. if(versionValue && sscanf(versionValue, "%d.%d", &major, &minor) != 2)
  1146. {
  1147. versionValue = 0;
  1148. }
  1149. if(versionValue && major < 2)
  1150. {
  1151. includeSourceDir = true;
  1152. }
  1153. // Hack for VTK 4.0 - 4.4 which depend on the old behavior but do
  1154. // not set the backwards compatibility level automatically.
  1155. const char* vtkSourceDir =
  1156. this->Makefile->GetDefinition("VTK_SOURCE_DIR");
  1157. if(vtkSourceDir)
  1158. {
  1159. const char* vtk_major =
  1160. this->Makefile->GetDefinition("VTK_MAJOR_VERSION");
  1161. const char* vtk_minor =
  1162. this->Makefile->GetDefinition("VTK_MINOR_VERSION");
  1163. vtk_major = vtk_major? vtk_major : "4";
  1164. vtk_minor = vtk_minor? vtk_minor : "4";
  1165. int vmajor = 0;
  1166. int vminor = 0;
  1167. if(sscanf(vtk_major, "%d", &vmajor) &&
  1168. sscanf(vtk_minor, "%d", &vminor) && vmajor == 4 && vminor <= 4)
  1169. {
  1170. includeSourceDir = true;
  1171. }
  1172. }
  1173. // Do not repeat an include path.
  1174. std::set<cmStdString> emitted;
  1175. // Store the automatic include paths.
  1176. if(includeBinaryDir)
  1177. {
  1178. dirs.push_back(this->Makefile->GetStartOutputDirectory());
  1179. emitted.insert(this->Makefile->GetStartOutputDirectory());
  1180. }
  1181. if(includeSourceDir)
  1182. {
  1183. if(emitted.find(this->Makefile->GetStartDirectory()) == emitted.end())
  1184. {
  1185. dirs.push_back(this->Makefile->GetStartDirectory());
  1186. emitted.insert(this->Makefile->GetStartDirectory());
  1187. }
  1188. }
  1189. if(filter_system_dirs)
  1190. {
  1191. // Do not explicitly add the standard include path "/usr/include".
  1192. // This can cause problems with certain standard library
  1193. // implementations because the wrong headers may be found first.
  1194. emitted.insert("/usr/include");
  1195. if(const char* implicitIncludes = this->Makefile->GetDefinition
  1196. ("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES"))
  1197. {
  1198. std::vector<std::string> implicitIncludeVec;
  1199. cmSystemTools::ExpandListArgument(implicitIncludes, implicitIncludeVec);
  1200. for(unsigned int k = 0; k < implicitIncludeVec.size(); ++k)
  1201. {
  1202. emitted.insert(implicitIncludeVec[k]);
  1203. }
  1204. }
  1205. }
  1206. // Get the project-specified include directories.
  1207. std::vector<std::string>& includes =
  1208. this->Makefile->GetIncludeDirectories();
  1209. // Support putting all the in-project include directories first if
  1210. // it is requested by the project.
  1211. if(this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"))
  1212. {
  1213. const char* topSourceDir = this->Makefile->GetHomeDirectory();
  1214. const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
  1215. for(std::vector<std::string>::iterator i = includes.begin();
  1216. i != includes.end(); ++i)
  1217. {
  1218. // Emit this directory only if it is a subdirectory of the
  1219. // top-level source or binary tree.
  1220. if(cmSystemTools::ComparePath(i->c_str(), topSourceDir) ||
  1221. cmSystemTools::ComparePath(i->c_str(), topBinaryDir) ||
  1222. cmSystemTools::IsSubDirectory(i->c_str(), topSourceDir) ||
  1223. cmSystemTools::IsSubDirectory(i->c_str(), topBinaryDir))
  1224. {
  1225. if(emitted.insert(*i).second)
  1226. {
  1227. dirs.push_back(*i);
  1228. }
  1229. }
  1230. }
  1231. }
  1232. // Construct the final ordered include directory list.
  1233. for(std::vector<std::string>::iterator i = includes.begin();
  1234. i != includes.end(); ++i)
  1235. {
  1236. if(emitted.insert(*i).second)
  1237. {
  1238. dirs.push_back(*i);
  1239. }
  1240. }
  1241. }
  1242. void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
  1243. std::string& flags,
  1244. std::string& linkFlags,
  1245. cmTarget& target)
  1246. {
  1247. std::string buildType =
  1248. this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
  1249. buildType = cmSystemTools::UpperCase(buildType);
  1250. const char* libraryLinkVariable =
  1251. "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
  1252. switch(target.GetType())
  1253. {
  1254. case cmTarget::STATIC_LIBRARY:
  1255. {
  1256. const char* targetLinkFlags =
  1257. target.GetProperty("STATIC_LIBRARY_FLAGS");
  1258. if(targetLinkFlags)
  1259. {
  1260. linkFlags += targetLinkFlags;
  1261. linkFlags += " ";
  1262. }
  1263. }
  1264. break;
  1265. case cmTarget::MODULE_LIBRARY:
  1266. libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
  1267. case cmTarget::SHARED_LIBRARY:
  1268. {
  1269. linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
  1270. linkFlags += " ";
  1271. if(buildType.size())
  1272. {
  1273. std::string build = libraryLinkVariable;
  1274. build += "_";
  1275. build += buildType;
  1276. linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
  1277. linkFlags += " ";
  1278. }
  1279. if(this->Makefile->IsOn("WIN32") &&
  1280. !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
  1281. {
  1282. const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
  1283. for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
  1284. i != sources.end(); ++i)
  1285. {
  1286. cmSourceFile* sf = *i;
  1287. if(sf->GetExtension() == "def")
  1288. {
  1289. linkFlags +=
  1290. this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
  1291. linkFlags += this->Convert(sf->GetFullPath().c_str(),
  1292. START_OUTPUT, SHELL);
  1293. linkFlags += " ";
  1294. }
  1295. }
  1296. }
  1297. const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
  1298. if(targetLinkFlags)
  1299. {
  1300. linkFlags += targetLinkFlags;
  1301. linkFlags += " ";
  1302. std::string configLinkFlags = targetLinkFlags;
  1303. configLinkFlags += buildType;
  1304. targetLinkFlags = target.GetProperty(configLinkFlags.c_str());
  1305. if(targetLinkFlags)
  1306. {
  1307. linkFlags += targetLinkFlags;
  1308. linkFlags += " ";
  1309. }
  1310. }
  1311. cmOStringStream linklibsStr;
  1312. this->OutputLinkLibraries(linklibsStr, target, false);
  1313. linkLibs = linklibsStr.str();
  1314. }
  1315. break;
  1316. case cmTarget::EXECUTABLE:
  1317. {
  1318. linkFlags +=
  1319. this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
  1320. linkFlags += " ";
  1321. if(buildType.size())
  1322. {
  1323. std::string build = "CMAKE_EXE_LINKER_FLAGS_";
  1324. build += buildType;
  1325. linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
  1326. linkFlags += " ";
  1327. }
  1328. const char* linkLanguage =
  1329. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1330. if(!linkLanguage)
  1331. {
  1332. cmSystemTools::Error
  1333. ("CMake can not determine linker language for target:",
  1334. target.GetName());
  1335. return;
  1336. }
  1337. std::string langVar = "CMAKE_";
  1338. langVar += linkLanguage;
  1339. std::string flagsVar = langVar + "_FLAGS";
  1340. std::string sharedFlagsVar = "CMAKE_SHARED_LIBRARY_";
  1341. sharedFlagsVar += linkLanguage;
  1342. sharedFlagsVar += "_FLAGS";
  1343. flags += this->Makefile->GetSafeDefinition(flagsVar.c_str());
  1344. flags += " ";
  1345. flags += this->Makefile->GetSafeDefinition(sharedFlagsVar.c_str());
  1346. flags += " ";
  1347. cmOStringStream linklibs;
  1348. this->OutputLinkLibraries(linklibs, target, false);
  1349. linkLibs = linklibs.str();
  1350. if(cmSystemTools::IsOn
  1351. (this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
  1352. {
  1353. std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_")
  1354. + linkLanguage + std::string("_FLAGS");
  1355. linkFlags += this->Makefile->GetSafeDefinition(sFlagVar.c_str());
  1356. linkFlags += " ";
  1357. }
  1358. if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
  1359. {
  1360. linkFlags +=
  1361. this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
  1362. linkFlags += " ";
  1363. }
  1364. else
  1365. {
  1366. linkFlags +=
  1367. this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
  1368. linkFlags += " ";
  1369. }
  1370. const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
  1371. if(targetLinkFlags)
  1372. {
  1373. linkFlags += targetLinkFlags;
  1374. linkFlags += " ";
  1375. std::string configLinkFlags = targetLinkFlags;
  1376. configLinkFlags += buildType;
  1377. targetLinkFlags = target.GetProperty(configLinkFlags.c_str());
  1378. if(targetLinkFlags)
  1379. {
  1380. linkFlags += targetLinkFlags;
  1381. linkFlags += " ";
  1382. }
  1383. }
  1384. }
  1385. break;
  1386. case cmTarget::UTILITY:
  1387. case cmTarget::GLOBAL_TARGET:
  1388. case cmTarget::INSTALL_FILES:
  1389. case cmTarget::INSTALL_PROGRAMS:
  1390. case cmTarget::INSTALL_DIRECTORY:
  1391. break;
  1392. }
  1393. }
  1394. /**
  1395. * Output the linking rules on a command line. For executables,
  1396. * targetLibrary should be a NULL pointer. For libraries, it should point
  1397. * to the name of the library. This will not link a library against itself.
  1398. */
  1399. void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
  1400. cmTarget& tgt,
  1401. bool relink)
  1402. {
  1403. // Try to emit each search path once
  1404. std::set<cmStdString> emitted;
  1405. // Embed runtime search paths if possible and if required.
  1406. bool outputRuntime = true;
  1407. std::string runtimeFlag;
  1408. std::string runtimeSep;
  1409. const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
  1410. const char* linkLanguage =
  1411. tgt.GetLinkerLanguage(this->GetGlobalGenerator());
  1412. if(!linkLanguage)
  1413. {
  1414. cmSystemTools::
  1415. Error("CMake can not determine linker language for target:",
  1416. tgt.GetName());
  1417. return;
  1418. }
  1419. std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
  1420. runTimeFlagVar += linkLanguage;
  1421. runTimeFlagVar += "_FLAG";
  1422. std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
  1423. runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
  1424. runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
  1425. // concatenate all paths or no?
  1426. bool runtimeConcatenate = ( runtimeSep!="" );
  1427. if(runtimeFlag == "" || this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
  1428. {
  1429. outputRuntime = false;
  1430. }
  1431. // Some search paths should never be emitted
  1432. emitted.insert("");
  1433. if(const char* implicitLinks =
  1434. (this->Makefile->GetDefinition
  1435. ("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES")))
  1436. {
  1437. std::vector<std::string> implicitLinkVec;
  1438. cmSystemTools::ExpandListArgument(implicitLinks, implicitLinkVec);
  1439. for(unsigned int k = 0; k < implicitLinkVec.size(); ++k)
  1440. {
  1441. emitted.insert(implicitLinkVec[k]);
  1442. }
  1443. }
  1444. std::string libPathFlag =
  1445. this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
  1446. std::string libPathTerminator =
  1447. this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
  1448. std::string libLinkFlag =
  1449. this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
  1450. // collect all the flags needed for linking libraries
  1451. std::string linkLibs;
  1452. // Flags to link an executable to shared libraries.
  1453. std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
  1454. linkFlagsVar += linkLanguage;
  1455. linkFlagsVar += "_FLAGS";
  1456. if( tgt.GetType() == cmTarget::EXECUTABLE )
  1457. {
  1458. linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar.c_str());
  1459. linkLibs += " ";
  1460. }
  1461. // Compute the link library and directory information.
  1462. std::vector<cmStdString> libNames;
  1463. std::vector<cmStdString> libDirs;
  1464. this->ComputeLinkInformation(tgt, config, libNames, libDirs);
  1465. // Select whether to generate an rpath for the install tree or the
  1466. // build tree.
  1467. bool linking_for_install =
  1468. relink || tgt.GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
  1469. bool use_install_rpath =
  1470. outputRuntime && tgt.HaveInstallTreeRPATH() && linking_for_install;
  1471. bool use_build_rpath =
  1472. outputRuntime && tgt.HaveBuildTreeRPATH() && !linking_for_install;
  1473. bool use_link_rpath =
  1474. outputRuntime && linking_for_install &&
  1475. tgt.GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
  1476. // Construct the RPATH.
  1477. std::vector<std::string> runtimeDirs;
  1478. if(use_install_rpath)
  1479. {
  1480. const char* install_rpath = tgt.GetProperty("INSTALL_RPATH");
  1481. cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
  1482. for(unsigned int i=0; i < runtimeDirs.size(); ++i)
  1483. {
  1484. runtimeDirs[i] =
  1485. this->Convert(runtimeDirs[i].c_str(), FULL, SHELL, false);
  1486. }
  1487. }
  1488. // Append the library search path flags.
  1489. for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
  1490. libDir != libDirs.end(); ++libDir)
  1491. {
  1492. std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
  1493. if(emitted.insert(libpath).second)
  1494. {
  1495. std::string fullLibPath;
  1496. if(!this->WindowsShell && this->UseRelativePaths)
  1497. {
  1498. fullLibPath = "\"`cd ";
  1499. }
  1500. fullLibPath += libpath;
  1501. if(!this->WindowsShell && this->UseRelativePaths)
  1502. {
  1503. fullLibPath += ";pwd`\"";
  1504. }
  1505. std::string::size_type pos = libDir->find(libPathFlag.c_str());
  1506. if((pos == std::string::npos || pos > 0)
  1507. && libDir->find("${") == std::string::npos)
  1508. {
  1509. linkLibs += libPathFlag;
  1510. linkLibs += fullLibPath;
  1511. linkLibs += libPathTerminator;
  1512. linkLibs += " ";
  1513. // Put this directory in the rpath if using build-tree rpath
  1514. // support or if using the link path as an rpath.
  1515. if(use_build_rpath)
  1516. {
  1517. runtimeDirs.push_back(fullLibPath);
  1518. }
  1519. else if(use_link_rpath)
  1520. {
  1521. // Do not add any path inside the source or build tree.
  1522. const char* topSourceDir = this->Makefile->GetHomeDirectory();
  1523. const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
  1524. if(!cmSystemTools::ComparePath(libDir->c_str(), topSourceDir) &&
  1525. !cmSystemTools::ComparePath(libDir->c_str(), topBinaryDir) &&
  1526. !cmSystemTools::IsSubDirectory(libDir->c_str(), topSourceDir) &&
  1527. !cmSystemTools::IsSubDirectory(libDir->c_str(), topBinaryDir))
  1528. {
  1529. runtimeDirs.push_back(fullLibPath);
  1530. }
  1531. }
  1532. }
  1533. }
  1534. }
  1535. // Append the link libraries.
  1536. for(std::vector<cmStdString>::iterator lib = libNames.begin();
  1537. lib != libNames.end(); ++lib)
  1538. {
  1539. linkLibs += *lib;
  1540. linkLibs += " ";
  1541. }
  1542. fout << linkLibs;
  1543. if(!runtimeDirs.empty())
  1544. {
  1545. // For the runtime search directories, do a "-Wl,-rpath,a:b:c" or
  1546. // a "-R a -R b -R c" type link line
  1547. fout << runtimeFlag;
  1548. std::vector<std::string>::iterator itr = runtimeDirs.begin();
  1549. fout << *itr;
  1550. ++itr;
  1551. for( ; itr != runtimeDirs.end(); ++itr )
  1552. {
  1553. if(runtimeConcatenate)
  1554. {
  1555. fout << runtimeSep << *itr;
  1556. }
  1557. else
  1558. {
  1559. fout << " " << runtimeFlag << *itr;
  1560. }
  1561. }
  1562. fout << " ";
  1563. }
  1564. // Add standard libraries for this language.
  1565. std::string standardLibsVar = "CMAKE_";
  1566. standardLibsVar += linkLanguage;
  1567. standardLibsVar += "_STANDARD_LIBRARIES";
  1568. if(const char* stdLibs =
  1569. this->Makefile->GetDefinition(standardLibsVar.c_str()))
  1570. {
  1571. fout << stdLibs << " ";
  1572. }
  1573. }
  1574. //----------------------------------------------------------------------------
  1575. void cmLocalGenerator
  1576. ::ComputeLinkInformation(cmTarget& target,
  1577. const char* config,
  1578. std::vector<cmStdString>& outLibs,
  1579. std::vector<cmStdString>& outDirs,
  1580. std::vector<cmStdString>* fullPathLibs)
  1581. {
  1582. // Compute which library configuration to link.
  1583. cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
  1584. if(config && cmSystemTools::UpperCase(config) == "DEBUG")
  1585. {
  1586. linkType = cmTarget::DEBUG;
  1587. }
  1588. // Get the language used for linking.
  1589. const char* linkLanguage =
  1590. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1591. // Check whether we should use an import library for linking a target.
  1592. bool implib =
  1593. this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")?true:false;
  1594. // On platforms without import libraries there may be a special flag
  1595. // to use when creating a plugin (module) that obtains symbols from
  1596. // the program that will load it.
  1597. const char* loader_flag = 0;
  1598. if(!implib && target.GetType() == cmTarget::MODULE_LIBRARY)
  1599. {
  1600. if(!linkLanguage)
  1601. {
  1602. cmSystemTools::
  1603. Error("CMake can not determine linker language for target:",
  1604. target.GetName());
  1605. return;
  1606. }
  1607. std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
  1608. loader_flag_var += linkLanguage;
  1609. loader_flag_var += "_FLAG";
  1610. loader_flag = this->Makefile->GetDefinition(loader_flag_var.c_str());
  1611. }
  1612. // Get the list of libraries against which this target wants to link.
  1613. std::vector<std::string> linkLibraries;
  1614. const cmTarget::LinkLibraryVectorType& inLibs = target.GetLinkLibraries();
  1615. for(cmTarget::LinkLibraryVectorType::const_iterator j = inLibs.begin();
  1616. j != inLibs.end(); ++j)
  1617. {
  1618. // For backwards compatibility variables may have been expanded
  1619. // inside library names. Clean up the resulting name.
  1620. std::string lib = j->first;
  1621. std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
  1622. if(pos != lib.npos)
  1623. {
  1624. lib = lib.substr(pos, lib.npos);
  1625. }
  1626. pos = lib.find_last_not_of(" \t\r\n");
  1627. if(pos != lib.npos)
  1628. {
  1629. lib = lib.substr(0, pos+1);
  1630. }
  1631. if(lib.empty())
  1632. {
  1633. continue;
  1634. }
  1635. // Link to a library if it is not the same target and is meant for
  1636. // this configuration type.
  1637. if((target.GetType() == cmTarget::EXECUTABLE ||
  1638. lib != target.GetName()) &&
  1639. (j->second == cmTarget::GENERAL || j->second == linkType))
  1640. {
  1641. // Compute the proper name to use to link this library.
  1642. cmTarget* tgt = this->GlobalGenerator->FindTarget(0, lib.c_str(), false);
  1643. bool impexe = (tgt &&
  1644. tgt->GetType() == cmTarget::EXECUTABLE &&
  1645. tgt->GetPropertyAsBool("ENABLE_EXPORTS"));
  1646. if(impexe && !implib && !loader_flag)
  1647. {
  1648. // Skip linking to executables on platforms with no import
  1649. // libraries or loader flags.
  1650. continue;
  1651. }
  1652. else if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY ||
  1653. tgt->GetType() == cmTarget::SHARED_LIBRARY ||
  1654. tgt->GetType() == cmTarget::MODULE_LIBRARY ||
  1655. impexe))
  1656. {
  1657. // This is a CMake target. Ask the target for its real name.
  1658. std::string linkItem;
  1659. if(impexe && loader_flag)
  1660. {
  1661. // This link item is an executable that may provide symbols
  1662. // used by this target. A special flag is needed on this
  1663. // platform. Add it now.
  1664. std::string exe = tgt->GetFullPath(config, implib);
  1665. linkItem += loader_flag;
  1666. linkItem += this->Convert(exe.c_str(), NONE, SHELL, false);
  1667. }
  1668. else
  1669. {
  1670. // Pass the full path to the target file but purposely leave
  1671. // off the per-configuration subdirectory. The link directory
  1672. // ordering knows how to deal with this.
  1673. linkItem += tgt->GetDirectory(0, implib);
  1674. // on apple if the FRAMEWORK prop is set, then
  1675. // do not add the target full name but just use the directory
  1676. // name
  1677. #ifdef __APPLE__
  1678. if (!(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
  1679. tgt->GetPropertyAsBool("FRAMEWORK")))
  1680. #endif
  1681. {
  1682. linkItem += "/";
  1683. linkItem += tgt->GetFullName(config, implib);
  1684. }
  1685. }
  1686. linkLibraries.push_back(linkItem);
  1687. // For full path, use the true location.
  1688. if(fullPathLibs)
  1689. {
  1690. fullPathLibs->push_back(tgt->GetFullPath(config, implib));
  1691. }
  1692. }
  1693. else
  1694. {
  1695. // This is not a CMake target. Use the name given.
  1696. linkLibraries.push_back(lib);
  1697. // Add to the list of full paths if this library is one.
  1698. if(fullPathLibs &&
  1699. cmSystemTools::FileIsFullPath(lib.c_str()) &&
  1700. !cmSystemTools::FileIsDirectory(lib.c_str()))
  1701. {
  1702. fullPathLibs->push_back(lib);
  1703. }
  1704. }
  1705. }
  1706. }
  1707. // Get the list of directories the target wants to search for libraries.
  1708. const std::vector<std::string>&
  1709. linkDirectories = target.GetLinkDirectories();
  1710. // Lookup link type selection flags.
  1711. const char* static_link_type_flag = 0;
  1712. const char* shared_link_type_flag = 0;
  1713. const char* target_type_str = 0;
  1714. switch(target.GetType())
  1715. {
  1716. case cmTarget::EXECUTABLE: target_type_str = "EXE"; break;
  1717. case cmTarget::SHARED_LIBRARY: target_type_str = "SHARED_LIBRARY"; break;
  1718. case cmTarget::MODULE_LIBRARY: target_type_str = "SHARED_MODULE"; break;
  1719. default: break;
  1720. }
  1721. if(target_type_str)
  1722. {
  1723. if(!linkLanguage)
  1724. {
  1725. cmSystemTools::
  1726. Error("CMake can not determine linker language for target:",
  1727. target.GetName());
  1728. return;
  1729. }
  1730. std::string static_link_type_flag_var = "CMAKE_";
  1731. static_link_type_flag_var += target_type_str;
  1732. static_link_type_flag_var += "_LINK_STATIC_";
  1733. static_link_type_flag_var += linkLanguage;
  1734. static_link_type_flag_var += "_FLAGS";
  1735. static_link_type_flag =
  1736. this->Makefile->GetDefinition(static_link_type_flag_var.c_str());
  1737. std::string shared_link_type_flag_var = "CMAKE_";
  1738. shared_link_type_flag_var += target_type_str;
  1739. shared_link_type_flag_var += "_LINK_DYNAMIC_";
  1740. shared_link_type_flag_var += linkLanguage;
  1741. shared_link_type_flag_var += "_FLAGS";
  1742. shared_link_type_flag =
  1743. this->Makefile->GetDefinition(shared_link_type_flag_var.c_str());
  1744. }
  1745. // Compute the link directory order needed to link the libraries.
  1746. cmOrderLinkDirectories orderLibs;
  1747. orderLibs.SetLinkTypeInformation(cmOrderLinkDirectories::LinkShared,
  1748. static_link_type_flag,
  1749. shared_link_type_flag);
  1750. orderLibs.AddLinkPrefix(
  1751. this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_PREFIX"));
  1752. orderLibs.AddLinkPrefix(
  1753. this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_PREFIX"));
  1754. // Import library names should be matched and treated as shared
  1755. // libraries for the purposes of linking.
  1756. orderLibs.AddLinkExtension(
  1757. this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
  1758. cmOrderLinkDirectories::LinkShared);
  1759. orderLibs.AddLinkExtension(
  1760. this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"),
  1761. cmOrderLinkDirectories::LinkStatic);
  1762. orderLibs.AddLinkExtension(
  1763. this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"),
  1764. cmOrderLinkDirectories::LinkShared);
  1765. orderLibs.AddLinkExtension(
  1766. this->Makefile->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"));
  1767. if(const char* linkSuffixes =
  1768. this->Makefile->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS"))
  1769. {
  1770. std::vector<std::string> linkSuffixVec;
  1771. cmSystemTools::ExpandListArgument(linkSuffixes, linkSuffixVec);
  1772. for(std::vector<std::string>::iterator i = linkSuffixVec.begin();
  1773. i != linkSuffixVec.end(); ++i)
  1774. {
  1775. orderLibs.AddLinkExtension(i->c_str());
  1776. }
  1777. }
  1778. std::string configSubdir;
  1779. cmGlobalGenerator* gg = this->GetGlobalGenerator();
  1780. gg->AppendDirectoryForConfig("", config, "", configSubdir);
  1781. orderLibs.SetLinkInformation(target.GetName(),
  1782. linkLibraries,
  1783. linkDirectories,
  1784. gg->GetTargetManifest(),
  1785. configSubdir.c_str());
  1786. orderLibs.DetermineLibraryPathOrder();
  1787. std::vector<cmStdString> orderedLibs;
  1788. orderLibs.GetLinkerInformation(outDirs, orderedLibs);
  1789. // Make sure libraries are linked with the proper syntax.
  1790. std::string libLinkFlag =
  1791. this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
  1792. std::string libLinkSuffix =
  1793. this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
  1794. for(std::vector<cmStdString>::iterator l = orderedLibs.begin();
  1795. l != orderedLibs.end(); ++l)
  1796. {
  1797. std::string lib = *l;
  1798. if(lib[0] == '-' || lib[0] == '$' || lib[0] == '`')
  1799. {
  1800. // The library is linked with special syntax by the user.
  1801. outLibs.push_back(lib);
  1802. }
  1803. else
  1804. {
  1805. // Generate the proper link syntax.
  1806. lib = libLinkFlag;
  1807. lib += *l;
  1808. lib += libLinkSuffix;
  1809. outLibs.push_back(lib);
  1810. }
  1811. }
  1812. }
  1813. //----------------------------------------------------------------------------
  1814. void cmLocalGenerator::AddLanguageFlags(std::string& flags,
  1815. const char* lang,
  1816. const char* config)
  1817. {
  1818. // Add language-specific flags.
  1819. std::string flagsVar = "CMAKE_";
  1820. flagsVar += lang;
  1821. flagsVar += "_FLAGS";
  1822. if(this->EmitUniversalBinaryFlags)
  1823. {
  1824. const char* osxArch =
  1825. this->Makefile->GetDefinition("CMAKE_OSX_ARCHITECTURES");
  1826. const char* sysroot =
  1827. this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
  1828. if(osxArch && sysroot && lang && lang[0] =='C')
  1829. {
  1830. std::vector<std::string> archs;
  1831. cmSystemTools::ExpandListArgument(std::string(osxArch),
  1832. archs);
  1833. bool addArchFlag = true;
  1834. if(archs.size() == 1)
  1835. {
  1836. const char* archOrig =
  1837. this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
  1838. if(archs[0] == archOrig)
  1839. {
  1840. addArchFlag = false;
  1841. }
  1842. }
  1843. // if there is more than one arch add the -arch and
  1844. // -isysroot flags, or if there is one arch flag, but
  1845. // it is not the default -arch flag for the system, then
  1846. // add it. Otherwize do not add -arch and -isysroot
  1847. if(addArchFlag)
  1848. {
  1849. for( std::vector<std::string>::iterator i = archs.begin();
  1850. i != archs.end(); ++i)
  1851. {
  1852. flags += " -arch ";
  1853. flags += *i;
  1854. }
  1855. flags += " -isysroot ";
  1856. flags += sysroot;
  1857. }
  1858. }
  1859. }
  1860. this->AddConfigVariableFlags(flags, flagsVar.c_str(), config);
  1861. }
  1862. //----------------------------------------------------------------------------
  1863. std::string cmLocalGenerator::GetRealDependency(const char* inName,
  1864. const char* config)
  1865. {
  1866. // Older CMake code may specify the dependency using the target
  1867. // output file rather than the target name. Such code would have
  1868. // been written before there was support for target properties that
  1869. // modify the name so stripping down to just the file name should
  1870. // produce the target name in this case.
  1871. std::string name = cmSystemTools::GetFilenameName(inName);
  1872. if(cmSystemTools::GetFilenameLastExtension(name) == ".exe")
  1873. {
  1874. name = cmSystemTools::GetFilenameWithoutLastExtension(name);
  1875. }
  1876. // Look for a CMake target with the given name.
  1877. if(cmTarget* target = this->GlobalGenerator->FindTarget(0,name.c_str(),true))
  1878. {
  1879. // make sure it is not just a coincidence that the target name
  1880. // found is part of the inName
  1881. if(cmSystemTools::FileIsFullPath(inName))
  1882. {
  1883. std::string tLocation = target->GetLocation(config);
  1884. tLocation = cmSystemTools::GetFilenamePath(tLocation);
  1885. std::string depLocation = cmSystemTools::GetFilenamePath(
  1886. std::string(inName));
  1887. depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
  1888. tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
  1889. if(depLocation != tLocation)
  1890. {
  1891. // it is a full path to a depend that has the same name
  1892. // as a target but is in a different location so do not use
  1893. // the target as the depend
  1894. return inName;
  1895. }
  1896. }
  1897. switch (target->GetType())
  1898. {
  1899. case cmTarget::EXECUTABLE:
  1900. case cmTarget::STATIC_LIBRARY:
  1901. case cmTarget::SHARED_LIBRARY:
  1902. case cmTarget::MODULE_LIBRARY:
  1903. {
  1904. // Get the location of the target's output file and depend on it.
  1905. if(const char* location = target->GetLocation(config))
  1906. {
  1907. return location;
  1908. }
  1909. }
  1910. break;
  1911. case cmTarget::UTILITY:
  1912. case cmTarget::GLOBAL_TARGET:
  1913. // Depending on a utility target may not work but just trust
  1914. // the user to have given a valid name.
  1915. return inName;
  1916. case cmTarget::INSTALL_FILES:
  1917. case cmTarget::INSTALL_PROGRAMS:
  1918. case cmTarget::INSTALL_DIRECTORY:
  1919. break;
  1920. }
  1921. }
  1922. // The name was not that of a CMake target. It must name a file.
  1923. if(cmSystemTools::FileIsFullPath(inName))
  1924. {
  1925. // This is a full path. Return it as given.
  1926. return inName;
  1927. }
  1928. // Treat the name as relative to the source directory in which it
  1929. // was given.
  1930. name = this->Makefile->GetCurrentDirectory();
  1931. name += "/";
  1932. name += inName;
  1933. return name;
  1934. }
  1935. //----------------------------------------------------------------------------
  1936. std::string cmLocalGenerator::GetRealLocation(const char* inName,
  1937. const char* config)
  1938. {
  1939. std::string outName=inName;
  1940. // Look for a CMake target with the given name, which is an executable
  1941. // and which can be run
  1942. cmTarget* target = this->GlobalGenerator->FindTarget(0, inName, true);
  1943. if ((target != 0)
  1944. && (target->GetType() == cmTarget::EXECUTABLE)
  1945. && ((this->Makefile->IsOn("CMAKE_CROSSCOMPILING") == false)
  1946. || (target->IsImported() == true)))
  1947. {
  1948. outName = target->GetLocation( config );
  1949. }
  1950. return outName;
  1951. }
  1952. //----------------------------------------------------------------------------
  1953. void cmLocalGenerator::AddSharedFlags(std::string& flags,
  1954. const char* lang,
  1955. bool shared)
  1956. {
  1957. std::string flagsVar;
  1958. // Add flags for dealing with shared libraries for this language.
  1959. if(shared)
  1960. {
  1961. flagsVar = "CMAKE_SHARED_LIBRARY_";
  1962. flagsVar += lang;
  1963. flagsVar += "_FLAGS";
  1964. this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
  1965. }
  1966. // Add flags specific to shared builds.
  1967. if(cmSystemTools::IsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
  1968. {
  1969. flagsVar = "CMAKE_SHARED_BUILD_";
  1970. flagsVar += lang;
  1971. flagsVar += "_FLAGS";
  1972. this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
  1973. }
  1974. }
  1975. //----------------------------------------------------------------------------
  1976. void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
  1977. const char* var,
  1978. const char* config)
  1979. {
  1980. // Add the flags from the variable itself.
  1981. std::string flagsVar = var;
  1982. this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
  1983. // Add the flags from the build-type specific variable.
  1984. if(config && *config)
  1985. {
  1986. flagsVar += "_";
  1987. flagsVar += cmSystemTools::UpperCase(config);
  1988. this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
  1989. }
  1990. }
  1991. //----------------------------------------------------------------------------
  1992. void cmLocalGenerator::AppendFlags(std::string& flags,
  1993. const char* newFlags)
  1994. {
  1995. if(newFlags && *newFlags)
  1996. {
  1997. std::string newf = newFlags;
  1998. if(flags.size())
  1999. {
  2000. flags += " ";
  2001. }
  2002. flags += newFlags;
  2003. }
  2004. }
  2005. //----------------------------------------------------------------------------
  2006. std::string
  2007. cmLocalGenerator::ConstructComment(const cmCustomCommand& cc,
  2008. const char* default_comment)
  2009. {
  2010. // Check for a comment provided with the command.
  2011. if(cc.GetComment())
  2012. {
  2013. return cc.GetComment();
  2014. }
  2015. // Construct a reasonable default comment if possible.
  2016. if(!cc.GetOutputs().empty())
  2017. {
  2018. std::string comment;
  2019. comment = "Generating ";
  2020. const char* sep = "";
  2021. for(std::vector<std::string>::const_iterator o = cc.GetOutputs().begin();
  2022. o != cc.GetOutputs().end(); ++o)
  2023. {
  2024. comment += sep;
  2025. comment += this->Convert(o->c_str(), cmLocalGenerator::START_OUTPUT);
  2026. sep = ", ";
  2027. }
  2028. return comment;
  2029. }
  2030. // Otherwise use the provided default.
  2031. return default_comment;
  2032. }
  2033. //----------------------------------------------------------------------------
  2034. std::string
  2035. cmLocalGenerator::ConvertToOptionallyRelativeOutputPath(const char* remote)
  2036. {
  2037. return this->Convert(remote, START_OUTPUT, SHELL, true);
  2038. }
  2039. //----------------------------------------------------------------------------
  2040. std::string cmLocalGenerator::Convert(const char* source,
  2041. RelativeRoot relative,
  2042. OutputFormat output,
  2043. bool optional)
  2044. {
  2045. // Make sure the relative path conversion components are set.
  2046. if(!this->PathConversionsSetup)
  2047. {
  2048. this->SetupPathConversions();
  2049. this->PathConversionsSetup = true;
  2050. }
  2051. // Convert the path to a relative path.
  2052. std::string result = source;
  2053. if (!optional || this->UseRelativePaths)
  2054. {
  2055. switch (relative)
  2056. {
  2057. case HOME:
  2058. //result = cmSystemTools::CollapseFullPath(result.c_str());
  2059. result = this->ConvertToRelativePath(this->HomeDirectoryComponents,
  2060. result.c_str());
  2061. break;
  2062. case START:
  2063. //result = cmSystemTools::CollapseFullPath(result.c_str());
  2064. result = this->ConvertToRelativePath(this->StartDirectoryComponents,
  2065. result.c_str());
  2066. break;
  2067. case HOME_OUTPUT:
  2068. //result = cmSystemTools::CollapseFullPath(result.c_str());
  2069. result =
  2070. this->ConvertToRelativePath(this->HomeOutputDirectoryComponents,
  2071. result.c_str());
  2072. break;
  2073. case START_OUTPUT:
  2074. //result = cmSystemTools::CollapseFullPath(result.c_str());
  2075. result =
  2076. this->ConvertToRelativePath(this->StartOutputDirectoryComponents,
  2077. result.c_str());
  2078. break;
  2079. case FULL:
  2080. result = cmSystemTools::CollapseFullPath(result.c_str());
  2081. break;
  2082. case NONE:
  2083. break;
  2084. }
  2085. }
  2086. // Now convert it to an output path.
  2087. if (output == MAKEFILE)
  2088. {
  2089. result = cmSystemTools::ConvertToOutputPath(result.c_str());
  2090. }
  2091. else if( output == SHELL)
  2092. {
  2093. // For the MSYS shell convert drive letters to posix paths, so
  2094. // that c:/some/path becomes /c/some/path. This is needed to
  2095. // avoid problems with the shell path translation.
  2096. if(this->MSYSShell)
  2097. {
  2098. if(result.size() > 2 && result[1] == ':')
  2099. {
  2100. result[1] = result[0];
  2101. result[0] = '/';
  2102. }
  2103. }
  2104. if(this->WindowsShell)
  2105. {
  2106. std::string::size_type pos = 0;
  2107. while((pos = result.find('/', pos)) != std::string::npos)
  2108. {
  2109. result[pos] = '\\';
  2110. pos++;
  2111. }
  2112. }
  2113. result = this->EscapeForShell(result.c_str(), true, false);
  2114. }
  2115. return result;
  2116. }
  2117. //----------------------------------------------------------------------------
  2118. std::string cmLocalGenerator::FindRelativePathTopSource()
  2119. {
  2120. // Relative path conversion within a single tree managed by CMake is
  2121. // safe. We can use our parent relative path top if and only if
  2122. // this is a subdirectory of that top.
  2123. if(cmLocalGenerator* parent = this->GetParent())
  2124. {
  2125. std::string parentTop = parent->FindRelativePathTopSource();
  2126. if(cmSystemTools::IsSubDirectory(
  2127. this->Makefile->GetStartDirectory(), parentTop.c_str()))
  2128. {
  2129. return parentTop;
  2130. }
  2131. }
  2132. // Otherwise this directory itself is the new top.
  2133. return this->Makefile->GetStartDirectory();
  2134. }
  2135. //----------------------------------------------------------------------------
  2136. std::string cmLocalGenerator::FindRelativePathTopBinary()
  2137. {
  2138. // Relative path conversion within a single tree managed by CMake is
  2139. // safe. We can use our parent relative path top if and only if
  2140. // this is a subdirectory of that top.
  2141. if(cmLocalGenerator* parent = this->GetParent())
  2142. {
  2143. std::string parentTop = parent->FindRelativePathTopBinary();
  2144. if(cmSystemTools::IsSubDirectory(
  2145. this->Makefile->GetStartOutputDirectory(), parentTop.c_str()))
  2146. {
  2147. return parentTop;
  2148. }
  2149. }
  2150. // Otherwise this directory itself is the new top.
  2151. return this->Makefile->GetStartOutputDirectory();
  2152. }
  2153. //----------------------------------------------------------------------------
  2154. void cmLocalGenerator::ConfigureRelativePaths()
  2155. {
  2156. // Relative path conversion inside the source tree is not used to
  2157. // construct relative paths passed to build tools so it is safe to
  2158. // even when the source is a network path.
  2159. std::string source = this->FindRelativePathTopSource();
  2160. this->RelativePathTopSource = source;
  2161. // The current working directory on Windows cannot be a network
  2162. // path. Therefore relative paths cannot work when the binary tree
  2163. // is a network path.
  2164. std::string binary = this->FindRelativePathTopBinary();
  2165. if(binary.size() < 2 || binary.substr(0, 2) != "//")
  2166. {
  2167. this->RelativePathTopBinary = binary;
  2168. }
  2169. else
  2170. {
  2171. this->RelativePathTopBinary = "";
  2172. }
  2173. }
  2174. //----------------------------------------------------------------------------
  2175. static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
  2176. {
  2177. return (cmSystemTools::ComparePath(a, b) ||
  2178. cmSystemTools::IsSubDirectory(a, b));
  2179. }
  2180. //----------------------------------------------------------------------------
  2181. std::string
  2182. cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
  2183. const char* in_remote)
  2184. {
  2185. // The path should never be quoted.
  2186. assert(in_remote[0] != '\"');
  2187. // The local path should never have a trailing slash.
  2188. assert(local.size() > 0 && !(local[local.size()-1] == ""));
  2189. // If the path is already relative then just return the path.
  2190. if(!cmSystemTools::FileIsFullPath(in_remote))
  2191. {
  2192. return in_remote;
  2193. }
  2194. // Make sure relative path conversion is configured.
  2195. if(!this->RelativePathsConfigured)
  2196. {
  2197. this->ConfigureRelativePaths();
  2198. this->RelativePathsConfigured = true;
  2199. }
  2200. // Skip conversion if the path and local are not both in the source
  2201. // or both in the binary tree.
  2202. std::string local_path = cmSystemTools::JoinPath(local);
  2203. if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
  2204. this->RelativePathTopBinary.c_str()) &&
  2205. cmLocalGeneratorNotAbove(in_remote,
  2206. this->RelativePathTopBinary.c_str())) ||
  2207. (cmLocalGeneratorNotAbove(local_path.c_str(),
  2208. this->RelativePathTopSource.c_str()) &&
  2209. cmLocalGeneratorNotAbove(in_remote,
  2210. this->RelativePathTopSource.c_str()))))
  2211. {
  2212. return in_remote;
  2213. }
  2214. // Identify the longest shared path component between the remote
  2215. // path and the local path.
  2216. std::vector<std::string> remote;
  2217. cmSystemTools::SplitPath(in_remote, remote);
  2218. unsigned int common=0;
  2219. while(common < remote.size() &&
  2220. common < local.size() &&
  2221. cmSystemTools::ComparePath(remote[common].c_str(),
  2222. local[common].c_str()))
  2223. {
  2224. ++common;
  2225. }
  2226. // If no part of the path is in common then return the full path.
  2227. if(common == 0)
  2228. {
  2229. return in_remote;
  2230. }
  2231. // If the entire path is in common then just return a ".".
  2232. if(common == remote.size() &&
  2233. common == local.size())
  2234. {
  2235. return ".";
  2236. }
  2237. // If the entire path is in common except for a trailing slash then
  2238. // just return a "./".
  2239. if(common+1 == remote.size() &&
  2240. remote[common].size() == 0 &&
  2241. common == local.size())
  2242. {
  2243. return "./";
  2244. }
  2245. // Construct the relative path.
  2246. std::string relative;
  2247. // First add enough ../ to get up to the level of the shared portion
  2248. // of the path. Leave off the trailing slash. Note that the last
  2249. // component of local will never be empty because local should never
  2250. // have a trailing slash.
  2251. for(unsigned int i=common; i < local.size(); ++i)
  2252. {
  2253. relative += "..";
  2254. if(i < local.size()-1)
  2255. {
  2256. relative += "/";
  2257. }
  2258. }
  2259. // Now add the portion of the destination path that is not included
  2260. // in the shared portion of the path. Add a slash the first time
  2261. // only if there was already something in the path. If there was a
  2262. // trailing slash in the input then the last iteration of the loop
  2263. // will add a slash followed by an empty string which will preserve
  2264. // the trailing slash in the output.
  2265. for(unsigned int i=common; i < remote.size(); ++i)
  2266. {
  2267. if(relative.size() > 0)
  2268. {
  2269. relative += "/";
  2270. }
  2271. relative += remote[i];
  2272. }
  2273. // Finally return the path.
  2274. return relative;
  2275. }
  2276. //----------------------------------------------------------------------------
  2277. void
  2278. cmLocalGenerator
  2279. ::GenerateTargetInstallRules(
  2280. std::ostream& os, const char* config,
  2281. std::vector<std::string> const& configurationTypes)
  2282. {
  2283. // Convert the old-style install specification from each target to
  2284. // an install generator and run it.
  2285. cmTargets& tgts = this->Makefile->GetTargets();
  2286. for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
  2287. {
  2288. // Include the user-specified pre-install script for this target.
  2289. if(const char* preinstall = l->second.GetProperty("PRE_INSTALL_SCRIPT"))
  2290. {
  2291. cmInstallScriptGenerator g(preinstall, false, 0);
  2292. g.Generate(os, config, configurationTypes);
  2293. }
  2294. // Install this target if a destination is given.
  2295. if(l->second.GetInstallPath() != "")
  2296. {
  2297. // Compute the full install destination. Note that converting
  2298. // to unix slashes also removes any trailing slash.
  2299. std::string destination = "${CMAKE_INSTALL_PREFIX}";
  2300. destination += l->second.GetInstallPath();
  2301. cmSystemTools::ConvertToUnixSlashes(destination);
  2302. // Generate the proper install generator for this target type.
  2303. switch(l->second.GetType())
  2304. {
  2305. case cmTarget::EXECUTABLE:
  2306. case cmTarget::STATIC_LIBRARY:
  2307. case cmTarget::MODULE_LIBRARY:
  2308. {
  2309. // Use a target install generator.
  2310. cmInstallTargetGenerator g(l->second, destination.c_str(), false);
  2311. g.Generate(os, config, configurationTypes);
  2312. }
  2313. break;
  2314. case cmTarget::SHARED_LIBRARY:
  2315. {
  2316. #if defined(_WIN32) || defined(__CYGWIN__)
  2317. // Special code to handle DLL. Install the import library
  2318. // to the normal destination and the DLL to the runtime
  2319. // destination.
  2320. cmInstallTargetGenerator g1(l->second, destination.c_str(), true);
  2321. g1.Generate(os, config, configurationTypes);
  2322. destination = "${CMAKE_INSTALL_PREFIX}";
  2323. destination += l->second.GetRuntimeInstallPath();
  2324. cmSystemTools::ConvertToUnixSlashes(destination);
  2325. cmInstallTargetGenerator g2(l->second, destination.c_str(), false);
  2326. g2.Generate(os, config, configurationTypes);
  2327. #else
  2328. // Use a target install generator.
  2329. cmInstallTargetGenerator g(l->second, destination.c_str(), false);
  2330. g.Generate(os, config, configurationTypes);
  2331. #endif
  2332. }
  2333. break;
  2334. default:
  2335. break;
  2336. }
  2337. }
  2338. // Include the user-specified post-install script for this target.
  2339. if(const char* postinstall = l->second.GetProperty("POST_INSTALL_SCRIPT"))
  2340. {
  2341. cmInstallScriptGenerator g(postinstall, false, 0);
  2342. g.Generate(os, config, configurationTypes);
  2343. }
  2344. }
  2345. }
  2346. #if defined(CM_LG_ENCODE_OBJECT_NAMES)
  2347. static std::string cmLocalGeneratorMD5(const char* input)
  2348. {
  2349. char md5out[32];
  2350. cmsysMD5* md5 = cmsysMD5_New();
  2351. cmsysMD5_Initialize(md5);
  2352. cmsysMD5_Append(md5, reinterpret_cast<unsigned char const*>(input), -1);
  2353. cmsysMD5_FinalizeHex(md5, md5out);
  2354. cmsysMD5_Delete(md5);
  2355. return std::string(md5out, 32);
  2356. }
  2357. static bool
  2358. cmLocalGeneratorShortenObjectName(std::string& objName,
  2359. std::string::size_type max_len)
  2360. {
  2361. // Replace the beginning of the path portion of the object name with
  2362. // its own md5 sum.
  2363. std::string::size_type pos = objName.find('/', objName.size()-max_len+32);
  2364. if(pos != objName.npos)
  2365. {
  2366. std::string md5name = cmLocalGeneratorMD5(objName.substr(0, pos).c_str());
  2367. md5name += objName.substr(pos);
  2368. objName = md5name;
  2369. // The object name is now short enough.
  2370. return true;
  2371. }
  2372. else
  2373. {
  2374. // The object name could not be shortened enough.
  2375. return false;
  2376. }
  2377. }
  2378. static bool cmLocalGeneratorCheckObjectName(std::string& objName,
  2379. std::string::size_type dir_len)
  2380. {
  2381. // Choose a maximum file name length.
  2382. #if defined(_WIN32) || defined(__CYGWIN__)
  2383. std::string::size_type const max_total_len = 250;
  2384. #else
  2385. std::string::size_type const max_total_len = 1000;
  2386. #endif
  2387. // Enforce the maximum file name length if possible.
  2388. std::string::size_type max_obj_len = max_total_len;
  2389. if(dir_len < max_total_len)
  2390. {
  2391. max_obj_len = max_total_len - dir_len;
  2392. if(objName.size() > max_obj_len)
  2393. {
  2394. // The current object file name is too long. Try to shorten it.
  2395. return cmLocalGeneratorShortenObjectName(objName, max_obj_len);
  2396. }
  2397. else
  2398. {
  2399. // The object file name is short enough.
  2400. return true;
  2401. }
  2402. }
  2403. else
  2404. {
  2405. // The build directory in which the object will be stored is
  2406. // already too deep.
  2407. return false;
  2408. }
  2409. }
  2410. #endif
  2411. //----------------------------------------------------------------------------
  2412. std::string&
  2413. cmLocalGenerator
  2414. ::CreateSafeUniqueObjectFileName(const char* sin,
  2415. std::string::size_type dir_len)
  2416. {
  2417. // Look for an existing mapped name for this object file.
  2418. std::map<cmStdString,cmStdString>::iterator it =
  2419. this->UniqueObjectNamesMap.find(sin);
  2420. // If no entry exists create one.
  2421. if(it == this->UniqueObjectNamesMap.end())
  2422. {
  2423. // Start with the original name.
  2424. std::string ssin = sin;
  2425. // Avoid full paths by removing leading slashes.
  2426. std::string::size_type pos = 0;
  2427. for(;pos < ssin.size() && ssin[pos] == '/'; ++pos);
  2428. ssin = ssin.substr(pos);
  2429. // Avoid full paths by removing colons.
  2430. cmSystemTools::ReplaceString(ssin, ":", "_");
  2431. // Avoid relative paths that go up the tree.
  2432. cmSystemTools::ReplaceString(ssin, "../", "__/");
  2433. // Avoid spaces.
  2434. cmSystemTools::ReplaceString(ssin, " ", "_");
  2435. // Mangle the name if necessary.
  2436. if(this->Makefile->IsOn("CMAKE_MANGLE_OBJECT_FILE_NAMES"))
  2437. {
  2438. bool done;
  2439. int cc = 0;
  2440. char rpstr[100];
  2441. sprintf(rpstr, "_p_");
  2442. cmSystemTools::ReplaceString(ssin, "+", rpstr);
  2443. std::string sssin = sin;
  2444. do
  2445. {
  2446. done = true;
  2447. for ( it = this->UniqueObjectNamesMap.begin();
  2448. it != this->UniqueObjectNamesMap.end();
  2449. ++ it )
  2450. {
  2451. if ( it->second == ssin )
  2452. {
  2453. done = false;
  2454. }
  2455. }
  2456. if ( done )
  2457. {
  2458. break;
  2459. }
  2460. sssin = ssin;
  2461. cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
  2462. sprintf(rpstr, "_p%d_", cc++);
  2463. }
  2464. while ( !done );
  2465. }
  2466. #if defined(CM_LG_ENCODE_OBJECT_NAMES)
  2467. cmLocalGeneratorCheckObjectName(ssin, dir_len);
  2468. #else
  2469. (void)dir_len;
  2470. #endif
  2471. // Insert the newly mapped object file name.
  2472. std::map<cmStdString, cmStdString>::value_type e(sin, ssin);
  2473. it = this->UniqueObjectNamesMap.insert(e).first;
  2474. }
  2475. // Return the map entry.
  2476. return it->second;
  2477. }
  2478. //----------------------------------------------------------------------------
  2479. std::string
  2480. cmLocalGenerator
  2481. ::GetObjectFileNameWithoutTarget(const cmSourceFile& source,
  2482. std::string::size_type dir_len)
  2483. {
  2484. // Construct the object file name using the full path to the source
  2485. // file which is its only unique identification.
  2486. const char* fullPath = source.GetFullPath().c_str();
  2487. // Try referencing the source relative to the source tree.
  2488. std::string relFromSource = this->Convert(fullPath, START);
  2489. assert(!relFromSource.empty());
  2490. bool relSource = !cmSystemTools::FileIsFullPath(relFromSource.c_str());
  2491. bool subSource = relSource && relFromSource[0] != '.';
  2492. // Try referencing the source relative to the binary tree.
  2493. std::string relFromBinary = this->Convert(fullPath, START_OUTPUT);
  2494. assert(!relFromBinary.empty());
  2495. bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary.c_str());
  2496. bool subBinary = relBinary && relFromBinary[0] != '.';
  2497. // Select a nice-looking reference to the source file to construct
  2498. // the object file name.
  2499. std::string objectName;
  2500. if((relSource && !relBinary) || (subSource && !subBinary))
  2501. {
  2502. objectName = relFromSource;
  2503. }
  2504. else if((relBinary && !relSource) || (subBinary && !subSource))
  2505. {
  2506. objectName = relFromBinary;
  2507. }
  2508. else if(relFromBinary.length() < relFromSource.length())
  2509. {
  2510. objectName = relFromBinary;
  2511. }
  2512. else
  2513. {
  2514. objectName = relFromSource;
  2515. }
  2516. // if it is still a full path check for the try compile case
  2517. // try compile never have in source sources, and should not
  2518. // have conflicting source file names in the same target
  2519. if(cmSystemTools::FileIsFullPath(objectName.c_str()))
  2520. {
  2521. if(this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile())
  2522. {
  2523. objectName = cmSystemTools::GetFilenameName(source.GetFullPath());
  2524. }
  2525. }
  2526. // Replace the original source file extension with the object file
  2527. // extension.
  2528. if(!source.GetPropertyAsBool("KEEP_EXTENSION"))
  2529. {
  2530. // Remove the original extension.
  2531. std::string::size_type dot_pos = objectName.rfind(".");
  2532. if(dot_pos != std::string::npos)
  2533. {
  2534. objectName = objectName.substr(0, dot_pos);
  2535. }
  2536. // Store the new extension.
  2537. objectName +=
  2538. this->GlobalGenerator->GetLanguageOutputExtension(source);
  2539. }
  2540. // Convert to a safe name.
  2541. return this->CreateSafeUniqueObjectFileName(objectName.c_str(), dir_len);
  2542. }
  2543. //----------------------------------------------------------------------------
  2544. const char*
  2545. cmLocalGenerator
  2546. ::GetSourceFileLanguage(const cmSourceFile& source)
  2547. {
  2548. return source.GetLanguage();
  2549. }
  2550. //----------------------------------------------------------------------------
  2551. std::string cmLocalGenerator::EscapeForShellOldStyle(const char* str)
  2552. {
  2553. std::string result;
  2554. bool forceOn = cmSystemTools::GetForceUnixPaths();
  2555. if(forceOn && this->WindowsShell)
  2556. {
  2557. cmSystemTools::SetForceUnixPaths(false);
  2558. }
  2559. result = cmSystemTools::EscapeSpaces(str);
  2560. if(forceOn && this->WindowsShell)
  2561. {
  2562. cmSystemTools::SetForceUnixPaths(true);
  2563. }
  2564. return result;
  2565. }
  2566. //----------------------------------------------------------------------------
  2567. std::string cmLocalGenerator::EscapeForShell(const char* str, bool makeVars,
  2568. bool forEcho)
  2569. {
  2570. // Compute the flags for the target shell environment.
  2571. int flags = 0;
  2572. if(this->WindowsVSIDE)
  2573. {
  2574. flags |= cmsysSystem_Shell_Flag_VSIDE;
  2575. }
  2576. else
  2577. {
  2578. flags |= cmsysSystem_Shell_Flag_Make;
  2579. }
  2580. if(makeVars)
  2581. {
  2582. flags |= cmsysSystem_Shell_Flag_AllowMakeVariables;
  2583. }
  2584. if(forEcho)
  2585. {
  2586. flags |= cmsysSystem_Shell_Flag_EchoWindows;
  2587. }
  2588. if(this->WatcomWMake)
  2589. {
  2590. flags |= cmsysSystem_Shell_Flag_WatcomWMake;
  2591. }
  2592. if(this->MinGWMake)
  2593. {
  2594. flags |= cmsysSystem_Shell_Flag_MinGWMake;
  2595. }
  2596. // Compute the buffer size needed.
  2597. int size = (this->WindowsShell ?
  2598. cmsysSystem_Shell_GetArgumentSizeForWindows(str, flags) :
  2599. cmsysSystem_Shell_GetArgumentSizeForUnix(str, flags));
  2600. // Compute the shell argument itself.
  2601. std::vector<char> arg(size);
  2602. if(this->WindowsShell)
  2603. {
  2604. cmsysSystem_Shell_GetArgumentForWindows(str, &arg[0], flags);
  2605. }
  2606. else
  2607. {
  2608. cmsysSystem_Shell_GetArgumentForUnix(str, &arg[0], flags);
  2609. }
  2610. return std::string(&arg[0]);
  2611. }
  2612. //----------------------------------------------------------------------------
  2613. std::string
  2614. cmLocalGenerator::GetTargetDirectory(cmTarget const&) const
  2615. {
  2616. cmSystemTools::Error("GetTargetDirectory"
  2617. " called on cmLocalGenerator");
  2618. return "";
  2619. }
  2620. //----------------------------------------------------------------------------
  2621. void
  2622. cmLocalGenerator::GetTargetObjectFileDirectories(cmTarget* ,
  2623. std::vector<std::string>&
  2624. )
  2625. {
  2626. cmSystemTools::Error("GetTargetObjectFileDirectories"
  2627. " called on cmLocalGenerator");
  2628. }