cmLocalGenerator.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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 "cmGlobalGenerator.h"
  15. #include "cmake.h"
  16. #include "cmMakefile.h"
  17. #include "cmGeneratedFileStream.h"
  18. cmLocalGenerator::cmLocalGenerator()
  19. {
  20. m_Makefile = new cmMakefile;
  21. m_Makefile->SetLocalGenerator(this);
  22. }
  23. cmLocalGenerator::~cmLocalGenerator()
  24. {
  25. delete m_Makefile;
  26. }
  27. void cmLocalGenerator::Configure()
  28. {
  29. // set the PROJECT_SOURCE_DIR and PROJECT_BIN_DIR to default values
  30. // just in case the project does not include a PROJECT command
  31. m_Makefile->AddDefinition("PROJECT_BINARY_DIR",
  32. m_Makefile->GetHomeOutputDirectory());
  33. m_Makefile->AddDefinition("PROJECT_SOURCE_DIR",
  34. m_Makefile->GetHomeDirectory());
  35. // find & read the list file
  36. std::string currentStart = m_Makefile->GetStartDirectory();
  37. currentStart += "/CMakeLists.txt";
  38. m_Makefile->ReadListFile(currentStart.c_str());
  39. }
  40. void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
  41. {
  42. m_GlobalGenerator = gg;
  43. // setup the home directories
  44. m_Makefile->SetHomeDirectory(
  45. gg->GetCMakeInstance()->GetHomeDirectory());
  46. m_Makefile->SetHomeOutputDirectory(
  47. gg->GetCMakeInstance()->GetHomeOutputDirectory());
  48. }
  49. void cmLocalGenerator::ConfigureFinalPass()
  50. {
  51. m_Makefile->ConfigureFinalPass();
  52. }
  53. void cmLocalGenerator::GenerateInstallRules()
  54. {
  55. const cmTargets &tgts = m_Makefile->GetTargets();
  56. const char* prefix
  57. = m_Makefile->GetDefinition("CMAKE_INSTALL_PREFIX");
  58. if (!prefix)
  59. {
  60. prefix = "/usr/local";
  61. }
  62. std::string file = m_Makefile->GetStartOutputDirectory();
  63. cmSystemTools::ConvertToUnixSlashes(file);
  64. file += "/cmake_install.cmake";
  65. cmGeneratedFileStream tempFile(file.c_str());
  66. std::ostream& fout = tempFile.GetStream();
  67. fout << "# Install script for directory: " << m_Makefile->GetCurrentDirectory()
  68. << std::endl << std::endl;
  69. const char* cmakeDebugPosfix = m_Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
  70. if ( cmakeDebugPosfix )
  71. {
  72. fout << "SET(CMAKE_DEBUG_POSTFIX \"" << cmakeDebugPosfix << "\")"
  73. << std::endl << std::endl;
  74. }
  75. std::string libOutPath = "";
  76. if (m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
  77. {
  78. libOutPath = m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
  79. if(libOutPath.size())
  80. {
  81. if(libOutPath[libOutPath.size() -1] != '/')
  82. {
  83. libOutPath += "/";
  84. }
  85. }
  86. }
  87. std::string exeOutPath = "";
  88. if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
  89. {
  90. exeOutPath =
  91. m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  92. if(exeOutPath.size())
  93. {
  94. if(exeOutPath[exeOutPath.size() -1] != '/')
  95. {
  96. exeOutPath += "/";
  97. }
  98. }
  99. }
  100. std::string destination;
  101. for(cmTargets::const_iterator l = tgts.begin();
  102. l != tgts.end(); l++)
  103. {
  104. if (l->second.GetInstallPath() != "")
  105. {
  106. destination = prefix + l->second.GetInstallPath();
  107. cmSystemTools::ConvertToUnixSlashes(destination);
  108. const char* dest = destination.c_str();
  109. int type = l->second.GetType();
  110. std::string fname;
  111. const char* files;
  112. // now install the target
  113. switch (type)
  114. {
  115. case cmTarget::STATIC_LIBRARY:
  116. case cmTarget::MODULE_LIBRARY:
  117. fname = libOutPath;
  118. fname += this->GetFullTargetName(l->first.c_str(), l->second);
  119. files = fname.c_str();
  120. this->AddInstallRule(fout, dest, type, files);
  121. break;
  122. case cmTarget::SHARED_LIBRARY:
  123. {
  124. // Special code to handle DLL
  125. fname = libOutPath;
  126. fname += this->GetFullTargetName(l->first.c_str(), l->second);
  127. std::string ext = cmSystemTools::GetFilenameExtension(fname);
  128. ext = cmSystemTools::LowerCase(ext);
  129. if ( ext == ".dll" )
  130. {
  131. std::string libname = libOutPath;
  132. libname += cmSystemTools::GetFilenameWithoutExtension(fname);
  133. libname += ".lib";
  134. files = libname.c_str();
  135. this->AddInstallRule(fout, dest, cmTarget::STATIC_LIBRARY, files, true);
  136. std::string dlldest = prefix + l->second.GetRuntimeInstallPath();
  137. files = fname.c_str();
  138. this->AddInstallRule(fout, dlldest.c_str(), type, files);
  139. }
  140. else
  141. {
  142. files = fname.c_str();
  143. this->AddInstallRule(fout, dest, type, files);
  144. }
  145. }
  146. break;
  147. case cmTarget::EXECUTABLE:
  148. fname = exeOutPath;
  149. fname += this->GetFullTargetName(l->first.c_str(), l->second);
  150. files = fname.c_str();
  151. this->AddInstallRule(fout, dest, type, files);
  152. break;
  153. case cmTarget::INSTALL_FILES:
  154. {
  155. std::string sourcePath = m_Makefile->GetCurrentDirectory();
  156. std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
  157. sourcePath += "/";
  158. binaryPath += "/";
  159. const std::vector<std::string> &sf = l->second.GetSourceLists();
  160. std::vector<std::string>::const_iterator i;
  161. for (i = sf.begin(); i != sf.end(); ++i)
  162. {
  163. std::string f = *i;
  164. if(f.substr(0, sourcePath.length()) == sourcePath)
  165. {
  166. f = f.substr(sourcePath.length());
  167. }
  168. else if(f.substr(0, binaryPath.length()) == binaryPath)
  169. {
  170. f = f.substr(binaryPath.length());
  171. }
  172. files = i->c_str();
  173. this->AddInstallRule(fout, dest, type, files);
  174. }
  175. }
  176. break;
  177. case cmTarget::INSTALL_PROGRAMS:
  178. {
  179. std::string sourcePath = m_Makefile->GetCurrentDirectory();
  180. std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
  181. sourcePath += "/";
  182. binaryPath += "/";
  183. const std::vector<std::string> &sf = l->second.GetSourceLists();
  184. std::vector<std::string>::const_iterator i;
  185. for (i = sf.begin(); i != sf.end(); ++i)
  186. {
  187. std::string f = *i;
  188. if(f.substr(0, sourcePath.length()) == sourcePath)
  189. {
  190. f = f.substr(sourcePath.length());
  191. }
  192. else if(f.substr(0, binaryPath.length()) == binaryPath)
  193. {
  194. f = f.substr(binaryPath.length());
  195. }
  196. files = i->c_str();
  197. this->AddInstallRule(fout, dest, type, files);
  198. }
  199. }
  200. break;
  201. case cmTarget::UTILITY:
  202. default:
  203. break;
  204. }
  205. }
  206. }
  207. cmMakefile* mf = this->GetMakefile();
  208. if ( !mf->GetSubDirectories().empty() )
  209. {
  210. const std::vector<std::string>& subdirs = mf->GetSubDirectories();
  211. std::vector<std::string>::const_iterator i = subdirs.begin();
  212. for(; i != subdirs.end(); ++i)
  213. {
  214. std::string odir = mf->GetCurrentOutputDirectory();
  215. odir += "/" + (*i);
  216. cmSystemTools::ConvertToUnixSlashes(odir);
  217. fout << "INCLUDE(" << odir.c_str()
  218. << "/cmake_install.cmake)" << std::endl;
  219. }
  220. fout << std::endl;;
  221. }
  222. }
  223. void cmLocalGenerator::AddInstallRule(std::ostream& fout, const char* dest,
  224. int type, const char* files, bool optional)
  225. {
  226. std::string sfiles = files;
  227. std::string destination = dest;
  228. std::string stype;
  229. switch ( type )
  230. {
  231. case cmTarget::INSTALL_PROGRAMS: stype = "PROGRAM"; break;
  232. case cmTarget::EXECUTABLE: stype = "EXECUTABLE"; break;
  233. case cmTarget::STATIC_LIBRARY: stype = "STATIC_LIBRARY"; break;
  234. case cmTarget::SHARED_LIBRARY: stype = "SHARED_LIBRARY"; break;
  235. case cmTarget::MODULE_LIBRARY: stype = "MODULE"; break;
  236. case cmTarget::INSTALL_FILES:
  237. default: stype = "FILE"; break;
  238. }
  239. std::string fname = cmSystemTools::GetFilenameName(sfiles.c_str());
  240. fout
  241. << "MESSAGE(STATUS \"Installing " << destination.c_str()
  242. << "/" << fname.c_str() << "\")\n"
  243. << "FILE(INSTALL DESTINATION \"" << destination.c_str()
  244. << "\" TYPE " << stype.c_str() << (optional?" OPTIONAL":"")
  245. << " FILES \"" << sfiles.c_str() << "\")\n";
  246. }
  247. const char* cmLocalGenerator::GetSafeDefinition(const char* def)
  248. {
  249. const char* ret = m_Makefile->GetDefinition(def);
  250. if(!ret)
  251. {
  252. return "";
  253. }
  254. return ret;
  255. }
  256. std::string cmLocalGenerator::GetFullTargetName(const char* n,
  257. const cmTarget& t)
  258. {
  259. const char* targetPrefix = t.GetProperty("PREFIX");
  260. const char* targetSuffix = t.GetProperty("SUFFIX");
  261. const char* prefixVar = 0;
  262. const char* suffixVar = 0;
  263. switch(t.GetType())
  264. {
  265. case cmTarget::STATIC_LIBRARY:
  266. prefixVar = "CMAKE_STATIC_LIBRARY_PREFIX";
  267. suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX";
  268. break;
  269. case cmTarget::SHARED_LIBRARY:
  270. prefixVar = "CMAKE_SHARED_LIBRARY_PREFIX";
  271. suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX";
  272. break;
  273. case cmTarget::MODULE_LIBRARY:
  274. prefixVar = "CMAKE_SHARED_MODULE_PREFIX";
  275. suffixVar = "CMAKE_SHARED_MODULE_SUFFIX";
  276. break;
  277. case cmTarget::EXECUTABLE:
  278. targetSuffix = cmSystemTools::GetExecutableExtension();
  279. case cmTarget::UTILITY:
  280. case cmTarget::INSTALL_FILES:
  281. case cmTarget::INSTALL_PROGRAMS:
  282. break;
  283. }
  284. // if there is no prefix on the target use the cmake definition
  285. if(!targetPrefix && prefixVar)
  286. {
  287. targetPrefix = this->GetSafeDefinition(prefixVar);
  288. }
  289. // if there is no suffix on the target use the cmake definition
  290. if(!targetSuffix && suffixVar)
  291. {
  292. targetSuffix = this->GetSafeDefinition(suffixVar);
  293. }
  294. std::string name = targetPrefix?targetPrefix:"";
  295. name += n;
  296. name += targetSuffix?targetSuffix:"";
  297. return name;
  298. }
  299. std::string cmLocalGenerator::ConvertToRelativeOutputPath(const char* p)
  300. {
  301. if ( m_Makefile->GetDefinition("CMAKE_NO_RELATIVE_PATHS") )
  302. {
  303. return cmSystemTools::ConvertToOutputPath(p);
  304. }
  305. // do not use relative paths for network build trees
  306. // the network paths do not work
  307. const char* outputDirectory = m_Makefile->GetHomeOutputDirectory();
  308. if ( outputDirectory && *outputDirectory && *(outputDirectory+1) &&
  309. outputDirectory[0] == '/' && outputDirectory[1] == '/' )
  310. {
  311. return cmSystemTools::ConvertToOutputPath(p);
  312. }
  313. // The first time this is called, initialize all
  314. // the path ivars that are used. This can not
  315. // be moved to the constructor because all the paths are not set yet.
  316. if(m_CurrentOutputDirectory.size() == 0)
  317. {
  318. m_CurrentOutputDirectory = m_Makefile->GetCurrentOutputDirectory();
  319. m_HomeOutputDirectory = m_Makefile->GetHomeOutputDirectory();
  320. m_HomeDirectory = m_Makefile->GetHomeDirectory();
  321. if(m_RelativePathToSourceDir.size() == 0)
  322. {
  323. m_RelativePathToSourceDir = cmSystemTools::RelativePath(
  324. m_CurrentOutputDirectory.c_str(),
  325. m_HomeDirectory.c_str());
  326. std::string path = m_CurrentOutputDirectory;
  327. cmSystemTools::ReplaceString(path, m_HomeOutputDirectory.c_str(), "");
  328. unsigned i;
  329. m_RelativePathToBinaryDir = "";
  330. for(i =0; i < path.size(); ++i)
  331. {
  332. if(path[i] == '/')
  333. {
  334. m_RelativePathToBinaryDir += "../";
  335. }
  336. }
  337. }
  338. m_HomeOutputDirectoryNoSlash = m_HomeOutputDirectory;
  339. m_HomeOutputDirectory += "/";
  340. m_CurrentOutputDirectory += "/";
  341. }
  342. // Do the work of converting to a relative path
  343. std::string pathIn = p;
  344. if(pathIn.find('/') == pathIn.npos)
  345. {
  346. return pathIn;
  347. }
  348. if(pathIn.size() && pathIn[0] == '\"')
  349. {
  350. pathIn = pathIn.substr(1, pathIn.size()-2);
  351. }
  352. std::string ret = pathIn;
  353. if(m_CurrentOutputDirectory.size() <= ret.size())
  354. {
  355. std::string sub = ret.substr(0, m_CurrentOutputDirectory.size());
  356. if(
  357. #if defined(_WIN32) || defined(__APPLE__)
  358. cmSystemTools::LowerCase(sub) ==
  359. cmSystemTools::LowerCase(m_CurrentOutputDirectory)
  360. #else
  361. sub == m_CurrentOutputDirectory
  362. #endif
  363. )
  364. {
  365. ret = ret.substr(m_CurrentOutputDirectory.size(), ret.npos);
  366. }
  367. }
  368. if(m_HomeDirectory.size() <= ret.size())
  369. {
  370. std::string sub = ret.substr(0, m_HomeDirectory.size());
  371. if(
  372. #if defined(_WIN32) || defined(__APPLE__)
  373. cmSystemTools::LowerCase(sub) ==
  374. cmSystemTools::LowerCase(m_HomeDirectory)
  375. #else
  376. sub == m_HomeDirectory
  377. #endif
  378. )
  379. {
  380. ret = m_RelativePathToSourceDir + ret.substr(m_HomeDirectory.size(), ret.npos);
  381. }
  382. }
  383. if(m_HomeOutputDirectory.size() <= ret.size())
  384. {
  385. std::string sub = ret.substr(0, m_HomeOutputDirectory.size());
  386. if(
  387. #if defined(_WIN32) || defined(__APPLE__)
  388. cmSystemTools::LowerCase(sub) ==
  389. cmSystemTools::LowerCase(m_HomeOutputDirectory)
  390. #else
  391. sub == m_HomeOutputDirectory
  392. #endif
  393. )
  394. {
  395. ret = m_RelativePathToBinaryDir + ret.substr(m_HomeOutputDirectory.size(), ret.npos);
  396. }
  397. }
  398. std::string relpath = m_RelativePathToBinaryDir;
  399. if(relpath.size())
  400. {
  401. relpath.erase(relpath.size()-1, 1);
  402. }
  403. else
  404. {
  405. relpath = ".";
  406. }
  407. if(
  408. #if defined(_WIN32) || defined(__APPLE__)
  409. cmSystemTools::LowerCase(ret) ==
  410. cmSystemTools::LowerCase(m_HomeOutputDirectoryNoSlash)
  411. #else
  412. ret == m_HomeOutputDirectoryNoSlash
  413. #endif
  414. )
  415. {
  416. ret = relpath;
  417. }
  418. // Relative paths should always start in a '.', so add a './' if
  419. // necessary.
  420. if(ret.size()
  421. && ret[0] != '\"' && ret[0] != '/' && ret[0] != '.' && ret[0] != '$')
  422. {
  423. if(ret.size() > 1 && ret[1] != ':')
  424. {
  425. ret = std::string("./") + ret;
  426. }
  427. }
  428. ret = cmSystemTools::ConvertToOutputPath(ret.c_str());
  429. return ret;
  430. }