cmGlobalGenerator.cxx 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  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 "cmGlobalGenerator.h"
  14. #include "cmLocalGenerator.h"
  15. #include "cmake.h"
  16. #include "cmMakefile.h"
  17. #include <stdlib.h> // required for atof
  18. #if defined(_WIN32) && !defined(__CYGWIN__)
  19. #include <windows.h>
  20. #endif
  21. #include <assert.h>
  22. int cmGlobalGenerator::s_TryCompileTimeout = 0;
  23. cmGlobalGenerator::cmGlobalGenerator()
  24. {
  25. // by default use the native paths
  26. m_ForceUnixPaths = false;
  27. }
  28. cmGlobalGenerator::~cmGlobalGenerator()
  29. {
  30. // Delete any existing cmLocalGenerators
  31. unsigned int i;
  32. for (i = 0; i < m_LocalGenerators.size(); ++i)
  33. {
  34. delete m_LocalGenerators[i];
  35. }
  36. m_LocalGenerators.clear();
  37. }
  38. // Find the make program for the generator, required for try compiles
  39. void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
  40. {
  41. if(m_FindMakeProgramFile.size() == 0)
  42. {
  43. cmSystemTools::Error(
  44. "Generator implementation error, "
  45. "all generators must specify m_FindMakeProgramFile");
  46. }
  47. if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
  48. || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
  49. {
  50. std::string setMakeProgram = mf->GetModulesFile(m_FindMakeProgramFile.c_str());
  51. if(setMakeProgram.size())
  52. {
  53. mf->ReadListFile(0, setMakeProgram.c_str());
  54. }
  55. }
  56. if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
  57. || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
  58. {
  59. cmOStringStream err;
  60. err << "CMake was unable to find a build program corresponding to \""
  61. << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
  62. << "probably need to select a different build tool.";
  63. cmSystemTools::Error(err.str().c_str());
  64. cmSystemTools::SetFatalErrorOccured();
  65. return;
  66. }
  67. std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  68. // if there are spaces in the make program use short path
  69. // but do not short path the actual program name, as
  70. // this can cause trouble with VSExpress
  71. if(makeProgram.find(' ') != makeProgram.npos)
  72. {
  73. std::string dir;
  74. std::string file;
  75. cmSystemTools::SplitProgramPath(makeProgram.c_str(),
  76. dir, file);
  77. std::string saveFile = file;
  78. cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
  79. cmSystemTools::SplitProgramPath(makeProgram.c_str(),
  80. dir, file);
  81. makeProgram = dir;
  82. makeProgram += "/";
  83. makeProgram += saveFile;
  84. this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
  85. "make program",
  86. cmCacheManager::FILEPATH);
  87. }
  88. }
  89. // enable the given language
  90. void cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
  91. cmMakefile *mf)
  92. {
  93. if(languages.size() == 0)
  94. {
  95. cmSystemTools::Error("EnableLanguage must have a lang specified!");
  96. cmSystemTools::SetFatalErrorOccured();
  97. return;
  98. }
  99. mf->AddDefinition("RUN_CONFIGURE", true);
  100. bool needTestLanguage = false;
  101. std::string rootBin = mf->GetHomeOutputDirectory();
  102. // If the configuration files path has been set,
  103. // then we are in a try compile and need to copy the enable language
  104. // files into the try compile directory
  105. if(m_ConfiguredFilesPath.size())
  106. {
  107. std::string src = m_ConfiguredFilesPath;
  108. src += "/CMakeSystem.cmake";
  109. std::string dst = rootBin;
  110. dst += "/CMakeSystem.cmake";
  111. cmSystemTools::CopyFileIfDifferent(src.c_str(), dst.c_str());
  112. for(std::vector<std::string>::const_iterator l = languages.begin();
  113. l != languages.end(); ++l)
  114. {
  115. if(*l == "NONE")
  116. {
  117. this->SetLanguageEnabled("NONE", mf);
  118. continue;
  119. }
  120. const char* lang = l->c_str();
  121. std::string src2 = m_ConfiguredFilesPath;
  122. src2 += "/CMake";
  123. src2 += lang;
  124. src2 += "Compiler.cmake";
  125. std::string dst2 = rootBin;
  126. dst2 += "/CMake";
  127. dst2 += lang;
  128. dst2 += "Compiler.cmake";
  129. cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str());
  130. src2 = m_ConfiguredFilesPath;
  131. src2 += "/CMake";
  132. src2 += lang;
  133. src2 += "Platform.cmake";
  134. dst2 = rootBin;
  135. dst2 += "/CMake";
  136. dst2 += lang;
  137. dst2 += "Platform.cmake";
  138. cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str());
  139. }
  140. rootBin = m_ConfiguredFilesPath;
  141. }
  142. // **** Step 1, find and make sure CMAKE_MAKE_PROGRAM is defined
  143. this->FindMakeProgram(mf);
  144. // try and load the CMakeSystem.cmake if it is there
  145. std::string fpath = rootBin;
  146. if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
  147. {
  148. fpath += "/CMakeSystem.cmake";
  149. if(cmSystemTools::FileExists(fpath.c_str()))
  150. {
  151. mf->ReadListFile(0,fpath.c_str());
  152. }
  153. }
  154. // **** Step 2, Load the CMakeDetermineSystem.cmake file and find out
  155. // what platform we are running on
  156. if (!mf->GetDefinition("CMAKE_SYSTEM_NAME"))
  157. {
  158. #if defined(_WIN32) && !defined(__CYGWIN__)
  159. /* Windows version number data. */
  160. OSVERSIONINFO osvi;
  161. ZeroMemory(&osvi, sizeof(osvi));
  162. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  163. GetVersionEx (&osvi);
  164. cmOStringStream windowsVersionString;
  165. windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
  166. windowsVersionString.str();
  167. mf->AddDefinition("CMAKE_SYSTEM_VERSION", windowsVersionString.str().c_str());
  168. #endif
  169. // Read the DetermineSystem file
  170. std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
  171. mf->ReadListFile(0, systemFile.c_str());
  172. }
  173. // **** Step 3, load the CMakeSystem.cmake from the binary directory
  174. // this file is configured by the CMakeDetermineSystem.cmake file
  175. fpath = rootBin;
  176. if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
  177. {
  178. fpath += "/CMakeSystem.cmake";
  179. mf->ReadListFile(0,fpath.c_str());
  180. }
  181. // **** Step 4, foreach language
  182. // load the CMakeDetermine(LANG)Compiler.cmake file to find
  183. // the compiler
  184. for(std::vector<std::string>::const_iterator l = languages.begin();
  185. l != languages.end(); ++l)
  186. {
  187. const char* lang = l->c_str();
  188. if(*l == "NONE")
  189. {
  190. this->SetLanguageEnabled("NONE", mf);
  191. continue;
  192. }
  193. if(!this->GetLanguageEnabled(lang) )
  194. {
  195. if (m_CMakeInstance->GetIsInTryCompile())
  196. {
  197. cmSystemTools::Error("This should not have happen. "
  198. "If you see this message, you are probably using a "
  199. "broken CMakeLists.txt file or a problematic release of "
  200. "CMake");
  201. }
  202. // If the existing build tree was already configured with this
  203. // version of CMake then try to load the configured file first
  204. // to avoid duplicate compiler tests.
  205. unsigned int cacheMajor = mf->GetCacheMajorVersion();
  206. unsigned int cacheMinor = mf->GetCacheMinorVersion();
  207. unsigned int selfMajor = cmMakefile::GetMajorVersion();
  208. unsigned int selfMinor = cmMakefile::GetMinorVersion();
  209. if(selfMajor == cacheMajor && selfMinor == cacheMinor)
  210. {
  211. std::string loadedLang = "CMAKE_";
  212. loadedLang += lang;
  213. loadedLang += "_COMPILER_LOADED";
  214. if(!mf->GetDefinition(loadedLang.c_str()))
  215. {
  216. fpath = rootBin;
  217. fpath += "/CMake";
  218. fpath += lang;
  219. fpath += "Compiler.cmake";
  220. if(cmSystemTools::FileExists(fpath.c_str()))
  221. {
  222. if(!mf->ReadListFile(0,fpath.c_str()))
  223. {
  224. cmSystemTools::Error("Could not find cmake module file:", fpath.c_str());
  225. }
  226. this->SetLanguageEnabled(lang, mf);
  227. }
  228. }
  229. }
  230. needTestLanguage = true; // must test a language after finding it
  231. // read determine LANG compiler
  232. std::string determineCompiler = "CMakeDetermine";
  233. determineCompiler += lang;
  234. determineCompiler += "Compiler.cmake";
  235. std::string determineFile = mf->GetModulesFile(determineCompiler.c_str());
  236. if(!mf->ReadListFile(0,determineFile.c_str()))
  237. {
  238. cmSystemTools::Error("Could not find cmake module file:", determineFile.c_str());
  239. }
  240. // Some generators like visual studio should not use the env variables
  241. // So the global generator can specify that in this variable
  242. if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
  243. {
  244. // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER into the
  245. // environment, in case user scripts want to run configure, or sub cmakes
  246. std::string compilerName = "CMAKE_";
  247. compilerName += lang;
  248. compilerName += "_COMPILER";
  249. std::string compilerEnv = "CMAKE_";
  250. compilerEnv += lang;
  251. compilerEnv += "_COMPILER_ENV_VAR";
  252. std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
  253. std::string envVarValue = mf->GetRequiredDefinition(compilerName.c_str());
  254. std::string env = envVar;
  255. env += "=";
  256. env += envVarValue;
  257. cmSystemTools::PutEnv(env.c_str());
  258. }
  259. }
  260. // **** Step 5, Load the configured language compiler file, if not loaded.
  261. // look to see if CMAKE_(LANG)_COMPILER_LOADED is set,
  262. // if not then load the CMake(LANG)Compiler.cmake file from the
  263. // binary tree, this is a configured file provided by
  264. // CMakeDetermine(LANG)Compiler.cmake
  265. std::string loadedLang = "CMAKE_";
  266. loadedLang += lang;
  267. loadedLang += "_COMPILER_LOADED";
  268. if(!mf->GetDefinition(loadedLang.c_str()))
  269. {
  270. fpath = rootBin;
  271. fpath += "/CMake";
  272. fpath += lang;
  273. fpath += "Compiler.cmake";
  274. if(!mf->ReadListFile(0,fpath.c_str()))
  275. {
  276. cmSystemTools::Error("Could not find cmake module file:", fpath.c_str());
  277. }
  278. this->SetLanguageEnabled(lang, mf);
  279. }
  280. }
  281. // **** Step 6, Load the system specific information if not yet loaded
  282. if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
  283. {
  284. fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
  285. if(!mf->ReadListFile(0,fpath.c_str()))
  286. {
  287. cmSystemTools::Error("Could not find cmake module file:", fpath.c_str());
  288. }
  289. }
  290. for(std::vector<std::string>::const_iterator l = languages.begin();
  291. l != languages.end(); ++l)
  292. {
  293. const char* lang = l->c_str();
  294. if(*l == "NONE")
  295. {
  296. this->SetLanguageEnabled("NONE", mf);
  297. continue;
  298. }
  299. std::string langLoadedVar = "CMAKE_";
  300. langLoadedVar += lang;
  301. langLoadedVar += "_INFORMATION_LOADED";
  302. if (!mf->GetDefinition(langLoadedVar.c_str()))
  303. {
  304. fpath = "CMake";
  305. fpath += lang;
  306. fpath += "Information.cmake";
  307. fpath = mf->GetModulesFile(fpath.c_str());
  308. if(!mf->ReadListFile(0,fpath.c_str()))
  309. {
  310. cmSystemTools::Error("Could not find cmake module file:", fpath.c_str());
  311. }
  312. }
  313. // **** Step 7, Test the compiler for the language just setup
  314. // At this point we should have enough info for a try compile
  315. // which is used in the backward stuff
  316. if(needTestLanguage)
  317. {
  318. if (!m_CMakeInstance->GetIsInTryCompile())
  319. {
  320. std::string testLang = "CMakeTest";
  321. testLang += lang;
  322. testLang += "Compiler.cmake";
  323. std::string ifpath = mf->GetModulesFile(testLang.c_str());
  324. if(!mf->ReadListFile(0,ifpath.c_str()))
  325. {
  326. cmSystemTools::Error("Could not find cmake module file:", ifpath.c_str());
  327. }
  328. // **** Step 8, load backwards compatibility stuff for C and CXX
  329. // for old versions of CMake ListFiles C and CXX had some
  330. // backwards compatibility files they have to load
  331. const char* versionValue
  332. = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
  333. if (atof(versionValue) <= 1.4)
  334. {
  335. if(strcmp(lang, "C") == 0)
  336. {
  337. ifpath = mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
  338. mf->ReadListFile(0,ifpath.c_str());
  339. }
  340. if(strcmp(lang, "CXX") == 0)
  341. {
  342. ifpath = mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
  343. mf->ReadListFile(0,ifpath.c_str());
  344. }
  345. }
  346. }
  347. }
  348. }
  349. }
  350. const char* cmGlobalGenerator::GetLanguageOutputExtensionForLanguage(const char* lang)
  351. {
  352. if(!lang)
  353. {
  354. return "";
  355. }
  356. if(m_LanguageToOutputExtension.count(lang) > 0)
  357. {
  358. return m_LanguageToOutputExtension[lang].c_str();
  359. }
  360. return "";
  361. }
  362. const char* cmGlobalGenerator::GetLanguageOutputExtensionFromExtension(const char* ext)
  363. {
  364. if(!ext)
  365. {
  366. return "";
  367. }
  368. const char* lang = this->GetLanguageFromExtension(ext);
  369. if(!lang || *lang == 0)
  370. {
  371. // if no language is found then check to see if it is already an
  372. // ouput extension for some language. In that case it should be ignored
  373. // and in this map, so it will not be compiled but will just be used.
  374. if(m_OutputExtensions.count(ext))
  375. {
  376. return ext;
  377. }
  378. }
  379. return this->GetLanguageOutputExtensionForLanguage(lang);
  380. }
  381. const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
  382. {
  383. // if there is an extension and it starts with . then
  384. // move past the . because the extensions are not stored with a .
  385. // in the map
  386. if(ext && *ext == '.')
  387. {
  388. ++ext;
  389. }
  390. if(m_ExtensionToLanguage.count(ext) > 0)
  391. {
  392. return m_ExtensionToLanguage[ext].c_str();
  393. }
  394. return 0;
  395. }
  396. void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
  397. {
  398. if(m_LanguageEnabled.count(l) > 0)
  399. {
  400. return;
  401. }
  402. std::string outputExtensionVar = std::string("CMAKE_") +
  403. std::string(l) + std::string("_OUTPUT_EXTENSION");
  404. const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
  405. if(outputExtension)
  406. {
  407. m_LanguageToOutputExtension[l] = outputExtension;
  408. m_OutputExtensions[outputExtension] = outputExtension;
  409. if(outputExtension[0] == '.')
  410. {
  411. m_OutputExtensions[outputExtension+1] = outputExtension+1;
  412. }
  413. }
  414. std::string linkerPrefVar = std::string("CMAKE_") +
  415. std::string(l) + std::string("_LINKER_PREFERENCE");
  416. const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
  417. if(!linkerPref)
  418. {
  419. linkerPref = "None";
  420. }
  421. m_LanguageToLinkerPreference[l] = linkerPref;
  422. std::string extensionsVar = std::string("CMAKE_") +
  423. std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
  424. std::string ignoreExtensionsVar = std::string("CMAKE_") +
  425. std::string(l) + std::string("_IGNORE_EXTENSIONS");
  426. std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
  427. std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
  428. std::vector<std::string> extensionList;
  429. cmSystemTools::ExpandListArgument(exts, extensionList);
  430. for(std::vector<std::string>::iterator i = extensionList.begin();
  431. i != extensionList.end(); ++i)
  432. {
  433. m_ExtensionToLanguage[*i] = l;
  434. }
  435. cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
  436. for(std::vector<std::string>::iterator i = extensionList.begin();
  437. i != extensionList.end(); ++i)
  438. {
  439. m_IgnoreExtensions[*i] = true;
  440. }
  441. m_LanguageEnabled[l] = true;
  442. }
  443. bool cmGlobalGenerator::IgnoreFile(const char* l)
  444. {
  445. if(this->GetLanguageFromExtension(l))
  446. {
  447. return false;
  448. }
  449. return (m_IgnoreExtensions.count(l) > 0);
  450. }
  451. bool cmGlobalGenerator::GetLanguageEnabled(const char* l)
  452. {
  453. return (m_LanguageEnabled.count(l) > 0);
  454. }
  455. void cmGlobalGenerator::ClearEnabledLanguages()
  456. {
  457. m_LanguageEnabled.clear();
  458. }
  459. void cmGlobalGenerator::Configure()
  460. {
  461. // Delete any existing cmLocalGenerators
  462. unsigned int i;
  463. for (i = 0; i < m_LocalGenerators.size(); ++i)
  464. {
  465. delete m_LocalGenerators[i];
  466. }
  467. m_LocalGenerators.clear();
  468. // Setup relative path generation.
  469. this->ConfigureRelativePaths();
  470. // start with this directory
  471. cmLocalGenerator *lg = this->CreateLocalGenerator();
  472. m_LocalGenerators.push_back(lg);
  473. // set the Start directories
  474. lg->GetMakefile()->SetStartDirectory
  475. (m_CMakeInstance->GetStartDirectory());
  476. lg->GetMakefile()->SetStartOutputDirectory
  477. (m_CMakeInstance->GetStartOutputDirectory());
  478. lg->GetMakefile()->MakeStartDirectoriesCurrent();
  479. // now do it
  480. lg->Configure();
  481. // update the cache entry for the number of local generators, this is used
  482. // for progress
  483. char num[100];
  484. sprintf(num,"%d",static_cast<int>(m_LocalGenerators.size()));
  485. this->GetCMakeInstance()->AddCacheEntry
  486. ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
  487. "number of local generators",
  488. cmCacheManager::INTERNAL);
  489. std::set<cmStdString> notFoundMap;
  490. // after it is all done do a ConfigureFinalPass
  491. cmCacheManager* manager = 0;
  492. for (i = 0; i < m_LocalGenerators.size(); ++i)
  493. {
  494. manager = m_LocalGenerators[i]->GetMakefile()->GetCacheManager();
  495. m_LocalGenerators[i]->ConfigureFinalPass();
  496. cmTargets const& targets =
  497. m_LocalGenerators[i]->GetMakefile()->GetTargets();
  498. for (cmTargets::const_iterator l = targets.begin();
  499. l != targets.end(); l++)
  500. {
  501. cmTarget::LinkLibraries libs = l->second.GetLinkLibraries();
  502. for(cmTarget::LinkLibraries::iterator lib = libs.begin();
  503. lib != libs.end(); ++lib)
  504. {
  505. if(lib->first.size() > 9 &&
  506. cmSystemTools::IsNOTFOUND(lib->first.c_str()))
  507. {
  508. std::string varName = lib->first.substr(0, lib->first.size()-9);
  509. notFoundMap.insert(varName);
  510. }
  511. }
  512. std::vector<std::string>& incs =
  513. m_LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
  514. for( std::vector<std::string>::iterator lib = incs.begin();
  515. lib != incs.end(); ++lib)
  516. {
  517. if(lib->size() > 9 &&
  518. cmSystemTools::IsNOTFOUND(lib->c_str()))
  519. {
  520. std::string varName = lib->substr(0, lib->size()-9);
  521. notFoundMap.insert(varName);
  522. }
  523. }
  524. m_CMakeInstance->UpdateProgress("Configuring",
  525. 0.9f+0.1f*(i+1.0f)/m_LocalGenerators.size());
  526. m_LocalGenerators[i]->GetMakefile()->CheckInfiniteLoops();
  527. }
  528. }
  529. if(notFoundMap.size())
  530. {
  531. std::string notFoundVars;
  532. for(std::set<cmStdString>::iterator ii = notFoundMap.begin();
  533. ii != notFoundMap.end(); ++ii)
  534. {
  535. notFoundVars += *ii;
  536. if(manager)
  537. {
  538. cmCacheManager::CacheIterator it =
  539. manager->GetCacheIterator(ii->c_str());
  540. if(it.GetPropertyAsBool("ADVANCED"))
  541. {
  542. notFoundVars += " (ADVANCED)";
  543. }
  544. }
  545. notFoundVars += "\n";
  546. }
  547. cmSystemTools::Error("This project requires some variables to be set,\n"
  548. "and cmake can not find them.\n"
  549. "Please set the following variables:\n",
  550. notFoundVars.c_str());
  551. }
  552. // at this point m_LocalGenerators has been filled,
  553. // so create the map from project name to vector of local generators
  554. this->FillProjectMap();
  555. if ( !m_CMakeInstance->GetScriptMode() )
  556. {
  557. m_CMakeInstance->UpdateProgress("Configuring done", -1);
  558. }
  559. }
  560. void cmGlobalGenerator::Generate()
  561. {
  562. // For each existing cmLocalGenerator
  563. unsigned int i;
  564. for (i = 0; i < m_LocalGenerators.size(); ++i)
  565. {
  566. m_LocalGenerators[i]->Generate();
  567. m_LocalGenerators[i]->GenerateInstallRules();
  568. m_LocalGenerators[i]->GenerateTestFiles();
  569. m_CMakeInstance->UpdateProgress("Generating",
  570. (i+1.0f)/m_LocalGenerators.size());
  571. }
  572. m_CMakeInstance->UpdateProgress("Generating done", -1);
  573. }
  574. int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
  575. const char *projectName,
  576. const char *target,
  577. std::string *output, cmMakefile *mf)
  578. {
  579. std::string makeCommand =
  580. m_CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
  581. if(makeCommand.size() == 0)
  582. {
  583. cmSystemTools::Error(
  584. "Generator cannot find the appropriate make command.");
  585. return 1;
  586. }
  587. std::string newTarget;
  588. if (target && strlen(target))
  589. {
  590. newTarget += target;
  591. #if 0
  592. #if defined(_WIN32) || defined(__CYGWIN__)
  593. std::string tmp = target;
  594. // if the target does not already end in . something
  595. // then assume .exe
  596. if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
  597. {
  598. newTarget += ".exe";
  599. }
  600. #endif // WIN32
  601. #endif
  602. }
  603. const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
  604. return this->Build(srcdir,bindir,projectName,
  605. newTarget.c_str(),
  606. output,makeCommand.c_str(),config,false);
  607. }
  608. std::string cmGlobalGenerator::GenerateBuildCommand(const char* makeProgram,
  609. const char *projectName, const char *targetName, const char* config,
  610. bool ignoreErrors)
  611. {
  612. // Project name and config are not used yet.
  613. (void)projectName;
  614. (void)config;
  615. std::string makeCommand = cmSystemTools::ConvertToUnixOutputPath(makeProgram);
  616. // Since we have full control over the invocation of nmake, let us
  617. // make it quiet.
  618. if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
  619. {
  620. makeCommand += " /NOLOGO ";
  621. }
  622. if ( ignoreErrors )
  623. {
  624. makeCommand += " -i";
  625. }
  626. if ( targetName )
  627. {
  628. makeCommand += " ";
  629. makeCommand += targetName;
  630. }
  631. return makeCommand;
  632. }
  633. int cmGlobalGenerator::Build(
  634. const char *, const char *bindir,
  635. const char *projectName, const char *target,
  636. std::string *output,
  637. const char *makeCommandCSTR,
  638. const char *config,
  639. bool clean)
  640. {
  641. *output += "\nTesting TryCompileWithoutMakefile\n";
  642. /**
  643. * Run an executable command and put the stdout in output.
  644. */
  645. std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  646. cmSystemTools::ChangeDirectory(bindir);
  647. int retVal;
  648. int timeout = cmGlobalGenerator::s_TryCompileTimeout;
  649. bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
  650. cmSystemTools::SetRunCommandHideConsole(true);
  651. // should we do a clean first?
  652. if (clean)
  653. {
  654. std::string cleanCommand = this->GenerateBuildCommand(makeCommandCSTR, projectName, "clean", config, false);
  655. if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), output,
  656. &retVal, 0, false, timeout))
  657. {
  658. cmSystemTools::SetRunCommandHideConsole(hideconsole);
  659. cmSystemTools::Error("Generator: execution of make clean failed.");
  660. if (output)
  661. {
  662. *output += "\nGenerator: execution of make clean failed.\n";
  663. }
  664. // return to the original directory
  665. cmSystemTools::ChangeDirectory(cwd.c_str());
  666. return 1;
  667. }
  668. }
  669. // now build
  670. std::string makeCommand = this->GenerateBuildCommand(makeCommandCSTR, projectName, target, config, false);
  671. if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), output,
  672. &retVal, 0, false, timeout))
  673. {
  674. cmSystemTools::SetRunCommandHideConsole(hideconsole);
  675. cmSystemTools::Error("Generator: execution of make failed. Make command was: ",
  676. makeCommand.c_str());
  677. if (output)
  678. {
  679. *output += "\nGenerator: execution of make failed. Make command was: " +
  680. makeCommand + "\n";
  681. }
  682. // return to the original directory
  683. cmSystemTools::ChangeDirectory(cwd.c_str());
  684. return 1;
  685. }
  686. cmSystemTools::SetRunCommandHideConsole(hideconsole);
  687. // The SGI MipsPro 7.3 compiler does not return an error code when
  688. // the source has a #error in it! This is a work-around for such
  689. // compilers.
  690. if((retVal == 0) && (output->find("#error") != std::string::npos))
  691. {
  692. retVal = 1;
  693. }
  694. cmSystemTools::ChangeDirectory(cwd.c_str());
  695. return retVal;
  696. }
  697. void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
  698. {
  699. m_LocalGenerators.push_back(lg);
  700. // update progress
  701. // estimate how many lg there will be
  702. const char *numGenC =
  703. m_CMakeInstance->GetCacheManager()->GetCacheValue
  704. ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
  705. if (!numGenC)
  706. {
  707. return;
  708. }
  709. int numGen = atoi(numGenC);
  710. float prog = 0.9f*m_LocalGenerators.size()/numGen;
  711. if (prog > 0.9f)
  712. {
  713. prog = 0.9f;
  714. }
  715. m_CMakeInstance->UpdateProgress("Configuring", prog);
  716. }
  717. cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
  718. {
  719. cmLocalGenerator *lg = new cmLocalGenerator;
  720. lg->SetGlobalGenerator(this);
  721. return lg;
  722. }
  723. void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen )
  724. {
  725. this->SetConfiguredFilesPath(
  726. gen->GetCMakeInstance()->GetHomeOutputDirectory());
  727. const char* make =
  728. gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
  729. this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
  730. "make program",
  731. cmCacheManager::FILEPATH);
  732. // copy the enabled languages
  733. this->m_LanguageEnabled = gen->m_LanguageEnabled;
  734. this->m_ExtensionToLanguage = gen->m_ExtensionToLanguage;
  735. this->m_IgnoreExtensions = gen->m_IgnoreExtensions;
  736. this->m_LanguageToOutputExtension = gen->m_LanguageToOutputExtension;
  737. this->m_LanguageToLinkerPreference = gen->m_LanguageToLinkerPreference;
  738. this->m_OutputExtensions = gen->m_OutputExtensions;
  739. }
  740. //----------------------------------------------------------------------------
  741. void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
  742. {
  743. entry.name = this->GetName();
  744. entry.brief = "";
  745. entry.full = "";
  746. }
  747. bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
  748. cmLocalGenerator* gen)
  749. {
  750. cmLocalGenerator* cur = gen->GetParent();
  751. while(cur && cur != root)
  752. {
  753. if(cur->GetExcludeAll())
  754. {
  755. return true;
  756. }
  757. cur = cur->GetParent();
  758. }
  759. return false;
  760. }
  761. void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
  762. {
  763. for(std::map<cmStdString, bool>::iterator i = m_LanguageEnabled.begin();
  764. i != m_LanguageEnabled.end(); ++i)
  765. {
  766. lang.push_back(i->first);
  767. }
  768. }
  769. const char* cmGlobalGenerator::GetLinkerPreference(const char* lang)
  770. {
  771. if(m_LanguageToLinkerPreference.count(lang))
  772. {
  773. return m_LanguageToLinkerPreference[lang].c_str();
  774. }
  775. return "None";
  776. }
  777. void cmGlobalGenerator::FillProjectMap()
  778. {
  779. m_ProjectMap.clear(); // make sure we start with a clean map
  780. unsigned int i;
  781. for(i = 0; i < m_LocalGenerators.size(); ++i)
  782. {
  783. // for each local generator add all projects
  784. cmLocalGenerator *lg = m_LocalGenerators[i];
  785. std::string name;
  786. do
  787. {
  788. if (name != lg->GetMakefile()->GetProjectName())
  789. {
  790. name = lg->GetMakefile()->GetProjectName();
  791. m_ProjectMap[name].push_back(m_LocalGenerators[i]);
  792. }
  793. lg = lg->GetParent();
  794. }
  795. while (lg);
  796. }
  797. }
  798. cmTarget* cmGlobalGenerator::FindTarget(const char* project,
  799. const char* name)
  800. {
  801. std::vector<cmLocalGenerator*>* gens = &m_LocalGenerators;
  802. if(project)
  803. {
  804. gens = &m_ProjectMap[project];
  805. }
  806. for(unsigned int i = 0; i < gens->size(); ++i)
  807. {
  808. cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
  809. if(ret)
  810. {
  811. return ret;
  812. }
  813. }
  814. return 0;
  815. }
  816. //----------------------------------------------------------------------------
  817. void cmGlobalGenerator::ConfigureRelativePaths()
  818. {
  819. // Identify the longest shared path component between the source
  820. // directory and the build directory.
  821. std::vector<std::string> source;
  822. std::vector<std::string> binary;
  823. cmSystemTools::SplitPath(m_CMakeInstance->GetHomeDirectory(), source);
  824. cmSystemTools::SplitPath(m_CMakeInstance->GetHomeOutputDirectory(), binary);
  825. unsigned int common=0;
  826. while(common < source.size() && common < binary.size() &&
  827. cmSystemTools::ComparePath(source[common].c_str(),
  828. binary[common].c_str()))
  829. {
  830. ++common;
  831. }
  832. // Require more than just the root portion of the path to be in
  833. // common before allowing relative paths. Also disallow relative
  834. // paths if the build tree is a network path. The current working
  835. // directory on Windows cannot be a network path. Therefore
  836. // relative paths cannot work with network paths.
  837. if(common > 1 && source[0] != "//")
  838. {
  839. // Build the minimum prefix required of a path to be converted to
  840. // a relative path.
  841. source.erase(source.begin()+common, source.end());
  842. m_RelativePathTop = cmSystemTools::JoinPath(source);
  843. }
  844. else
  845. {
  846. // Disable relative paths.
  847. m_RelativePathTop = "";
  848. }
  849. }
  850. //----------------------------------------------------------------------------
  851. std::string
  852. cmGlobalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
  853. const char* in_remote)
  854. {
  855. // The path should never be quoted.
  856. assert(in_remote[0] != '\"');
  857. // The local path should never have a trailing slash.
  858. assert(local.size() > 0 && !(local[local.size()-1] == ""));
  859. // If the path is already relative or relative paths are disabled
  860. // then just return the path.
  861. if(m_RelativePathTop.size() == 0 ||
  862. !cmSystemTools::FileIsFullPath(in_remote))
  863. {
  864. return in_remote;
  865. }
  866. // If the path does not begin with the minimum relative path prefix
  867. // then do not convert it.
  868. std::string original = in_remote;
  869. if(original.size() < m_RelativePathTop.size() ||
  870. !cmSystemTools::ComparePath(
  871. original.substr(0, m_RelativePathTop.size()).c_str(),
  872. m_RelativePathTop.c_str()))
  873. {
  874. return in_remote;
  875. }
  876. // Identify the longest shared path component between the remote
  877. // path and the local path.
  878. std::vector<std::string> remote;
  879. cmSystemTools::SplitPath(in_remote, remote);
  880. unsigned int common=0;
  881. while(common < remote.size() &&
  882. common < local.size() &&
  883. cmSystemTools::ComparePath(remote[common].c_str(),
  884. local[common].c_str()))
  885. {
  886. ++common;
  887. }
  888. // If the entire path is in common then just return a ".".
  889. if(common == remote.size() &&
  890. common == local.size())
  891. {
  892. return ".";
  893. }
  894. // If the entire path is in common except for a trailing slash then
  895. // just return a "./".
  896. if(common+1 == remote.size() &&
  897. remote[common].size() == 0 &&
  898. common == local.size())
  899. {
  900. return "./";
  901. }
  902. // Construct the relative path.
  903. std::string relative;
  904. // First add enough ../ to get up to the level of the shared portion
  905. // of the path. Leave off the trailing slash. Note that the last
  906. // component of local will never be empty because local should never
  907. // have a trailing slash.
  908. for(unsigned int i=common; i < local.size(); ++i)
  909. {
  910. relative += "..";
  911. if(i < local.size()-1)
  912. {
  913. relative += "/";
  914. }
  915. }
  916. // Now add the portion of the destination path that is not included
  917. // in the shared portion of the path. Add a slash the first time
  918. // only if there was already something in the path. If there was a
  919. // trailing slash in the input then the last iteration of the loop
  920. // will add a slash followed by an empty string which will preserve
  921. // the trailing slash in the output.
  922. for(unsigned int i=common; i < remote.size(); ++i)
  923. {
  924. if(relative.size() > 0)
  925. {
  926. relative += "/";
  927. }
  928. relative += remote[i];
  929. }
  930. // Finally return the path.
  931. return relative;
  932. }
  933. inline std::string removeQuotes(const std::string& s)
  934. {
  935. if(s[0] == '\"' && s[s.size()-1] == '\"')
  936. {
  937. return s.substr(1, s.size()-2);
  938. }
  939. return s;
  940. }
  941. void cmGlobalGenerator::SetupTests()
  942. {
  943. std::string ctest =
  944. m_LocalGenerators[0]->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
  945. ctest = removeQuotes(ctest);
  946. ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
  947. ctest += "/";
  948. ctest += "ctest";
  949. ctest += cmSystemTools::GetExecutableExtension();
  950. if(!cmSystemTools::FileExists(ctest.c_str()))
  951. {
  952. ctest =
  953. m_LocalGenerators[0]->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
  954. ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
  955. ctest += "/Debug/";
  956. ctest += "ctest";
  957. ctest += cmSystemTools::GetExecutableExtension();
  958. }
  959. if(!cmSystemTools::FileExists(ctest.c_str()))
  960. {
  961. ctest =
  962. m_LocalGenerators[0]->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
  963. ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
  964. ctest += "/Release/";
  965. ctest += "ctest";
  966. ctest += cmSystemTools::GetExecutableExtension();
  967. }
  968. // if we found ctest
  969. if (cmSystemTools::FileExists(ctest.c_str()))
  970. {
  971. // Create a full path filename for output Testfile
  972. std::string fname;
  973. fname = m_CMakeInstance->GetStartOutputDirectory();
  974. fname += "/";
  975. if ( m_LocalGenerators[0]->GetMakefile()->IsSet("CTEST_NEW_FORMAT") )
  976. {
  977. fname += "CTestTestfile.txt";
  978. }
  979. else
  980. {
  981. fname += "DartTestfile.txt";
  982. }
  983. // If the file doesn't exist, then ENABLE_TESTING hasn't been run
  984. if (cmSystemTools::FileExists(fname.c_str()))
  985. {
  986. const char* no_output = 0;
  987. std::vector<std::string> no_depends;
  988. std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
  989. for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
  990. {
  991. std::vector<cmLocalGenerator*>& gen = it->second;
  992. // add the ALL_BUILD to the first local generator of each project
  993. if(gen.size())
  994. {
  995. gen[0]->GetMakefile()->
  996. AddUtilityCommand("RUN_TESTS", false, no_output, no_depends,
  997. ctest.c_str(), "-C", "$(IntDir)");
  998. }
  999. }
  1000. }
  1001. }
  1002. }