cmLocalGenerator.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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::WIN32_EXECUTABLE:
  148. case cmTarget::EXECUTABLE:
  149. fname = exeOutPath;
  150. fname += this->GetFullTargetName(l->first.c_str(), l->second);
  151. files = fname.c_str();
  152. this->AddInstallRule(fout, dest, type, files);
  153. break;
  154. case cmTarget::INSTALL_FILES:
  155. {
  156. std::string sourcePath = m_Makefile->GetCurrentDirectory();
  157. std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
  158. sourcePath += "/";
  159. binaryPath += "/";
  160. const std::vector<std::string> &sf = l->second.GetSourceLists();
  161. std::vector<std::string>::const_iterator i;
  162. for (i = sf.begin(); i != sf.end(); ++i)
  163. {
  164. std::string f = *i;
  165. if(f.substr(0, sourcePath.length()) == sourcePath)
  166. {
  167. f = f.substr(sourcePath.length());
  168. }
  169. else if(f.substr(0, binaryPath.length()) == binaryPath)
  170. {
  171. f = f.substr(binaryPath.length());
  172. }
  173. files = i->c_str();
  174. this->AddInstallRule(fout, dest, type, files);
  175. }
  176. }
  177. break;
  178. case cmTarget::INSTALL_PROGRAMS:
  179. {
  180. std::string sourcePath = m_Makefile->GetCurrentDirectory();
  181. std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
  182. sourcePath += "/";
  183. binaryPath += "/";
  184. const std::vector<std::string> &sf = l->second.GetSourceLists();
  185. std::vector<std::string>::const_iterator i;
  186. for (i = sf.begin(); i != sf.end(); ++i)
  187. {
  188. std::string f = *i;
  189. if(f.substr(0, sourcePath.length()) == sourcePath)
  190. {
  191. f = f.substr(sourcePath.length());
  192. }
  193. else if(f.substr(0, binaryPath.length()) == binaryPath)
  194. {
  195. f = f.substr(binaryPath.length());
  196. }
  197. files = i->c_str();
  198. this->AddInstallRule(fout, dest, type, files);
  199. }
  200. }
  201. break;
  202. case cmTarget::UTILITY:
  203. default:
  204. break;
  205. }
  206. }
  207. }
  208. cmMakefile* mf = this->GetMakefile();
  209. if ( !mf->GetSubDirectories().empty() )
  210. {
  211. const std::vector<std::string>& subdirs = mf->GetSubDirectories();
  212. std::vector<std::string>::const_iterator i = subdirs.begin();
  213. for(; i != subdirs.end(); ++i)
  214. {
  215. std::string odir = mf->GetCurrentOutputDirectory();
  216. odir += "/" + (*i);
  217. cmSystemTools::ConvertToUnixSlashes(odir);
  218. fout << "INCLUDE(" << odir.c_str()
  219. << "/cmake_install.cmake)" << std::endl;
  220. }
  221. fout << std::endl;;
  222. }
  223. }
  224. void cmLocalGenerator::AddInstallRule(std::ostream& fout, const char* dest,
  225. int type, const char* files, bool optional)
  226. {
  227. std::string sfiles = files;
  228. std::string destination = dest;
  229. std::string stype;
  230. switch ( type )
  231. {
  232. case cmTarget::INSTALL_PROGRAMS: stype = "PROGRAM"; break;
  233. case cmTarget::EXECUTABLE:
  234. case cmTarget::WIN32_EXECUTABLE: stype = "EXECUTABLE"; break;
  235. case cmTarget::STATIC_LIBRARY: stype = "STATIC_LIBRARY"; break;
  236. case cmTarget::SHARED_LIBRARY: stype = "SHARED_LIBRARY"; break;
  237. case cmTarget::MODULE_LIBRARY: stype = "MODULE"; break;
  238. case cmTarget::INSTALL_FILES:
  239. default: stype = "FILE"; break;
  240. }
  241. std::string fname = cmSystemTools::GetFilenameName(sfiles.c_str());
  242. fout
  243. << "MESSAGE(STATUS \"Installing " << destination.c_str()
  244. << "/" << fname.c_str() << "\")\n"
  245. << "FILE(INSTALL DESTINATION \"" << destination.c_str()
  246. << "\" TYPE " << stype.c_str() << (optional?" OPTIONAL":"")
  247. << " FILES \"" << sfiles.c_str() << "\")\n";
  248. }
  249. const char* cmLocalGenerator::GetSafeDefinition(const char* def)
  250. {
  251. const char* ret = m_Makefile->GetDefinition(def);
  252. if(!ret)
  253. {
  254. return "";
  255. }
  256. return ret;
  257. }
  258. std::string cmLocalGenerator::GetFullTargetName(const char* n,
  259. const cmTarget& t)
  260. {
  261. const char* targetPrefix = t.GetProperty("PREFIX");
  262. const char* targetSuffix = t.GetProperty("SUFFIX");
  263. const char* prefixVar = 0;
  264. const char* suffixVar = 0;
  265. switch(t.GetType())
  266. {
  267. case cmTarget::STATIC_LIBRARY:
  268. prefixVar = "CMAKE_STATIC_LIBRARY_PREFIX";
  269. suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX";
  270. break;
  271. case cmTarget::SHARED_LIBRARY:
  272. prefixVar = "CMAKE_SHARED_LIBRARY_PREFIX";
  273. suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX";
  274. break;
  275. case cmTarget::MODULE_LIBRARY:
  276. prefixVar = "CMAKE_SHARED_MODULE_PREFIX";
  277. suffixVar = "CMAKE_SHARED_MODULE_SUFFIX";
  278. break;
  279. case cmTarget::EXECUTABLE:
  280. case cmTarget::WIN32_EXECUTABLE:
  281. targetSuffix = cmSystemTools::GetExecutableExtension();
  282. case cmTarget::UTILITY:
  283. case cmTarget::INSTALL_FILES:
  284. case cmTarget::INSTALL_PROGRAMS:
  285. break;
  286. }
  287. // if there is no prefix on the target use the cmake definition
  288. if(!targetPrefix && prefixVar)
  289. {
  290. targetPrefix = this->GetSafeDefinition(prefixVar);
  291. }
  292. // if there is no suffix on the target use the cmake definition
  293. if(!targetSuffix && suffixVar)
  294. {
  295. targetSuffix = this->GetSafeDefinition(suffixVar);
  296. }
  297. std::string name = targetPrefix?targetPrefix:"";
  298. name += n;
  299. name += targetSuffix?targetSuffix:"";
  300. return name;
  301. }
  302. std::string cmLocalGenerator::ConvertToRelativeOutputPath(const char* p)
  303. {
  304. // do not use relative paths for network build trees
  305. // the network paths do not work
  306. const char* outputDirectory = m_Makefile->GetHomeOutputDirectory();
  307. if ( outputDirectory && *outputDirectory && *(outputDirectory+1) &&
  308. outputDirectory[0] == '/' && outputDirectory[1] == '/' )
  309. {
  310. return cmSystemTools::ConvertToOutputPath(p);
  311. }
  312. // The first time this is called, initialize all
  313. // the path ivars that are used. This can not
  314. // be moved to the constructor because all the paths are not set yet.
  315. if(m_CurrentOutputDirectory.size() == 0)
  316. {
  317. m_CurrentOutputDirectory = m_Makefile->GetCurrentOutputDirectory();
  318. m_HomeOutputDirectory = m_Makefile->GetHomeOutputDirectory();
  319. m_HomeDirectory = m_Makefile->GetHomeDirectory();
  320. if(m_RelativePathToSourceDir.size() == 0)
  321. {
  322. m_RelativePathToSourceDir = cmSystemTools::RelativePath(
  323. m_CurrentOutputDirectory.c_str(),
  324. m_HomeDirectory.c_str());
  325. std::string path = m_CurrentOutputDirectory;
  326. cmSystemTools::ReplaceString(path, m_HomeOutputDirectory.c_str(), "");
  327. unsigned i;
  328. m_RelativePathToBinaryDir = "";
  329. for(i =0; i < path.size(); ++i)
  330. {
  331. if(path[i] == '/')
  332. {
  333. m_RelativePathToBinaryDir += "../";
  334. }
  335. }
  336. }
  337. m_HomeOutputDirectoryNoSlash = m_HomeOutputDirectory;
  338. m_HomeOutputDirectory += "/";
  339. m_CurrentOutputDirectory += "/";
  340. }
  341. // Do the work of converting to a relative path
  342. std::string pathIn = p;
  343. if(pathIn.find('/') == pathIn.npos)
  344. {
  345. return pathIn;
  346. }
  347. if(pathIn.size() && pathIn[0] == '\"')
  348. {
  349. pathIn = pathIn.substr(1, pathIn.size()-2);
  350. }
  351. std::string ret = pathIn;
  352. if(m_CurrentOutputDirectory.size() <= ret.size())
  353. {
  354. std::string sub = ret.substr(0, m_CurrentOutputDirectory.size());
  355. if(
  356. #if defined(_WIN32) || defined(__APPLE__)
  357. cmSystemTools::LowerCase(sub) ==
  358. cmSystemTools::LowerCase(m_CurrentOutputDirectory)
  359. #else
  360. sub == m_CurrentOutputDirectory
  361. #endif
  362. )
  363. {
  364. ret = ret.substr(m_CurrentOutputDirectory.size(), ret.npos);
  365. }
  366. }
  367. if(m_HomeDirectory.size() <= ret.size())
  368. {
  369. std::string sub = ret.substr(0, m_HomeDirectory.size());
  370. if(
  371. #if defined(_WIN32) || defined(__APPLE__)
  372. cmSystemTools::LowerCase(sub) ==
  373. cmSystemTools::LowerCase(m_HomeDirectory)
  374. #else
  375. sub == m_HomeDirectory
  376. #endif
  377. )
  378. {
  379. ret = m_RelativePathToSourceDir + ret.substr(m_HomeDirectory.size(), ret.npos);
  380. }
  381. }
  382. if(m_HomeOutputDirectory.size() <= ret.size())
  383. {
  384. std::string sub = ret.substr(0, m_HomeOutputDirectory.size());
  385. if(
  386. #if defined(_WIN32) || defined(__APPLE__)
  387. cmSystemTools::LowerCase(sub) ==
  388. cmSystemTools::LowerCase(m_HomeOutputDirectory)
  389. #else
  390. sub == m_HomeOutputDirectory
  391. #endif
  392. )
  393. {
  394. ret = m_RelativePathToBinaryDir + ret.substr(m_HomeOutputDirectory.size(), ret.npos);
  395. }
  396. }
  397. std::string relpath = m_RelativePathToBinaryDir;
  398. if(relpath.size())
  399. {
  400. relpath.erase(relpath.size()-1, 1);
  401. }
  402. else
  403. {
  404. relpath = ".";
  405. }
  406. if(
  407. #if defined(_WIN32) || defined(__APPLE__)
  408. cmSystemTools::LowerCase(ret) ==
  409. cmSystemTools::LowerCase(m_HomeOutputDirectoryNoSlash)
  410. #else
  411. ret == m_HomeOutputDirectoryNoSlash
  412. #endif
  413. )
  414. {
  415. ret = relpath;
  416. }
  417. // Relative paths should always start in a '.', so add a './' if
  418. // necessary.
  419. if(ret.size()
  420. && ret[0] != '\"' && ret[0] != '/' && ret[0] != '.' && ret[0] != '$')
  421. {
  422. if(ret.size() > 1 && ret[1] != ':')
  423. {
  424. ret = std::string("./") + ret;
  425. }
  426. }
  427. ret = cmSystemTools::ConvertToOutputPath(ret.c_str());
  428. return ret;
  429. }