cmMakefile.cxx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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 "cmMakefile.h"
  12. #include "cmRuleMaker.h"
  13. #include "cmStandardIncludes.h"
  14. #include "cmClassFile.h"
  15. #include "cmDirectory.h"
  16. #include "cmSystemTools.h"
  17. #include "cmMakefileGenerator.h"
  18. #include "cmAbstractFilesRule.h"
  19. #include "cmAddTargetRule.h"
  20. #include "cmAuxSourceDirectoryRule.h"
  21. #include "cmExecutablesRule.h"
  22. #include "cmFindIncludeRule.h"
  23. #include "cmFindLibraryRule.h"
  24. #include "cmFindProgramRule.h"
  25. #include "cmIncludeDirectoryRule.h"
  26. #include "cmLibraryRule.h"
  27. #include "cmLinkDirectoriesRule.h"
  28. #include "cmLinkLibrariesRule.h"
  29. #include "cmProjectRule.h"
  30. #include "cmSourceFilesRule.h"
  31. #include "cmSourceFilesRequireRule.h"
  32. #include "cmSubdirRule.h"
  33. #include "cmUnixDefinesRule.h"
  34. #include "cmUnixLibrariesRule.h"
  35. #include "cmWin32DefinesRule.h"
  36. #include "cmWin32LibrariesRule.h"
  37. #include "cmTestsRule.h"
  38. // default is not to be building executables
  39. cmMakefile::cmMakefile()
  40. {
  41. m_DefineFlags = " ";
  42. m_Executables = false;
  43. m_MakefileGenerator = 0;
  44. this->AddDefaultRules();
  45. }
  46. void cmMakefile::AddDefaultRules()
  47. {
  48. this->AddRuleMaker(new cmAbstractFilesRule);
  49. this->AddRuleMaker(new cmAddTargetRule);
  50. this->AddRuleMaker(new cmAuxSourceDirectoryRule);
  51. this->AddRuleMaker(new cmExecutablesRule);
  52. this->AddRuleMaker(new cmFindIncludeRule);
  53. this->AddRuleMaker(new cmFindLibraryRule);
  54. this->AddRuleMaker(new cmFindProgramRule);
  55. this->AddRuleMaker(new cmIncludeDirectoryRule);
  56. this->AddRuleMaker(new cmLibraryRule);
  57. this->AddRuleMaker(new cmLinkDirectoriesRule);
  58. this->AddRuleMaker(new cmLinkLibrariesRule);
  59. this->AddRuleMaker(new cmProjectRule);
  60. this->AddRuleMaker(new cmSourceFilesRule);
  61. this->AddRuleMaker(new cmSourceFilesRequireRule);
  62. this->AddRuleMaker(new cmSubdirRule);
  63. this->AddRuleMaker(new cmUnixLibrariesRule);
  64. this->AddRuleMaker(new cmUnixDefinesRule);
  65. this->AddRuleMaker(new cmWin32LibrariesRule);
  66. this->AddRuleMaker(new cmWin32DefinesRule);
  67. this->AddRuleMaker(new cmTestsRule);
  68. #ifdef _WIN32
  69. this->AddDefinition("WIN32", "1");
  70. #else
  71. this->AddDefinition("UNIX", "1");
  72. #endif
  73. // Cygwin is more like unix so enable the unix rules
  74. #if defined(__CYGWIN__)
  75. this->AddDefinition("UNIX", "1");
  76. #endif
  77. }
  78. cmMakefile::~cmMakefile()
  79. {
  80. for(int i=0; i < m_UsedRuleMakers.size(); i++)
  81. {
  82. delete m_UsedRuleMakers[i];
  83. }
  84. for(StringRuleMakerMap::iterator j = m_RuleMakers.begin();
  85. j != m_RuleMakers.end(); ++j)
  86. {
  87. delete (*j).second;
  88. }
  89. delete m_MakefileGenerator;
  90. }
  91. void cmMakefile::PrintStringVector(const char* s, std::vector<std::string>& v)
  92. {
  93. std::cout << s << ": ( \n";
  94. for(std::vector<std::string>::iterator i = v.begin();
  95. i != v.end(); ++i)
  96. {
  97. std::cout << (*i).c_str() << " ";
  98. }
  99. std::cout << " )\n";
  100. }
  101. // call print on all the classes in the makefile
  102. void cmMakefile::Print()
  103. {
  104. std::cout << "classes:\n";
  105. for(unsigned int i = 0; i < m_Classes.size(); i++)
  106. m_Classes[i].Print();
  107. std::cout << " m_OutputDirectory; " <<
  108. m_OutputDirectory.c_str() << std::endl;
  109. std::cout << " m_OutputHomeDirectory; " <<
  110. m_OutputHomeDirectory.c_str() << std::endl;
  111. std::cout << " m_cmHomeDirectory; " <<
  112. m_cmHomeDirectory.c_str() << std::endl;
  113. std::cout << " m_cmCurrentDirectory; " <<
  114. m_cmCurrentDirectory.c_str() << std::endl;
  115. std::cout << " m_LibraryName; " << m_LibraryName.c_str() << std::endl;
  116. std::cout << " m_ProjectName; " << m_ProjectName.c_str() << std::endl;
  117. this->PrintStringVector("m_SubDirectories ", m_SubDirectories);
  118. this->PrintStringVector("m_MakeVerbatim ", m_MakeVerbatim);
  119. this->PrintStringVector("m_IncludeDirectories;", m_IncludeDirectories);
  120. this->PrintStringVector("m_LinkDirectories", m_LinkDirectories);
  121. this->PrintStringVector("m_LinkLibraries", m_LinkLibraries);
  122. this->PrintStringVector("m_LinkLibrariesWin32", m_LinkLibrariesWin32);
  123. this->PrintStringVector("m_LinkLibrariesUnix", m_LinkLibrariesUnix);
  124. }
  125. // Parse the given CMakeLists.txt file into a list of classes.
  126. bool cmMakefile::ReadMakefile(const char* filename, bool inheriting)
  127. {
  128. // If not being called from ParseDirectory which
  129. // sets the inheriting flag, then parse up the
  130. // tree and collect inherited parameters
  131. if(!inheriting)
  132. {
  133. cmSystemTools::ConvertToUnixSlashes(m_cmCurrentDirectory);
  134. m_SourceHomeDirectory = m_cmHomeDirectory;
  135. cmSystemTools::ConvertToUnixSlashes(m_SourceHomeDirectory);
  136. this->ParseDirectory(m_cmCurrentDirectory.c_str());
  137. }
  138. // Now read the input file
  139. std::ifstream fin(filename);
  140. if(!fin)
  141. {
  142. cmSystemTools::Error("error can not open file ", filename);
  143. return false;
  144. }
  145. std::string name;
  146. std::vector<std::string> arguments;
  147. while ( fin )
  148. {
  149. if(cmSystemTools::ParseFunction(fin, name, arguments) )
  150. {
  151. // Special rule that needs to be removed when
  152. // ADD_RULE is implemented
  153. if(name == "VERBATIM")
  154. {
  155. if(!inheriting)
  156. {
  157. m_MakeVerbatim = arguments;
  158. }
  159. }
  160. else
  161. {
  162. StringRuleMakerMap::iterator pos = m_RuleMakers.find(name);
  163. if(pos != m_RuleMakers.end())
  164. {
  165. cmRuleMaker* rm = (*pos).second;
  166. cmRuleMaker* usedMaker = rm->Clone();
  167. usedMaker->SetMakefile(this);
  168. usedMaker->LoadCache();
  169. m_UsedRuleMakers.push_back(usedMaker);
  170. if(usedMaker->GetEnabled())
  171. {
  172. // if not running in inherit mode or
  173. // if the rule is inherited then Invoke it.
  174. if(!inheriting || usedMaker->IsInherited())
  175. {
  176. if(!usedMaker->Invoke(arguments))
  177. {
  178. cmSystemTools::Error(usedMaker->GetError());
  179. }
  180. }
  181. }
  182. }
  183. else
  184. {
  185. cmSystemTools::Error("unknown CMake function", name.c_str());
  186. }
  187. }
  188. }
  189. }
  190. return true;
  191. }
  192. void cmMakefile::AddRuleMaker(cmRuleMaker* wg)
  193. {
  194. std::string name = wg->GetName();
  195. m_RuleMakers.insert( StringRuleMakerMap::value_type(name, wg));
  196. }
  197. // Set the make file
  198. void cmMakefile::SetMakefileGenerator(cmMakefileGenerator* mf)
  199. {
  200. delete m_MakefileGenerator;
  201. m_MakefileGenerator = mf;
  202. }
  203. // Generate the output file
  204. void cmMakefile::GenerateMakefile()
  205. {
  206. // do all the variable expansions here
  207. this->ExpandVaribles();
  208. // set the makefile on the generator
  209. m_MakefileGenerator->SetMakefile(this);
  210. // give all the rules a chance to do something
  211. // after the file has been parsed before generation
  212. for(std::vector<cmRuleMaker*>::iterator i = m_UsedRuleMakers.begin();
  213. i != m_UsedRuleMakers.end(); ++i)
  214. {
  215. (*i)->FinalPass();
  216. }
  217. // now do the generation
  218. m_MakefileGenerator->GenerateMakefile();
  219. }
  220. void cmMakefile::AddClass(cmClassFile& cmfile)
  221. {
  222. m_Classes.push_back(cmfile);
  223. }
  224. void cmMakefile::AddCustomRule(const char* source,
  225. const char* result,
  226. const char* command,
  227. std::vector<std::string>& depends)
  228. {
  229. cmMakefile::customRule rule;
  230. rule.m_Source = source;
  231. rule.m_Result = result;
  232. rule.m_Command = command;
  233. rule.m_Depends = depends;
  234. m_CustomRules.push_back(rule);
  235. }
  236. void cmMakefile::AddDefineFlag(const char* flag)
  237. {
  238. m_DefineFlags += " ";
  239. m_DefineFlags += flag;
  240. }
  241. void cmMakefile::AddExecutable(cmClassFile& cf)
  242. {
  243. m_Classes.push_back(cf);
  244. m_Executables = true;
  245. }
  246. void cmMakefile::AddLinkLibrary(const char* lib)
  247. {
  248. m_LinkLibraries.push_back(lib);
  249. }
  250. void cmMakefile::AddLinkDirectory(const char* dir)
  251. {
  252. m_LinkDirectories.push_back(dir);
  253. }
  254. void cmMakefile::AddSubDirectory(const char* sub)
  255. {
  256. m_SubDirectories.push_back(sub);
  257. }
  258. void cmMakefile::AddIncludeDirectory(const char* inc)
  259. {
  260. m_IncludeDirectories.push_back(inc);
  261. }
  262. void cmMakefile::AddDefinition(const char* name, const char* value)
  263. {
  264. m_Definitions.insert(DefinitionMap::value_type(name, value));
  265. }
  266. void cmMakefile::SetProjectName(const char* p)
  267. {
  268. m_ProjectName = p;
  269. }
  270. void cmMakefile::SetLibraryName(const char* l)
  271. {
  272. m_LibraryName = l;
  273. }
  274. void cmMakefile::AddExtraDirectory(const char* dir)
  275. {
  276. m_AuxSourceDirectories.push_back(dir);
  277. }
  278. // Go until directory == m_cmHomeDirectory
  279. // 1. fix slashes
  280. // 2. peal off /dir until home found, go no higher
  281. void cmMakefile::ParseDirectory(const char* dir)
  282. {
  283. std::string listsFile = dir;
  284. listsFile += "/CMakeLists.txt";
  285. if(cmSystemTools::FileExists(listsFile.c_str()))
  286. {
  287. this->ReadMakefile(listsFile.c_str(), true);
  288. }
  289. if(m_SourceHomeDirectory == dir)
  290. {
  291. return;
  292. }
  293. std::string dotdotDir = dir;
  294. std::string::size_type pos = dotdotDir.rfind('/');
  295. if(pos != std::string::npos)
  296. {
  297. dotdotDir = dotdotDir.substr(0, pos);
  298. this->ParseDirectory(dotdotDir.c_str());
  299. }
  300. }
  301. // expance CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
  302. // include and library directories.
  303. void cmMakefile::ExpandVaribles()
  304. {
  305. // Now replace varibles
  306. std::vector<std::string>::iterator j, begin, end;
  307. begin = m_IncludeDirectories.begin();
  308. end = m_IncludeDirectories.end();
  309. for(j = begin; j != end; ++j)
  310. {
  311. cmSystemTools::ReplaceString(*j, "${CMAKE_BINARY_DIR}",
  312. this->GetOutputHomeDirectory() );
  313. cmSystemTools::ReplaceString(*j, "${CMAKE_SOURCE_DIR}",
  314. this->GetHomeDirectory() );
  315. }
  316. begin = m_LinkDirectories.begin();
  317. end = m_LinkDirectories.end();
  318. for(j = begin; j != end; ++j)
  319. {
  320. cmSystemTools::ReplaceString(*j, "${CMAKE_BINARY_DIR}",
  321. this->GetOutputHomeDirectory() );
  322. cmSystemTools::ReplaceString(*j, "${CMAKE_SOURCE_DIR}",
  323. this->GetHomeDirectory() );
  324. }
  325. }
  326. const char* cmMakefile::GetDefinition(const char* name)
  327. {
  328. DefinitionMap::iterator pos = m_Definitions.find(name);
  329. if(pos != m_Definitions.end())
  330. {
  331. return (*pos).second.c_str();
  332. }
  333. return 0;
  334. }