cmUnixMakefileGenerator.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2000 National Library of Medicine
  8. All rights reserved.
  9. See COPYRIGHT.txt for copyright details.
  10. =========================================================================*/
  11. #include "cmUnixMakefileGenerator.h"
  12. #include "cmMakefile.h"
  13. #include "cmStandardIncludes.h"
  14. #include "cmSystemTools.h"
  15. #include "cmClassFile.h"
  16. #include "cmMakeDepend.h"
  17. void cmUnixMakefileGenerator::GenerateMakefile()
  18. {
  19. // Generate depends
  20. cmMakeDepend md;
  21. md.SetMakefile(m_Makefile);
  22. md.DoDepends();
  23. // output the makefile fragment
  24. this->OutputMakefile("CMakeTargets.make");
  25. }
  26. // This is where CMakeTargets.make is generated
  27. void cmUnixMakefileGenerator::OutputMakefile(const char* file)
  28. {
  29. // Create sub directories fro aux source directories
  30. std::vector<std::string>& auxSourceDirs =
  31. m_Makefile->GetAuxSourceDirectories();
  32. if( auxSourceDirs.size() )
  33. {
  34. // For the case when this is running as a remote build
  35. // on unix, make the directory
  36. for(std::vector<std::string>::iterator i = auxSourceDirs.begin();
  37. i != auxSourceDirs.end(); ++i)
  38. {
  39. cmSystemTools::MakeDirectory(i->c_str());
  40. }
  41. }
  42. std::ofstream fout(file);
  43. if(!fout)
  44. {
  45. cmSystemTools::Error("Error can not open for write: ", file);
  46. return;
  47. }
  48. this->OutputMakeFlags(fout);
  49. this->OutputSourceToObjectList(fout);
  50. this->OutputVerbatim(fout);
  51. this->OutputExecutableRules(fout);
  52. this->OutputSubDirectoryRules(fout);
  53. this->OutputObjectDepends(fout);
  54. this->OutputCustomRules(fout);
  55. }
  56. // Output the LIBRARY and SRC_OBJS list based on
  57. // the library name and cmClassFile objects in the
  58. // makefile
  59. void cmUnixMakefileGenerator::OutputSourceToObjectList(std::ostream& fout)
  60. {
  61. std::vector<cmClassFile>& Classes = m_Makefile->GetClasses();
  62. if(Classes.size() == 0)
  63. {
  64. return;
  65. }
  66. // Ouput Library name if there are SRC_OBJS
  67. if(strlen(m_Makefile->GetLibraryName()) > 0)
  68. {
  69. fout << "LIBRARY = " << m_Makefile->GetLibraryName() << "\n\n";
  70. fout << "BUILD_LIB_FILE = lib${LIBRARY}${CMAKE_LIB_EXT}\n\n";
  71. }
  72. // Output SRC_OBJ list for all the classes to be compiled
  73. fout << "SRC_OBJ = \\\n";
  74. for(unsigned int i = 0; i < Classes.size(); i++)
  75. {
  76. if(!Classes[i].m_AbstractClass && !Classes[i].m_HeaderFileOnly
  77. && !Classes[i].m_IsExecutable)
  78. {
  79. fout << Classes[i].m_ClassName << ".o ";
  80. if(i == Classes.size() -1)
  81. {
  82. fout << "\n\n";
  83. }
  84. else
  85. {
  86. fout << "\\\n";
  87. }
  88. }
  89. }
  90. fout << "\n";
  91. }
  92. // output the list of libraries that the executables
  93. // in this makefile will depend on.
  94. void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
  95. {
  96. std::vector<std::string>& libs = m_Makefile->GetLinkLibraries();
  97. std::vector<std::string>& libdirs = m_Makefile->GetLinkDirectories();
  98. std::vector<std::string>::iterator dir, lib;
  99. // Search the list of libraries that will be linked into
  100. // the executable
  101. for(lib = libs.begin(); lib != libs.end(); ++lib)
  102. {
  103. bool found = false;
  104. // loop over the list of directories that the libraries might
  105. // be in, looking for a LIBRARY=(lib) line.
  106. for(dir = libdirs.begin(); dir != libdirs.end() && !found; ++dir)
  107. {
  108. std::string expression = "LIBRARY.*=.*";
  109. expression += lib->c_str();
  110. if(cmSystemTools::Grep(dir->c_str(), "CMakeTargets.make",
  111. expression.c_str()))
  112. {
  113. std::string libpath = *dir;
  114. libpath += "/lib";
  115. libpath += *lib;
  116. libpath += "${CMAKE_LIB_EXT}";
  117. fout << libpath << " ";
  118. found = true;
  119. }
  120. }
  121. }
  122. std::vector<std::string>& utils = m_Makefile->GetUtilities();
  123. std::vector<std::string>& utildirs = m_Makefile->GetUtilityDirectories();
  124. std::vector<std::string>::iterator util;
  125. // Search the list of utilities that may be used to generate code for
  126. // this project.
  127. for(util = utils.begin(); util != utils.end(); ++util)
  128. {
  129. bool found = false;
  130. // loop over the list of directories that the utilities might
  131. // be in, looking for an EXECUTABLES=(util) line.
  132. for(dir = utildirs.begin(); dir != utildirs.end() && !found; ++dir)
  133. {
  134. std::string expression = "EXECUTABLES.*=.*";
  135. expression += util->c_str();
  136. if(cmSystemTools::Grep(dir->c_str(), "CMakeTargets.make",
  137. expression.c_str()))
  138. {
  139. fout << *util << " ";
  140. found = true;
  141. }
  142. }
  143. }
  144. fout << "\n";
  145. }
  146. // output make include flags
  147. void cmUnixMakefileGenerator::OutputMakeFlags(std::ostream& fout)
  148. {
  149. // Output Include paths
  150. fout << "INCLUDE_FLAGS = ";
  151. std::vector<std::string>& includes = m_Makefile->GetIncludeDirectories();
  152. std::vector<std::string>::iterator i;
  153. for(i = includes.begin(); i != includes.end(); ++i)
  154. {
  155. std::string include = *i;
  156. fout << "-I" << i->c_str() << " ";
  157. }
  158. fout << m_Makefile->GetDefineFlags();
  159. fout << " ${LOCAL_INCLUDE_FLAGS} ";
  160. fout << "\n";
  161. fout << "default_target: all\n\n";
  162. // see if there are files to compile in this makefile
  163. // These are used for both libraries and executables
  164. }
  165. // output verbatim section
  166. void cmUnixMakefileGenerator::OutputVerbatim(std::ostream& fout)
  167. {
  168. std::vector<std::string>& MakeVerbatim = m_Makefile->GetMakeVerbatim();
  169. // Ouput user make text embeded in the input file
  170. for(unsigned int i =0; i < MakeVerbatim.size(); i++)
  171. {
  172. fout << MakeVerbatim[i] << "\n";
  173. }
  174. fout << "\n\n";
  175. }
  176. // output executables
  177. void cmUnixMakefileGenerator::OutputExecutableRules(std::ostream& fout)
  178. {
  179. if(!m_Makefile->HasExecutables())
  180. {
  181. return ;
  182. }
  183. // collect all the flags needed for linking libraries
  184. std::string linkLibs;
  185. std::vector<std::string>::iterator j;
  186. std::vector<std::string>& libdirs = m_Makefile->GetLinkDirectories();
  187. for(j = libdirs.begin(); j != libdirs.end(); ++j)
  188. {
  189. std::string::size_type pos = (*j).find("-L");
  190. if((pos == std::string::npos || pos > 0)
  191. && (*j).find("${") == std::string::npos)
  192. {
  193. linkLibs += "-L";
  194. }
  195. linkLibs += *j;
  196. linkLibs += " ";
  197. }
  198. std::string librariesLinked;
  199. std::vector<std::string>& libs = m_Makefile->GetLinkLibraries();
  200. for(j = libs.begin(); j != libs.end(); ++j)
  201. {
  202. std::string::size_type pos = (*j).find("-l");
  203. if((pos == std::string::npos || pos > 0)
  204. && (*j).find("${") == std::string::npos)
  205. {
  206. librariesLinked += "-l";
  207. }
  208. librariesLinked += *j;
  209. librariesLinked += " ";
  210. }
  211. // Add these in twice so order does not matter
  212. linkLibs += librariesLinked;
  213. linkLibs += librariesLinked;
  214. std::vector<std::string>& libsUnix = m_Makefile->GetLinkLibrariesUnix();
  215. for(j = libsUnix.begin(); j != libsUnix.end(); ++j)
  216. {
  217. linkLibs += *j;
  218. linkLibs += " ";
  219. }
  220. linkLibs += " ${LOCAL_LINK_FLAGS} ";
  221. // create and output a varible in the makefile that
  222. // each executable will depend on. This will have all the
  223. // libraries that the executable uses
  224. fout << "CMAKE_DEPEND_LIBS = ";
  225. this->OutputDependencies(fout);
  226. // Now create rules for all of the executables to be built
  227. std::vector<cmClassFile>& Classes = m_Makefile->GetClasses();
  228. for(unsigned int i = 0; i < Classes.size(); i++)
  229. {
  230. if(!Classes[i].m_AbstractClass && !Classes[i].m_HeaderFileOnly
  231. && Classes[i].m_IsExecutable)
  232. {
  233. std::string DotO = Classes[i].m_ClassName;
  234. DotO += ".o";
  235. fout << Classes[i].m_ClassName << ": " << DotO << " ";
  236. fout << "${CMAKE_DEPEND_LIBS}\n";
  237. fout << "\t${CXX} ${CXX_FLAGS} "
  238. << DotO.c_str() << " "
  239. << linkLibs.c_str()
  240. << " -o $@ ""\n\n";
  241. }
  242. }
  243. // ouput the list of executables
  244. fout << "EXECUTABLES = \\\n";
  245. for(unsigned int i = 0; i < Classes.size(); i++)
  246. {
  247. if(!Classes[i].m_AbstractClass && !Classes[i].m_HeaderFileOnly
  248. && Classes[i].m_IsExecutable)
  249. {
  250. fout << Classes[i].m_ClassName;
  251. if(i < Classes.size()-1)
  252. {
  253. fout << " \\";
  254. }
  255. fout << "\n";
  256. }
  257. }
  258. fout << "\n";
  259. }
  260. // fix up names of directories so they can be used
  261. // as targets in makefiles.
  262. inline std::string FixDirectoryName(const char* dir)
  263. {
  264. std::string s = dir;
  265. // replace ../ with 3 under bars
  266. size_t pos = s.find("../");
  267. if(pos != std::string::npos)
  268. {
  269. s.replace(pos, 3, "___");
  270. }
  271. // replace / directory separators with a single under bar
  272. pos = s.find("/");
  273. while(pos != std::string::npos)
  274. {
  275. s.replace(pos, 1, "_");
  276. pos = s.find("/");
  277. }
  278. return s;
  279. }
  280. // output rules for decending into sub directories
  281. void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout)
  282. {
  283. // Output Sub directory build rules
  284. const std::vector<std::string>& SubDirectories
  285. = m_Makefile->GetSubDirectories();
  286. if( SubDirectories.size() == 0)
  287. {
  288. return;
  289. }
  290. fout << "SUBDIR_BUILD = \\\n";
  291. unsigned int i;
  292. for(i =0; i < SubDirectories.size(); i++)
  293. {
  294. std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
  295. fout << "build_" << subdir.c_str();
  296. if(i == SubDirectories.size()-1)
  297. {
  298. fout << " \n\n";
  299. }
  300. else
  301. {
  302. fout << " \\\n";
  303. }
  304. }
  305. fout << std::endl;
  306. fout << "SUBDIR_CLEAN = \\\n";
  307. for(i =0; i < SubDirectories.size(); i++)
  308. {
  309. std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
  310. fout << "clean_" << subdir.c_str();
  311. if(i == SubDirectories.size()-1)
  312. {
  313. fout << " \n\n";
  314. }
  315. else
  316. {
  317. fout << " \\\n";
  318. }
  319. }
  320. fout << std::endl;
  321. fout << "alldirs : ${SUBDIR_BUILD}\n\n";
  322. for(i =0; i < SubDirectories.size(); i++)
  323. {
  324. std::string subdir = FixDirectoryName(SubDirectories[i].c_str());
  325. fout << "build_" << subdir.c_str() << ":\n";
  326. fout << "\tcd " << SubDirectories[i].c_str()
  327. << "; ${MAKE} -${MAKEFLAGS} CMakeTargets.make\n";
  328. fout << "\tcd " << SubDirectories[i].c_str()
  329. << "; ${MAKE} -${MAKEFLAGS} all\n\n";
  330. fout << "clean_" << subdir.c_str() << ": \n";
  331. fout << "\tcd " << SubDirectories[i].c_str()
  332. << "; ${MAKE} -${MAKEFLAGS} clean\n\n";
  333. }
  334. }
  335. // Output the depend information for all the classes
  336. // in the makefile. These would have been generated
  337. // by the class cmMakeDepend GenerateMakefile
  338. void cmUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout)
  339. {
  340. std::vector<cmClassFile>& Classes = m_Makefile->GetClasses();
  341. for(unsigned int i = 0; i < Classes.size(); i++)
  342. {
  343. if(!Classes[i].m_AbstractClass && !Classes[i].m_HeaderFileOnly)
  344. {
  345. if( Classes[i].m_Depends.size())
  346. {
  347. fout << Classes[i].m_ClassName << ".o : \\\n";
  348. for(std::vector<std::string>::iterator j =
  349. Classes[i].m_Depends.begin();
  350. j != Classes[i].m_Depends.end(); ++j)
  351. {
  352. if(j+1 == Classes[i].m_Depends.end())
  353. {
  354. fout << *j << " \n";
  355. }
  356. else
  357. {
  358. fout << *j << " \\\n";
  359. }
  360. }
  361. fout << "\n\n";
  362. }
  363. }
  364. }
  365. }
  366. // Output each custom rule in the following format:
  367. // m_Result: m_Source m_Depends[0] m_Depends[1] ...
  368. // (tab) m_Command
  369. void cmUnixMakefileGenerator::OutputCustomRules(std::ostream& fout)
  370. {
  371. for(std::vector<cmMakefile::customCommand>::const_iterator c =
  372. m_Makefile->GetCustomCommands().begin();
  373. c != m_Makefile->GetCustomCommands().end(); ++c)
  374. {
  375. fout << c->m_Result.c_str() << ": " << c->m_Source.c_str();
  376. for(std::vector<std::string>::const_iterator d = c->m_Depends.begin();
  377. d != c->m_Depends.end(); ++ d)
  378. {
  379. fout << " " << d->c_str();
  380. }
  381. fout << "\n\t" << c->m_Command.c_str() << "\n\n";
  382. }
  383. }