cmMakefile.cxx 9.6 KB

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