cmLocalUnixMakefileGenerator2.cxx 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413
  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 "cmLocalUnixMakefileGenerator2.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmGlobalGenerator.h"
  16. #include "cmMakefile.h"
  17. #include "cmSourceFile.h"
  18. #include <queue>
  19. //----------------------------------------------------------------------------
  20. cmLocalUnixMakefileGenerator2::cmLocalUnixMakefileGenerator2()
  21. {
  22. }
  23. //----------------------------------------------------------------------------
  24. cmLocalUnixMakefileGenerator2::~cmLocalUnixMakefileGenerator2()
  25. {
  26. }
  27. //----------------------------------------------------------------------------
  28. void cmLocalUnixMakefileGenerator2::SetEmptyCommand(const char* cmd)
  29. {
  30. m_EmptyCommands.clear();
  31. if(cmd)
  32. {
  33. m_EmptyCommands.push_back(cmd);
  34. }
  35. }
  36. //----------------------------------------------------------------------------
  37. void cmLocalUnixMakefileGenerator2::Generate(bool fromTheTop)
  38. {
  39. // TODO: Account for control-c during Makefile generation.
  40. // TODO: Think about unifying generation of "@" for silent commands.
  41. // Generate old style for now.
  42. this->cmLocalUnixMakefileGenerator::Generate(fromTheTop);
  43. // Generate the rule files for each target.
  44. const cmTargets& targets = m_Makefile->GetTargets();
  45. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  46. {
  47. // TODO: Dispatch generation of each target type.
  48. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  49. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  50. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  51. (t->second.GetType() == cmTarget::MODULE_LIBRARY))
  52. {
  53. this->GenerateTargetRuleFile(t->second);
  54. }
  55. }
  56. // Generate the rule files for each custom command.
  57. const std::vector<cmSourceFile*>& sources = m_Makefile->GetSourceFiles();
  58. for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
  59. i != sources.end(); ++i)
  60. {
  61. if((*i)->GetCustomCommand())
  62. {
  63. this->GenerateCustomRuleFile(*(*i));
  64. }
  65. }
  66. // Generate the main makefile.
  67. this->GenerateMakefile();
  68. // Generate the cmake file that keeps the makefile up to date.
  69. this->GenerateCMakefile();
  70. }
  71. //----------------------------------------------------------------------------
  72. void cmLocalUnixMakefileGenerator2::GenerateMakefile()
  73. {
  74. // Open the output file.
  75. std::string makefileName = m_Makefile->GetStartOutputDirectory();
  76. makefileName += "/Makefile2";
  77. std::ofstream makefileStream(makefileName.c_str());
  78. if(!makefileStream)
  79. {
  80. cmSystemTools::Error("Error can not open for write: ",
  81. makefileName.c_str());
  82. cmSystemTools::ReportLastSystemError("");
  83. return;
  84. }
  85. // Write the do not edit header.
  86. this->WriteDisclaimer(makefileStream);
  87. // Write standard variables to the makefile.
  88. this->WriteMakeVariables(makefileStream);
  89. // Write special targets that belong at the top of the file.
  90. this->WriteSpecialTargetsTop(makefileStream);
  91. // Write the directory-level build rules.
  92. this->WriteAllRule(makefileStream);
  93. // Write the subdirectory driver rules.
  94. this->WriteSubdirRules(makefileStream, "all");
  95. // Write include statements to get rules for this directory.
  96. this->WriteRuleFileIncludes(makefileStream);
  97. // Write jump-and-build rules that were recorded in the map.
  98. this->WriteJumpAndBuildRules(makefileStream);
  99. // Write special targets that belong at the bottom of the file.
  100. this->WriteSpecialTargetsBottom(makefileStream);
  101. }
  102. //----------------------------------------------------------------------------
  103. void cmLocalUnixMakefileGenerator2::GenerateCMakefile()
  104. {
  105. std::string makefileName = m_Makefile->GetStartOutputDirectory();
  106. makefileName += "/Makefile2";
  107. std::string cmakefileName = makefileName;
  108. cmakefileName += ".cmake";
  109. // Open the output file.
  110. std::ofstream cmakefileStream(cmakefileName.c_str());
  111. if(!cmakefileStream)
  112. {
  113. cmSystemTools::Error("Error can not open for write: ",
  114. cmakefileName.c_str());
  115. cmSystemTools::ReportLastSystemError("");
  116. return;
  117. }
  118. // Write the do not edit header.
  119. this->WriteDisclaimer(cmakefileStream);
  120. // Get the list of files contributing to this generation step.
  121. // Sort the list and remove duplicates.
  122. std::vector<std::string> lfiles = m_Makefile->GetListFiles();
  123. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  124. std::vector<std::string>::iterator new_end = std::unique(lfiles.begin(),
  125. lfiles.end());
  126. lfiles.erase(new_end, lfiles.end());
  127. // Save the list to the cmake file.
  128. cmakefileStream
  129. << "# The corresponding makefile\n"
  130. << "# \"" << makefileName << "\"\n"
  131. << "# was generated from the following files:\n"
  132. << "SET(CMAKE_MAKEFILE_DEPENDS\n"
  133. << " \"" << m_Makefile->GetHomeOutputDirectory() << "/CMakeCache.txt\"\n";
  134. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  135. i != lfiles.end(); ++i)
  136. {
  137. cmakefileStream
  138. << " \"" << i->c_str() << "\"\n";
  139. }
  140. cmakefileStream
  141. << " )\n\n";
  142. // Set the corresponding makefile in the cmake file.
  143. cmakefileStream
  144. << "# The corresponding makefile is:\n"
  145. << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
  146. << " \"" << makefileName.c_str() << "\"\n"
  147. << " )\n\n";
  148. // Set the set of files to check for dependency integrity.
  149. cmakefileStream
  150. << "# The set of files whose dependency integrity should be checked:\n"
  151. << "SET(CMAKE_DEPENDS_CHECK\n";
  152. for(std::set<cmStdString>::const_iterator i = m_CheckDependFiles.begin();
  153. i != m_CheckDependFiles.end(); ++i)
  154. {
  155. cmakefileStream
  156. << " \"" << i->c_str() << "\"\n";
  157. }
  158. cmakefileStream
  159. << " )\n";
  160. }
  161. //----------------------------------------------------------------------------
  162. void
  163. cmLocalUnixMakefileGenerator2
  164. ::GenerateTargetRuleFile(const cmTarget& target)
  165. {
  166. // Create a directory for this target.
  167. std::string dir = this->GetTargetDirectory(target);
  168. cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
  169. // First generate the object rule files. Save a list of all object
  170. // files for this target.
  171. std::vector<std::string> objects;
  172. const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
  173. for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
  174. source != sources.end(); ++source)
  175. {
  176. if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
  177. !(*source)->GetCustomCommand() &&
  178. !m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
  179. {
  180. // Generate this object file's rule file.
  181. this->GenerateObjectRuleFile(target, *(*source));
  182. // Save the object file name.
  183. objects.push_back(this->GetObjectFileName(target, *(*source)));
  184. }
  185. }
  186. // Generate the build-time dependencies file for this target.
  187. std::string depBase = dir;
  188. depBase += "/";
  189. depBase += target.GetName();
  190. std::string depMakeFile = this->GenerateDependsMakeFile(depBase.c_str());
  191. // Construct the rule file name.
  192. std::string ruleFileName = dir;
  193. ruleFileName += "/";
  194. ruleFileName += target.GetName();
  195. ruleFileName += ".make";
  196. // The rule file must be included by the makefile.
  197. m_IncludeRuleFiles.push_back(ruleFileName);
  198. // Open the rule file. This should be copy-if-different because the
  199. // rules may depend on this file itself.
  200. std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
  201. cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str(), true);
  202. if(!ruleFileStream)
  203. {
  204. return;
  205. }
  206. this->WriteDisclaimer(ruleFileStream);
  207. ruleFileStream
  208. << "# Rule file for target " << target.GetName() << ".\n\n";
  209. // Include the dependencies for the target.
  210. ruleFileStream
  211. << "# Include any dependencies generated for this rule.\n"
  212. << m_IncludeDirective << " "
  213. << this->ConvertToOutputForExisting(depMakeFile.c_str()).c_str()
  214. << "\n\n";
  215. // Include the rule file for each object.
  216. if(!objects.empty())
  217. {
  218. ruleFileStream
  219. << "# Include make rules for object files.\n";
  220. for(std::vector<std::string>::const_iterator obj = objects.begin();
  221. obj != objects.end(); ++obj)
  222. {
  223. std::string objRuleFileName = *obj;
  224. objRuleFileName += ".make";
  225. ruleFileStream
  226. << m_IncludeDirective << " "
  227. << this->ConvertToOutputForExisting(objRuleFileName.c_str()).c_str()
  228. << "\n";
  229. }
  230. ruleFileStream
  231. << "\n";
  232. }
  233. // Write the dependency generation rule.
  234. {
  235. std::vector<std::string> depends;
  236. std::vector<std::string> no_commands;
  237. std::string depEcho = "Building dependencies for ";
  238. depEcho += target.GetName();
  239. depEcho += "...";
  240. std::string depTarget = dir;
  241. depTarget += "/";
  242. depTarget += target.GetName();
  243. depTarget += ".depends";
  244. for(std::vector<std::string>::const_iterator obj = objects.begin();
  245. obj != objects.end(); ++obj)
  246. {
  247. depends.push_back((*obj)+".depends");
  248. }
  249. depends.push_back(ruleFileName);
  250. this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
  251. depTarget.c_str(), depends, no_commands);
  252. }
  253. // Write the build rule.
  254. switch(target.GetType())
  255. {
  256. case cmTarget::STATIC_LIBRARY:
  257. this->WriteStaticLibraryRule(ruleFileStream, ruleFileName.c_str(),
  258. target, objects);
  259. break;
  260. case cmTarget::SHARED_LIBRARY:
  261. this->WriteSharedLibraryRule(ruleFileStream, ruleFileName.c_str(),
  262. target, objects);
  263. break;
  264. case cmTarget::MODULE_LIBRARY:
  265. this->WriteModuleLibraryRule(ruleFileStream, ruleFileName.c_str(),
  266. target, objects);
  267. break;
  268. case cmTarget::EXECUTABLE:
  269. this->WriteExecutableRule(ruleFileStream, ruleFileName.c_str(),
  270. target, objects);
  271. break;
  272. default:
  273. break;
  274. }
  275. }
  276. //----------------------------------------------------------------------------
  277. void
  278. cmLocalUnixMakefileGenerator2
  279. ::GenerateObjectRuleFile(const cmTarget& target, const cmSourceFile& source)
  280. {
  281. // Identify the language of the source file.
  282. const char* lang = this->GetSourceFileLanguage(source);
  283. if(!lang)
  284. {
  285. // If language is not known, this is an error.
  286. cmSystemTools::Error("Source file \"", source.GetFullPath().c_str(),
  287. "\" has unknown type.");
  288. return;
  289. }
  290. // Get the full path name of the object file.
  291. std::string obj = this->GetObjectFileName(target, source);
  292. // The object file should be checked for dependency integrity.
  293. m_CheckDependFiles.insert(obj);
  294. // Create the directory containing the object file. This may be a
  295. // subdirectory under the target's directory.
  296. std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
  297. cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
  298. // Generate the build-time dependencies file for this object file.
  299. std::string depMakeFile = this->GenerateDependsMakeFile(obj.c_str());
  300. // Open the rule file for writing. This should be copy-if-different
  301. // because the rules may depend on this file itself.
  302. std::string ruleFileName = obj;
  303. ruleFileName += ".make";
  304. std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
  305. cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str(), true);
  306. if(!ruleFileStream)
  307. {
  308. return;
  309. }
  310. this->WriteDisclaimer(ruleFileStream);
  311. ruleFileStream
  312. << "# Rule file for object file " << obj.c_str() << ".\n\n";
  313. // Include the dependencies for the target.
  314. ruleFileStream
  315. << "# Include any dependencies generated for this rule.\n"
  316. << m_IncludeDirective << " "
  317. << this->ConvertToOutputForExisting(depMakeFile.c_str()).c_str()
  318. << "\n\n";
  319. // Create the list of dependencies known at cmake time. These are
  320. // shared between the object file and dependency scanning rule.
  321. std::vector<std::string> depends;
  322. depends.push_back(source.GetFullPath());
  323. if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
  324. {
  325. std::vector<std::string> deps;
  326. cmSystemTools::ExpandListArgument(objectDeps, deps);
  327. for(std::vector<std::string>::iterator i = deps.begin();
  328. i != deps.end(); ++i)
  329. {
  330. depends.push_back(this->ConvertToRelativeOutputPath(i->c_str()));
  331. }
  332. }
  333. depends.push_back(ruleFileName);
  334. // Write the dependency generation rule.
  335. std::string depTarget = obj;
  336. depTarget += ".depends";
  337. {
  338. std::string depEcho = "Scanning ";
  339. depEcho += lang;
  340. depEcho += " dependencies of ";
  341. depEcho += this->ConvertToRelativeOutputPath(obj.c_str());
  342. depEcho += "...";
  343. // Add a command to call CMake to scan dependencies. CMake will
  344. // touch the corresponding depends file after scanning dependencies.
  345. cmOStringStream depCmd;
  346. // TODO: Account for source file properties and directory-level
  347. // definitions when scanning for dependencies.
  348. depCmd << "@$(CMAKE_COMMAND) -E cmake_depends " << lang << " "
  349. << this->ConvertToRelativeOutputPath(obj.c_str()) << " "
  350. << this->ConvertToRelativeOutputPath(source.GetFullPath().c_str());
  351. std::vector<std::string> includeDirs;
  352. this->GetIncludeDirectories(includeDirs);
  353. for(std::vector<std::string>::iterator i = includeDirs.begin();
  354. i != includeDirs.end(); ++i)
  355. {
  356. depCmd << " -I" << this->ConvertToRelativeOutputPath(i->c_str());
  357. }
  358. std::vector<std::string> commands;
  359. commands.push_back(depCmd.str());
  360. // Write the rule.
  361. this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
  362. depTarget.c_str(), depends, commands);
  363. }
  364. // Write the build rule.
  365. {
  366. // Build the set of compiler flags.
  367. std::string flags;
  368. // Add the export symbol definition for shared library objects.
  369. bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
  370. (target.GetType() == cmTarget::MODULE_LIBRARY));
  371. if(shared)
  372. {
  373. flags += "-D";
  374. if(const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
  375. {
  376. flags += custom_export_name;
  377. }
  378. else
  379. {
  380. std::string in = target.GetName();
  381. in += "_EXPORTS";
  382. flags += cmSystemTools::MakeCindentifier(in.c_str());
  383. }
  384. }
  385. // Add flags from source file properties.
  386. this->AppendFlags(flags, source.GetProperty("COMPILE_FLAGS"));
  387. // Add language-specific flags.
  388. this->AddLanguageFlags(flags, lang);
  389. // Add shared-library flags if needed.
  390. this->AddSharedFlags(flags, lang, shared);
  391. // Add include directory flags.
  392. this->AppendFlags(flags, this->GetIncludeFlags(lang));
  393. // Get the output paths for source and object files.
  394. std::string sourceFile =
  395. this->ConvertToRelativeOutputPath(source.GetFullPath().c_str());
  396. std::string objectFile =
  397. this->ConvertToRelativeOutputPath(obj.c_str());
  398. // Construct the compile rules.
  399. std::vector<std::string> commands;
  400. std::string compileRuleVar = "CMAKE_";
  401. compileRuleVar += lang;
  402. compileRuleVar += "_COMPILE_OBJECT";
  403. std::string compileRule =
  404. m_Makefile->GetRequiredDefinition(compileRuleVar.c_str());
  405. cmSystemTools::ExpandListArgument(compileRule, commands);
  406. // Expand placeholders in the commands.
  407. for(std::vector<std::string>::iterator i = commands.begin();
  408. i != commands.end(); ++i)
  409. {
  410. this->ExpandRuleVariables(*i,
  411. lang,
  412. 0, // no objects
  413. 0, // no target
  414. 0, // no link libs
  415. sourceFile.c_str(),
  416. objectFile.c_str(),
  417. flags.c_str());
  418. }
  419. // Write the rule.
  420. std::string buildEcho = "Building ";
  421. buildEcho += lang;
  422. buildEcho += " object ";
  423. buildEcho += this->ConvertToRelativeOutputPath(obj.c_str());
  424. buildEcho += "...";
  425. this->WriteMakeRule(ruleFileStream, 0, buildEcho.c_str(),
  426. obj.c_str(), depends, commands);
  427. }
  428. }
  429. //----------------------------------------------------------------------------
  430. void
  431. cmLocalUnixMakefileGenerator2
  432. ::GenerateCustomRuleFile(const cmSourceFile& source)
  433. {
  434. // Get the custom command for the source.
  435. if(!source.GetCustomCommand())
  436. {
  437. cmSystemTools::Error("GenerateCustomRuleFile called for non-custom source.");
  438. return;
  439. }
  440. const cmCustomCommand& cc = *source.GetCustomCommand();
  441. // Construct the name of the rule file.
  442. std::string customName = this->GetCustomBaseName(cc);
  443. std::string ruleFileName = customName;
  444. ruleFileName += ".make";
  445. // If this is a duplicate rule produce an error.
  446. if(m_CustomRuleFiles.find(ruleFileName) != m_CustomRuleFiles.end())
  447. {
  448. cmSystemTools::Error("An output was found with multiple rules on how to build it for output: ",
  449. cc.GetOutput().c_str());
  450. return;
  451. }
  452. m_CustomRuleFiles.insert(ruleFileName);
  453. // This rule should be included by the makefile.
  454. m_IncludeRuleFiles.push_back(ruleFileName);
  455. // TODO: Convert outputs/dependencies (arguments?) to relative paths.
  456. // Open the rule file. This should be copy-if-different because the
  457. // rules may depend on this file itself.
  458. std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
  459. cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str(), true);
  460. if(!ruleFileStream)
  461. {
  462. return;
  463. }
  464. this->WriteDisclaimer(ruleFileStream);
  465. ruleFileStream
  466. << "# Custom command rule file for " << customName.c_str() << ".\n\n";
  467. // Build the command line in a single string.
  468. std::vector<std::string> commands;
  469. std::string cmd = cc.GetCommand();
  470. cmSystemTools::ReplaceString(cmd, "/./", "/");
  471. cmd = this->ConvertToRelativeOutputPath(cmd.c_str());
  472. if(cc.GetArguments().size() > 0)
  473. {
  474. cmd += " ";
  475. cmd += cc.GetArguments();
  476. }
  477. commands.push_back(cmd);
  478. // Collect the dependencies.
  479. std::vector<std::string> depends;
  480. for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
  481. d != cc.GetDepends().end(); ++d)
  482. {
  483. // Get the dependency with variables expanded.
  484. std::string dep = *d;
  485. m_Makefile->ExpandVariablesInString(dep);
  486. // If the rule depends on a target CMake knows how to build,
  487. // convert it to the path where it will be built.
  488. std::string libPath = dep + "_CMAKE_PATH";
  489. const char* cacheValue = m_Makefile->GetDefinition(libPath.c_str());
  490. if(cacheValue && *cacheValue)
  491. {
  492. libPath = cacheValue;
  493. if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH") &&
  494. m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")[0] != '\0')
  495. {
  496. libPath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  497. }
  498. libPath += "/";
  499. libPath += dep;
  500. libPath += cmSystemTools::GetExecutableExtension();
  501. dep = libPath;
  502. }
  503. // Cleanup the dependency and add it.
  504. cmSystemTools::ReplaceString(dep, "/./", "/");
  505. cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/");
  506. dep = this->ConvertToRelativeOutputPath(dep.c_str());
  507. depends.push_back(dep.c_str());
  508. }
  509. // Add a dependency on the rule file itself.
  510. depends.push_back(ruleFileName);
  511. // Write the rule.
  512. const char* comment = 0;
  513. if(cc.GetComment().size())
  514. {
  515. comment = cc.GetComment().c_str();
  516. }
  517. std::string preEcho = "Generating ";
  518. preEcho += customName;
  519. preEcho += "...";
  520. this->WriteMakeRule(ruleFileStream, comment, preEcho.c_str(),
  521. cc.GetOutput().c_str(), depends, commands);
  522. }
  523. //----------------------------------------------------------------------------
  524. std::string
  525. cmLocalUnixMakefileGenerator2
  526. ::GenerateDependsMakeFile(const char* file)
  527. {
  528. // Check if the build-time dependencies file exists.
  529. std::string depMarkFile = file;
  530. depMarkFile += ".depends";
  531. std::string depMakeFile = depMarkFile;
  532. depMakeFile += ".make";
  533. std::string depMakeFileFull = this->ConvertToFullPath(depMakeFile);
  534. if(cmSystemTools::FileExists(depMakeFileFull.c_str()))
  535. {
  536. // The build-time dependencies file already exists. Check it.
  537. this->CheckDependencies(m_Makefile->GetStartOutputDirectory(), file);
  538. }
  539. else
  540. {
  541. // The build-time dependencies file does not exist. Create an
  542. // empty one.
  543. std::string depMarkFileFull = this->ConvertToFullPath(depMarkFile);
  544. this->WriteEmptyDependMakeFile(file, depMarkFileFull.c_str(),
  545. depMakeFileFull.c_str());
  546. }
  547. return depMakeFile;
  548. }
  549. //----------------------------------------------------------------------------
  550. void
  551. cmLocalUnixMakefileGenerator2
  552. ::WriteMakeRule(std::ostream& os,
  553. const char* comment,
  554. const char* preEcho,
  555. const char* target,
  556. const std::vector<std::string>& depends,
  557. const std::vector<std::string>& commands,
  558. const char* postEcho)
  559. {
  560. // Make sure there is a target.
  561. if(!target || !*target)
  562. {
  563. cmSystemTools::Error("No target for WriteMakeRule!");
  564. return;
  565. }
  566. std::string replace;
  567. // Write the comment describing the rule in the makefile.
  568. if(comment)
  569. {
  570. replace = comment;
  571. m_Makefile->ExpandVariablesInString(replace);
  572. std::string::size_type lpos = 0;
  573. std::string::size_type rpos;
  574. while((rpos = replace.find('\n', lpos)) != std::string::npos)
  575. {
  576. os << "# " << replace.substr(lpos, rpos-lpos) << "\n";
  577. lpos = rpos+1;
  578. }
  579. os << "# " << replace.substr(lpos) << "\n";
  580. }
  581. // Construct the left hand side of the rule.
  582. replace = target;
  583. m_Makefile->ExpandVariablesInString(replace);
  584. std::string tgt = this->ConvertToRelativeOutputPath(replace.c_str());
  585. tgt = this->ConvertToMakeTarget(tgt.c_str());
  586. const char* space = "";
  587. if(tgt.size() == 1)
  588. {
  589. // Add a space before the ":" to avoid drive letter confusion on
  590. // Windows.
  591. space = " ";
  592. }
  593. // Write the rule.
  594. if(depends.empty())
  595. {
  596. // No dependencies. The commands will always run.
  597. os << tgt.c_str() << space << ":\n";
  598. }
  599. else
  600. {
  601. // Split dependencies into multiple rule lines. This allows for
  602. // very long dependency lists even on older make implementations.
  603. for(std::vector<std::string>::const_iterator dep = depends.begin();
  604. dep != depends.end(); ++dep)
  605. {
  606. replace = *dep;
  607. m_Makefile->ExpandVariablesInString(replace);
  608. replace = this->ConvertToRelativeOutputPath(replace.c_str());
  609. replace = this->ConvertToMakeTarget(replace.c_str());
  610. os << tgt.c_str() << space << ": " << replace.c_str() << "\n";
  611. }
  612. }
  613. // Write the list of commands.
  614. bool first = true;
  615. for(std::vector<std::string>::const_iterator i = commands.begin();
  616. i != commands.end(); ++i)
  617. {
  618. replace = *i;
  619. m_Makefile->ExpandVariablesInString(replace);
  620. if(first && preEcho)
  621. {
  622. this->OutputEcho(os, preEcho);
  623. }
  624. os << "\t" << replace.c_str() << "\n";
  625. first = false;
  626. }
  627. if(postEcho)
  628. {
  629. this->OutputEcho(os, postEcho);
  630. }
  631. os << "\n";
  632. }
  633. //----------------------------------------------------------------------------
  634. void cmLocalUnixMakefileGenerator2::WriteDivider(std::ostream& os)
  635. {
  636. os
  637. << "#======================================"
  638. << "=======================================\n";
  639. }
  640. //----------------------------------------------------------------------------
  641. void cmLocalUnixMakefileGenerator2::WriteDisclaimer(std::ostream& os)
  642. {
  643. os
  644. << "# CMAKE generated file: DO NOT EDIT!\n"
  645. << "# Generated by \"" << m_GlobalGenerator->GetName() << "\""
  646. << " Generator, CMake Version "
  647. << cmMakefile::GetMajorVersion() << "."
  648. << cmMakefile::GetMinorVersion() << "\n\n";
  649. }
  650. //----------------------------------------------------------------------------
  651. void
  652. cmLocalUnixMakefileGenerator2
  653. ::WriteMakeVariables(std::ostream& makefileStream)
  654. {
  655. this->WriteDivider(makefileStream);
  656. makefileStream
  657. << "# Set environment variables for the build.\n"
  658. << "\n";
  659. if(m_WindowsShell)
  660. {
  661. makefileStream
  662. << "!IF \"$(OS)\" == \"Windows_NT\"\n"
  663. << "NULL=\n"
  664. << "!ELSE\n"
  665. << "NULL=nul\n"
  666. << "!ENDIF\n";
  667. }
  668. else
  669. {
  670. makefileStream
  671. << "# The shell in which to execute make rules.\n"
  672. << "SHELL = /bin/sh\n"
  673. << "\n";
  674. }
  675. std::string cmakecommand =
  676. this->ConvertToOutputForExisting(
  677. m_Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
  678. makefileStream
  679. << "# The CMake executable.\n"
  680. << "CMAKE_COMMAND = " << cmakecommand.c_str() << "\n"
  681. << "\n";
  682. makefileStream
  683. << "# The command to remove a file.\n"
  684. << "RM = " << cmakecommand.c_str() << " -E remove -f\n"
  685. << "\n";
  686. if(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
  687. {
  688. makefileStream
  689. << "# The program to use to edit the cache.\n"
  690. << "CMAKE_EDIT_COMMAND = "
  691. << (this->ConvertToOutputForExisting(
  692. m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))) << "\n"
  693. << "\n";
  694. }
  695. makefileStream
  696. << "# The source directory corresponding to this makefile.\n"
  697. << "CMAKE_CURRENT_SOURCE = "
  698. << this->ConvertToRelativeOutputPath(m_Makefile->GetStartDirectory())
  699. << "\n"
  700. << "\n";
  701. makefileStream
  702. << "# The build directory corresponding to this makefile.\n"
  703. << "CMAKE_CURRENT_BINARY = "
  704. << this->ConvertToRelativeOutputPath(m_Makefile->GetStartOutputDirectory())
  705. << "\n"
  706. << "\n";
  707. makefileStream
  708. << "# The top-level source directory on which CMake was run.\n"
  709. << "CMAKE_SOURCE_DIR = "
  710. << this->ConvertToRelativeOutputPath(m_Makefile->GetHomeDirectory())
  711. << "\n"
  712. << "\n";
  713. makefileStream
  714. << "# The top-level build directory on which CMake was run.\n"
  715. << "CMAKE_BINARY_DIR = "
  716. << this->ConvertToRelativeOutputPath(m_Makefile->GetHomeOutputDirectory())
  717. << "\n"
  718. << "\n";
  719. }
  720. //----------------------------------------------------------------------------
  721. void
  722. cmLocalUnixMakefileGenerator2
  723. ::WriteSpecialTargetsTop(std::ostream& makefileStream)
  724. {
  725. this->WriteDivider(makefileStream);
  726. makefileStream
  727. << "# Special targets provided by cmake.\n"
  728. << "\n";
  729. // Build command to run CMake to check if anything needs regenerating.
  730. std::string cmakefileName = m_Makefile->GetStartOutputDirectory();
  731. cmakefileName += "/Makefile2.cmake";
  732. std::string runRule =
  733. "@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
  734. runRule += " --check-build-system ";
  735. runRule += this->ConvertToRelativeOutputPath(cmakefileName.c_str());
  736. // Write the main entry point target. This must be the VERY first
  737. // target so that make with no arguments will run it. The
  738. // dependencies and commands generated for this rule must not depend
  739. // on listfile contents because the build system check might
  740. // regenerate the makefile but it might not get read again by make
  741. // before the commands run.
  742. {
  743. std::vector<std::string> depends;
  744. std::vector<std::string> commands;
  745. // Check the build system in this directory.
  746. depends.push_back("cmake_check_build_system");
  747. // Recursively build pre-order directories.
  748. commands.push_back(this->GetRecursiveMakeCall("all.subdirs.pre", true));
  749. // Recursively build dependencies.
  750. commands.push_back(this->GetRecursiveMakeCall("all.depends", true));
  751. // Recursively build targets.
  752. commands.push_back(this->GetRecursiveMakeCall("all.build", true));
  753. // Recursively build post-order directories.
  754. commands.push_back(this->GetRecursiveMakeCall("all.subdirs.post", true));
  755. // Write the rule.
  756. std::string preEcho = "Entering directory ";
  757. preEcho += m_Makefile->GetStartOutputDirectory();
  758. std::string postEcho = "Finished directory ";
  759. postEcho += m_Makefile->GetStartOutputDirectory();
  760. this->WriteMakeRule(makefileStream,
  761. "Default target executed when no arguments are "
  762. "given to make.",
  763. preEcho.c_str(),
  764. "all",
  765. depends,
  766. commands,
  767. postEcho.c_str());
  768. }
  769. // Write special "cmake_check_build_system" target to run cmake with
  770. // the --check-build-system flag.
  771. {
  772. std::vector<std::string> no_depends;
  773. std::vector<std::string> commands;
  774. commands.push_back(runRule);
  775. std::string preEcho = "Checking build system in ";
  776. preEcho += m_Makefile->GetStartOutputDirectory();
  777. preEcho += "...";
  778. this->WriteMakeRule(makefileStream,
  779. "Special rule to run CMake to check the build system "
  780. "integrity.\n"
  781. "No rule that depends on this can have "
  782. "commands that come from listfiles\n"
  783. "because they might be regenerated.",
  784. preEcho.c_str(),
  785. "cmake_check_build_system",
  786. no_depends,
  787. commands);
  788. }
  789. // Write special "rebuild_cache" target to re-run cmake.
  790. {
  791. std::vector<std::string> no_depends;
  792. std::vector<std::string> commands;
  793. commands.push_back(
  794. "@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)");
  795. this->WriteMakeRule(makefileStream,
  796. "Special rule to re-run CMake using make.",
  797. "Running CMake to regenerate build system...",
  798. "rebuild_cache",
  799. no_depends,
  800. commands);
  801. }
  802. // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
  803. // Otherwise default to the interactive command-line interface.
  804. if(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
  805. {
  806. std::vector<std::string> no_depends;
  807. std::vector<std::string> commands;
  808. commands.push_back(
  809. "@$(CMAKE_EDIT_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)");
  810. this->WriteMakeRule(makefileStream,
  811. "Special rule to re-run CMake cache editor using make.",
  812. "Running CMake cache editor...",
  813. "edit_cache",
  814. no_depends,
  815. commands);
  816. }
  817. else
  818. {
  819. std::vector<std::string> no_depends;
  820. std::vector<std::string> commands;
  821. commands.push_back(
  822. "@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -i");
  823. this->WriteMakeRule(makefileStream,
  824. "Special rule to re-run CMake cache editor using make.",
  825. "Running interactive CMake command-line interface...",
  826. "edit_cache",
  827. no_depends,
  828. commands);
  829. }
  830. }
  831. //----------------------------------------------------------------------------
  832. void
  833. cmLocalUnixMakefileGenerator2
  834. ::WriteSpecialTargetsBottom(std::ostream& makefileStream)
  835. {
  836. this->WriteDivider(makefileStream);
  837. makefileStream
  838. << "# Special targets to cleanup operation of make.\n"
  839. << "\n";
  840. std::vector<std::string> no_commands;
  841. // Write special target to silence make output. This must be after
  842. // the default target in case VERBOSE is set (which changes the name).
  843. if(!m_Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
  844. {
  845. std::vector<std::string> no_depends;
  846. this->WriteMakeRule(makefileStream,
  847. "Suppress display of executed commands.",
  848. 0,
  849. "$(VERBOSE).SILENT",
  850. no_depends,
  851. no_commands);
  852. }
  853. // Special target to cleanup operation of make tool.
  854. std::vector<std::string> depends;
  855. depends.push_back(".hpux_make_must_have_this_dependency_here");
  856. this->WriteMakeRule(makefileStream,
  857. "Disable some common implicit rules to speed things up.",
  858. 0,
  859. ".SUFFIXES",
  860. depends,
  861. no_commands);
  862. }
  863. //----------------------------------------------------------------------------
  864. void
  865. cmLocalUnixMakefileGenerator2
  866. ::WriteAllRule(std::ostream& makefileStream)
  867. {
  868. // Write section header.
  869. this->WriteDivider(makefileStream);
  870. makefileStream
  871. << "# Main rules for this directory.\n"
  872. << "\n";
  873. const cmTargets& targets = m_Makefile->GetTargets();
  874. // Output top level dependency rule.
  875. {
  876. std::vector<std::string> depends;
  877. std::vector<std::string> commands;
  878. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  879. {
  880. // TODO: Dispatch generation of each target type.
  881. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  882. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  883. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  884. (t->second.GetType() == cmTarget::MODULE_LIBRARY))
  885. {
  886. if(t->second.IsInAll())
  887. {
  888. std::string dep = this->GetTargetDirectory(t->second);
  889. dep += "/";
  890. dep += t->first;
  891. dep += ".depends";
  892. depends.push_back(dep);
  893. }
  894. }
  895. }
  896. // If there are no dependencies, use empty commands.
  897. if(depends.empty())
  898. {
  899. commands = m_EmptyCommands;
  900. }
  901. // Write the rule.
  902. this->WriteMakeRule(makefileStream,
  903. "Main dependencies target for this directory.",
  904. 0,
  905. "all.depends",
  906. depends,
  907. commands);
  908. }
  909. // Output top level build rule.
  910. {
  911. std::vector<std::string> depends;
  912. std::vector<std::string> commands;
  913. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  914. {
  915. // TODO: Dispatch generation of each target type.
  916. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  917. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  918. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  919. (t->second.GetType() == cmTarget::MODULE_LIBRARY))
  920. {
  921. if(t->second.IsInAll())
  922. {
  923. depends.push_back(t->first+".requires");
  924. }
  925. }
  926. }
  927. // If there are no dependencies, use empty commands.
  928. if(depends.empty())
  929. {
  930. commands = m_EmptyCommands;
  931. }
  932. // Write the rule.
  933. this->WriteMakeRule(makefileStream,
  934. "Main build target for this directory.",
  935. 0,
  936. "all.build",
  937. depends,
  938. commands);
  939. }
  940. }
  941. //----------------------------------------------------------------------------
  942. void
  943. cmLocalUnixMakefileGenerator2
  944. ::WriteSubdirRules(std::ostream& makefileStream, const char* pass)
  945. {
  946. // Write the section header.
  947. this->WriteDivider(makefileStream);
  948. makefileStream
  949. << "# Subdirectory driver targets for " << pass << "\n"
  950. << "\n";
  951. // Iterate through subdirectories. Only entries in which the
  952. // boolean is true should be included. Keep track of the last
  953. // pre-order and last post-order rule created so that ordering can
  954. // be enforced.
  955. const std::vector<std::pair<cmStdString, bool> >&
  956. subdirs = m_Makefile->GetSubDirectories();
  957. std::string lastPre = "";
  958. std::string lastPost = "";
  959. for(std::vector<std::pair<cmStdString, bool> >::const_iterator
  960. i = subdirs.begin(); i != subdirs.end(); ++i)
  961. {
  962. if(i->second)
  963. {
  964. // Add the subdirectory rule either for pre-order or post-order.
  965. if(m_Makefile->IsDirectoryPreOrder(i->first.c_str()))
  966. {
  967. this->WriteSubdirRule(makefileStream, pass, i->first.c_str(), lastPre);
  968. }
  969. else
  970. {
  971. this->WriteSubdirRule(makefileStream, pass, i->first.c_str(), lastPost);
  972. }
  973. }
  974. }
  975. // Write the subdir driver rules. Hook them to the last
  976. // subdirectory of their corresponding order.
  977. this->WriteSubdirDriverRule(makefileStream, pass, "pre", lastPre);
  978. this->WriteSubdirDriverRule(makefileStream, pass, "post", lastPost);
  979. }
  980. //----------------------------------------------------------------------------
  981. void
  982. cmLocalUnixMakefileGenerator2
  983. ::WriteSubdirRule(std::ostream& makefileStream, const char* pass,
  984. const char* subdir, std::string& last)
  985. {
  986. std::vector<std::string> depends;
  987. std::vector<std::string> commands;
  988. // Construct the name of the subdirectory rule.
  989. std::string tgt = this->GetSubdirTargetName(pass, subdir);
  990. if(m_WindowsShell)
  991. {
  992. // On Windows we must perform each step separately and then change
  993. // back because the shell keeps the working directory between
  994. // commands.
  995. std::string cmd = "@cd ";
  996. cmd += this->ConvertToOutputForExisting(subdir);
  997. commands.push_back(cmd);
  998. // Build the target for this pass.
  999. commands.push_back(this->GetRecursiveMakeCall(pass, true));
  1000. // Change back to the starting directory. Any trailing slash must
  1001. // be removed to avoid problems with Borland Make.
  1002. std::string destFull = m_Makefile->GetStartOutputDirectory();
  1003. destFull += "/";
  1004. destFull += subdir;
  1005. std::string back =
  1006. cmSystemTools::RelativePath(destFull.c_str(),
  1007. m_Makefile->GetStartOutputDirectory());
  1008. if(back.size() && back[back.size()-1] == '/')
  1009. {
  1010. back = back.substr(0, back.size()-1);
  1011. }
  1012. cmd = "@cd ";
  1013. cmd += this->ConvertToOutputForExisting(back.c_str());
  1014. commands.push_back(cmd);
  1015. }
  1016. else
  1017. {
  1018. // On UNIX we must construct a single shell command to change
  1019. // directory and build because make resets the directory between
  1020. // each command.
  1021. std::string cmd = "@cd ";
  1022. cmd += this->ConvertToOutputForExisting(subdir);
  1023. // Build the target for this pass.
  1024. cmd += " && ";
  1025. cmd += this->GetRecursiveMakeCall(pass, false);
  1026. // Add the command as a single line.
  1027. commands.push_back(cmd);
  1028. }
  1029. // Depend on the last directory written out to enforce ordering.
  1030. if(last.size() > 0)
  1031. {
  1032. depends.push_back(last);
  1033. }
  1034. // Write the rule.
  1035. this->WriteMakeRule(makefileStream, 0, 0, tgt.c_str(), depends, commands);
  1036. // This rule is now the last one written.
  1037. last = tgt;
  1038. }
  1039. //----------------------------------------------------------------------------
  1040. void
  1041. cmLocalUnixMakefileGenerator2
  1042. ::WriteSubdirDriverRule(std::ostream& makefileStream, const char* pass,
  1043. const char* order, const std::string& last)
  1044. {
  1045. // This rule corresponds to a particular pass (all, clean, etc). It
  1046. // dispatches the build into subdirectories in pre- or post-order.
  1047. std::vector<std::string> depends;
  1048. std::vector<std::string> commands;
  1049. if(last.size())
  1050. {
  1051. // Use the dependency to drive subdirectory processing.
  1052. depends.push_back(last);
  1053. }
  1054. else
  1055. {
  1056. // There are no subdirectories. Use the empty commands to avoid
  1057. // make errors on some platforms.
  1058. commands = m_EmptyCommands;
  1059. }
  1060. // Build comment to describe purpose.
  1061. std::string comment = "Driver target for ";
  1062. comment += order;
  1063. comment += "-order subdirectories during ";
  1064. comment += pass;
  1065. comment += ".";
  1066. // Build the make target name.
  1067. std::string tgt = pass;
  1068. tgt += ".subdirs.";
  1069. tgt += order;
  1070. // Write the rule.
  1071. this->WriteMakeRule(makefileStream, comment.c_str(), 0,
  1072. tgt.c_str(), depends, commands);
  1073. }
  1074. //----------------------------------------------------------------------------
  1075. void
  1076. cmLocalUnixMakefileGenerator2
  1077. ::WriteRequiresRule(std::ostream& ruleFileStream, const cmTarget& target,
  1078. const char* targetFullPath)
  1079. {
  1080. std::vector<std::string> depends;
  1081. std::vector<std::string> no_commands;
  1082. std::string reqComment = "Requirements for target ";
  1083. reqComment += target.GetName();
  1084. std::string reqTarget = target.GetName();
  1085. reqTarget += ".requires";
  1086. depends.push_back(targetFullPath);
  1087. this->WriteMakeRule(ruleFileStream, reqComment.c_str(), 0,
  1088. reqTarget.c_str(), depends, no_commands);
  1089. }
  1090. //----------------------------------------------------------------------------
  1091. void
  1092. cmLocalUnixMakefileGenerator2
  1093. ::WriteRuleFileIncludes(std::ostream& makefileStream)
  1094. {
  1095. // Make sure we have some rules to include.
  1096. if(m_IncludeRuleFiles.empty())
  1097. {
  1098. return;
  1099. }
  1100. // Write section header.
  1101. this->WriteDivider(makefileStream);
  1102. makefileStream
  1103. << "# Include rule files for this directory.\n"
  1104. << "\n";
  1105. // Write the include rules.
  1106. for(std::vector<std::string>::const_iterator i = m_IncludeRuleFiles.begin();
  1107. i != m_IncludeRuleFiles.end(); ++i)
  1108. {
  1109. makefileStream
  1110. << m_IncludeDirective << " "
  1111. << this->ConvertToOutputForExisting(i->c_str()).c_str()
  1112. << "\n";
  1113. }
  1114. makefileStream << "\n";
  1115. }
  1116. //----------------------------------------------------------------------------
  1117. void
  1118. cmLocalUnixMakefileGenerator2
  1119. ::WriteExecutableRule(std::ostream& ruleFileStream,
  1120. const char* ruleFileName,
  1121. const cmTarget& target,
  1122. std::vector<std::string>& objects)
  1123. {
  1124. std::vector<std::string> commands;
  1125. // Build list of dependencies.
  1126. std::vector<std::string> depends;
  1127. for(std::vector<std::string>::const_iterator obj = objects.begin();
  1128. obj != objects.end(); ++obj)
  1129. {
  1130. depends.push_back(*obj);
  1131. }
  1132. // Add dependencies on libraries that will be linked.
  1133. this->AppendLibDepends(target, depends);
  1134. // Add a dependency on the rule file itself.
  1135. depends.push_back(ruleFileName);
  1136. // Construct the full path to the executable that will be generated.
  1137. std::string targetFullPath = m_ExecutableOutputPath;
  1138. if(targetFullPath.length() == 0)
  1139. {
  1140. targetFullPath = m_Makefile->GetStartOutputDirectory();
  1141. if(targetFullPath.size() && targetFullPath[targetFullPath.size()-1] != '/')
  1142. {
  1143. targetFullPath += "/";
  1144. }
  1145. }
  1146. #ifdef __APPLE__
  1147. if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
  1148. {
  1149. // Make bundle directories
  1150. targetFullPath += target.GetName();
  1151. targetFullPath += ".app/Contents/MacOS/";
  1152. }
  1153. #endif
  1154. targetFullPath += target.GetName();
  1155. targetFullPath += cmSystemTools::GetExecutableExtension();
  1156. targetFullPath = this->ConvertToRelativeOutputPath(targetFullPath.c_str());
  1157. // Get the language to use for linking this executable.
  1158. const char* linkLanguage =
  1159. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1160. // Build a list of compiler flags and linker flags.
  1161. std::string flags;
  1162. std::string linkFlags;
  1163. // Add flags to create an executable.
  1164. this->AddConfigVariableFlags(linkFlags, "CMAKE_EXE_LINKER_FLAGS");
  1165. if(target.GetPropertyAsBool("WIN32_EXECUTABLE"))
  1166. {
  1167. this->AppendFlags(linkFlags,
  1168. m_Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
  1169. }
  1170. else
  1171. {
  1172. this->AppendFlags(linkFlags,
  1173. m_Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
  1174. }
  1175. // Add language-specific flags.
  1176. this->AddLanguageFlags(flags, linkLanguage);
  1177. // Add flags to deal with shared libraries. Any library being
  1178. // linked in might be shared, so always use shared flags for an
  1179. // executable.
  1180. this->AddSharedFlags(flags, linkLanguage, true);
  1181. // Add target-specific linker flags.
  1182. this->AppendFlags(linkFlags, target.GetProperty("LINK_FLAGS"));
  1183. // TODO: Pre-build and pre-link rules.
  1184. // Construct the main link rule.
  1185. std::string linkRuleVar = "CMAKE_";
  1186. linkRuleVar += linkLanguage;
  1187. linkRuleVar += "_LINK_EXECUTABLE";
  1188. std::string linkRule = m_Makefile->GetRequiredDefinition(linkRuleVar.c_str());
  1189. cmSystemTools::ExpandListArgument(linkRule, commands);
  1190. // TODO: Post-build rules.
  1191. // Collect up flags to link in needed libraries.
  1192. cmOStringStream linklibs;
  1193. this->OutputLinkLibraries(linklibs, 0, target);
  1194. // Construct object file lists that may be needed to expand the
  1195. // rule. TODO: Store these in make variables with line continuation
  1196. // to avoid excessively long lines.
  1197. std::string objs;
  1198. std::string objsQuoted;
  1199. const char* space = "";
  1200. for(std::vector<std::string>::iterator i = objects.begin();
  1201. i != objects.end(); ++i)
  1202. {
  1203. objs += space;
  1204. objs += this->ConvertToRelativeOutputPath(i->c_str());
  1205. objsQuoted += space;
  1206. objsQuoted += "\"";
  1207. objsQuoted += this->ConvertToRelativeOutputPath(i->c_str());
  1208. objsQuoted += "\"";
  1209. space = " ";
  1210. }
  1211. // Expand placeholders in the commands.
  1212. for(std::vector<std::string>::iterator i = commands.begin();
  1213. i != commands.end(); ++i)
  1214. {
  1215. this->ExpandRuleVariables(*i,
  1216. linkLanguage,
  1217. objs.c_str(),
  1218. targetFullPath.c_str(),
  1219. linklibs.str().c_str(),
  1220. 0,
  1221. 0,
  1222. flags.c_str(),
  1223. 0,
  1224. 0,
  1225. 0,
  1226. linkFlags.c_str());
  1227. }
  1228. // Write the build rule.
  1229. std::string buildEcho = "Linking ";
  1230. buildEcho += linkLanguage;
  1231. buildEcho += " executable ";
  1232. buildEcho += this->ConvertToRelativeOutputPath(targetFullPath.c_str());
  1233. buildEcho += "...";
  1234. this->WriteMakeRule(ruleFileStream, 0, buildEcho.c_str(),
  1235. targetFullPath.c_str(), depends, commands);
  1236. // TODO: Add "local" target and canonical target name as rules.
  1237. // Write driver rule for this target.
  1238. this->WriteRequiresRule(ruleFileStream, target, targetFullPath.c_str());
  1239. }
  1240. //----------------------------------------------------------------------------
  1241. void
  1242. cmLocalUnixMakefileGenerator2
  1243. ::WriteStaticLibraryRule(std::ostream& ruleFileStream,
  1244. const char* ruleFileName,
  1245. const cmTarget& target,
  1246. std::vector<std::string>& objects)
  1247. {
  1248. const char* linkLanguage =
  1249. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1250. std::string linkRuleVar = "CMAKE_";
  1251. linkRuleVar += linkLanguage;
  1252. linkRuleVar += "_CREATE_STATIC_LIBRARY";
  1253. std::string extraFlags;
  1254. this->AppendFlags(extraFlags, target.GetProperty("STATIC_LIBRARY_FLAGS"));
  1255. this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
  1256. linkRuleVar.c_str(), extraFlags.c_str());
  1257. }
  1258. //----------------------------------------------------------------------------
  1259. void
  1260. cmLocalUnixMakefileGenerator2
  1261. ::WriteSharedLibraryRule(std::ostream& ruleFileStream,
  1262. const char* ruleFileName,
  1263. const cmTarget& target,
  1264. std::vector<std::string>& objects)
  1265. {
  1266. const char* linkLanguage =
  1267. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1268. std::string linkRuleVar = "CMAKE_";
  1269. linkRuleVar += linkLanguage;
  1270. linkRuleVar += "_CREATE_SHARED_LIBRARY";
  1271. std::string extraFlags;
  1272. this->AppendFlags(extraFlags, target.GetProperty("LINK_FLAGS"));
  1273. this->AddConfigVariableFlags(extraFlags, "CMAKE_SHARED_LINKER_FLAGS");
  1274. if(m_Makefile->IsOn("WIN32") && !(m_Makefile->IsOn("CYGWIN") || m_Makefile->IsOn("MINGW")))
  1275. {
  1276. const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
  1277. for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
  1278. i != sources.end(); ++i)
  1279. {
  1280. if((*i)->GetSourceExtension() == "def")
  1281. {
  1282. extraFlags += " ";
  1283. extraFlags += m_Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
  1284. extraFlags += this->ConvertToRelativeOutputPath((*i)->GetFullPath().c_str());
  1285. }
  1286. }
  1287. }
  1288. this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
  1289. linkRuleVar.c_str(), extraFlags.c_str());
  1290. }
  1291. //----------------------------------------------------------------------------
  1292. void
  1293. cmLocalUnixMakefileGenerator2
  1294. ::WriteModuleLibraryRule(std::ostream& ruleFileStream,
  1295. const char* ruleFileName,
  1296. const cmTarget& target,
  1297. std::vector<std::string>& objects)
  1298. {
  1299. const char* linkLanguage =
  1300. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1301. std::string linkRuleVar = "CMAKE_";
  1302. linkRuleVar += linkLanguage;
  1303. linkRuleVar += "_CREATE_SHARED_MODULE";
  1304. std::string extraFlags;
  1305. this->AppendFlags(extraFlags, target.GetProperty("LINK_FLAGS"));
  1306. this->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS");
  1307. // TODO: .def files should be supported here also.
  1308. this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
  1309. linkRuleVar.c_str(), extraFlags.c_str());
  1310. }
  1311. //----------------------------------------------------------------------------
  1312. void
  1313. cmLocalUnixMakefileGenerator2
  1314. ::WriteLibraryRule(std::ostream& ruleFileStream,
  1315. const char* ruleFileName,
  1316. const cmTarget& target,
  1317. std::vector<std::string>& objects,
  1318. const char* linkRuleVar,
  1319. const char* extraFlags)
  1320. {
  1321. // TODO: Merge the methods that call this method to avoid
  1322. // code duplication.
  1323. std::vector<std::string> commands;
  1324. // Build list of dependencies.
  1325. std::vector<std::string> depends;
  1326. for(std::vector<std::string>::const_iterator obj = objects.begin();
  1327. obj != objects.end(); ++obj)
  1328. {
  1329. depends.push_back(*obj);
  1330. }
  1331. // Add dependencies on libraries that will be linked.
  1332. this->AppendLibDepends(target, depends);
  1333. // Add a dependency on the rule file itself.
  1334. depends.push_back(ruleFileName);
  1335. const char* linkLanguage =
  1336. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1337. std::string linkFlags;
  1338. this->AppendFlags(linkFlags, extraFlags);
  1339. std::string targetName;
  1340. std::string targetNameSO;
  1341. std::string targetNameReal;
  1342. std::string targetNameBase;
  1343. this->GetLibraryNames(target.GetName(), target,
  1344. targetName, targetNameSO,
  1345. targetNameReal, targetNameBase);
  1346. std::string outpath;
  1347. std::string outdir;
  1348. if(m_UseRelativePaths)
  1349. {
  1350. outdir = this->ConvertToRelativeOutputPath(m_LibraryOutputPath.c_str());
  1351. }
  1352. else
  1353. {
  1354. outdir = m_LibraryOutputPath;
  1355. }
  1356. if(!m_WindowsShell && m_UseRelativePaths && outdir.size())
  1357. {
  1358. outpath = "\"`cd ";
  1359. }
  1360. outpath += outdir;
  1361. if(!m_WindowsShell && m_UseRelativePaths && outdir.size())
  1362. {
  1363. outpath += ";pwd`\"/";
  1364. }
  1365. if(outdir.size() == 0 && m_UseRelativePaths && !m_WindowsShell)
  1366. {
  1367. outpath = "\"`pwd`\"/";
  1368. }
  1369. // The full path versions of the names.
  1370. std::string targetFullPath = outpath + targetName;
  1371. std::string targetFullPathSO = outpath + targetNameSO;
  1372. std::string targetFullPathReal = outpath + targetNameReal;
  1373. std::string targetFullPathBase = outpath + targetNameBase;
  1374. // If not using relative paths then the output path needs to be
  1375. // converted here
  1376. if(!m_UseRelativePaths)
  1377. {
  1378. targetFullPath = this->ConvertToRelativeOutputPath(targetFullPath.c_str());
  1379. targetFullPathSO = this->ConvertToRelativeOutputPath(targetFullPathSO.c_str());
  1380. targetFullPathReal = this->ConvertToRelativeOutputPath(targetFullPathReal.c_str());
  1381. targetFullPathBase = this->ConvertToRelativeOutputPath(targetFullPathBase.c_str());
  1382. }
  1383. // Add a command to remove any existing files for this library.
  1384. std::string remove = "@$(CMAKE_COMMAND) -E remove -f ";
  1385. remove += targetFullPathReal;
  1386. if(targetFullPathSO != targetFullPathReal)
  1387. {
  1388. remove += " ";
  1389. remove += targetFullPathSO;
  1390. }
  1391. if(targetFullPath != targetFullPathSO &&
  1392. targetFullPath != targetFullPathReal)
  1393. {
  1394. remove += " ";
  1395. remove += targetFullPath;
  1396. }
  1397. commands.push_back(remove);
  1398. // TODO: Pre-build and pre-link rules.
  1399. // Construct the main link rule.
  1400. std::string linkRule = m_Makefile->GetRequiredDefinition(linkRuleVar);
  1401. cmSystemTools::ExpandListArgument(linkRule, commands);
  1402. // Add a rule to create necessary symlinks for the library.
  1403. if(targetFullPath != targetFullPathReal)
  1404. {
  1405. std::string symlink = "@$(CMAKE_COMMAND) -E cmake_symlink_library ";
  1406. symlink += targetFullPathReal;
  1407. symlink += " ";
  1408. symlink += targetFullPathSO;
  1409. symlink += " ";
  1410. symlink += targetFullPath;
  1411. commands.push_back(symlink);
  1412. }
  1413. // TODO: Post-build rules.
  1414. // Collect up flags to link in needed libraries.
  1415. cmOStringStream linklibs;
  1416. this->OutputLinkLibraries(linklibs, target.GetName(), target);
  1417. // Construct object file lists that may be needed to expand the
  1418. // rule. TODO: Store these in make variables with line continuation
  1419. // to avoid excessively long lines.
  1420. std::string objs;
  1421. std::string objsQuoted;
  1422. const char* space = "";
  1423. for(std::vector<std::string>::iterator i = objects.begin();
  1424. i != objects.end(); ++i)
  1425. {
  1426. objs += space;
  1427. objs += this->ConvertToRelativeOutputPath(i->c_str());
  1428. objsQuoted += space;
  1429. objsQuoted += "\"";
  1430. objsQuoted += this->ConvertToRelativeOutputPath(i->c_str());
  1431. objsQuoted += "\"";
  1432. space = " ";
  1433. }
  1434. // Expand placeholders in the commands.
  1435. for(std::vector<std::string>::iterator i = commands.begin();
  1436. i != commands.end(); ++i)
  1437. {
  1438. this->ExpandRuleVariables(*i,
  1439. linkLanguage,
  1440. objs.c_str(),
  1441. targetFullPathReal.c_str(),
  1442. linklibs.str().c_str(),
  1443. 0, 0, 0, objsQuoted.c_str(),
  1444. targetFullPathBase.c_str(),
  1445. targetNameSO.c_str(),
  1446. linkFlags.c_str());
  1447. }
  1448. // Write the build rule.
  1449. std::string buildEcho = "Linking ";
  1450. buildEcho += linkLanguage;
  1451. switch(target.GetType())
  1452. {
  1453. case cmTarget::STATIC_LIBRARY:
  1454. buildEcho += " static library "; break;
  1455. case cmTarget::SHARED_LIBRARY:
  1456. buildEcho += " shared library "; break;
  1457. case cmTarget::MODULE_LIBRARY:
  1458. buildEcho += " shared module "; break;
  1459. default:
  1460. buildEcho += " library "; break;
  1461. }
  1462. buildEcho += this->ConvertToRelativeOutputPath(targetFullPath.c_str());
  1463. buildEcho += "...";
  1464. this->WriteMakeRule(ruleFileStream, 0, buildEcho.c_str(),
  1465. targetFullPath.c_str(), depends, commands);
  1466. // TODO: Add "local" target and canonical target name as rules.
  1467. // Write driver rule for this target.
  1468. this->WriteRequiresRule(ruleFileStream, target, targetFullPath.c_str());
  1469. }
  1470. //----------------------------------------------------------------------------
  1471. std::string
  1472. cmLocalUnixMakefileGenerator2
  1473. ::GetTargetDirectory(const cmTarget& target)
  1474. {
  1475. std::string dir = target.GetName();
  1476. dir += ".dir";
  1477. return dir;
  1478. }
  1479. //----------------------------------------------------------------------------
  1480. std::string
  1481. cmLocalUnixMakefileGenerator2
  1482. ::GetSubdirTargetName(const char* pass, const char* subdir)
  1483. {
  1484. // Convert the subdirectory name to a valid make target name.
  1485. std::string s = pass;
  1486. s += "_";
  1487. s += subdir;
  1488. // Replace "../" with 3 underscores. This allows one .. at the beginning.
  1489. size_t pos = s.find("../");
  1490. if(pos != std::string::npos)
  1491. {
  1492. s.replace(pos, 3, "___");
  1493. }
  1494. // Replace "/" directory separators with a single underscore.
  1495. while((pos = s.find('/')) != std::string::npos)
  1496. {
  1497. s.replace(pos, 1, "_");
  1498. }
  1499. return s;
  1500. }
  1501. //----------------------------------------------------------------------------
  1502. std::string
  1503. cmLocalUnixMakefileGenerator2
  1504. ::GetObjectFileName(const cmTarget& target,
  1505. const cmSourceFile& source)
  1506. {
  1507. // If the full path to the source file includes this directory,
  1508. // we want to use the relative path for the filename of the
  1509. // object file. Otherwise, we will use just the filename
  1510. // portion.
  1511. std::string objectName;
  1512. if((cmSystemTools::GetFilenamePath(
  1513. source.GetFullPath()).find(
  1514. m_Makefile->GetCurrentDirectory()) == 0)
  1515. || (cmSystemTools::GetFilenamePath(
  1516. source.GetFullPath()).find(
  1517. m_Makefile->GetStartOutputDirectory()) == 0))
  1518. {
  1519. objectName = source.GetSourceName();
  1520. }
  1521. else
  1522. {
  1523. objectName = cmSystemTools::GetFilenameName(source.GetSourceName());
  1524. }
  1525. // Append the object file extension.
  1526. objectName +=
  1527. m_GlobalGenerator->GetLanguageOutputExtensionFromExtension(
  1528. source.GetSourceExtension().c_str());
  1529. // Convert to a safe name.
  1530. objectName = this->CreateSafeUniqueObjectFileName(objectName.c_str());
  1531. // Prepend the target directory.
  1532. std::string obj = this->GetTargetDirectory(target);
  1533. obj += "/";
  1534. obj += objectName;
  1535. return obj;
  1536. }
  1537. //----------------------------------------------------------------------------
  1538. std::string
  1539. cmLocalUnixMakefileGenerator2
  1540. ::GetCustomBaseName(const cmCustomCommand& cc)
  1541. {
  1542. // If the full path to the output file includes this build
  1543. // directory, we want to use the relative path for the filename of
  1544. // the custom file. Otherwise, we will use just the filename
  1545. // portion.
  1546. std::string customName;
  1547. if(cmSystemTools::FileIsFullPath(cc.GetOutput().c_str()) &&
  1548. (cc.GetOutput().find(m_Makefile->GetStartOutputDirectory()) == 0))
  1549. {
  1550. customName =
  1551. cmSystemTools::RelativePath(m_Makefile->GetStartOutputDirectory(),
  1552. cc.GetOutput().c_str());
  1553. }
  1554. else
  1555. {
  1556. customName = cmSystemTools::GetFilenameName(cc.GetOutput().c_str());
  1557. }
  1558. return customName;
  1559. }
  1560. //----------------------------------------------------------------------------
  1561. const char*
  1562. cmLocalUnixMakefileGenerator2
  1563. ::GetSourceFileLanguage(const cmSourceFile& source)
  1564. {
  1565. // Identify the language of the source file.
  1566. return (m_GlobalGenerator
  1567. ->GetLanguageFromExtension(source.GetSourceExtension().c_str()));
  1568. }
  1569. //----------------------------------------------------------------------------
  1570. std::string
  1571. cmLocalUnixMakefileGenerator2
  1572. ::ConvertToFullPath(const std::string& localPath)
  1573. {
  1574. std::string dir = m_Makefile->GetStartOutputDirectory();
  1575. dir += "/";
  1576. dir += localPath;
  1577. return dir;
  1578. }
  1579. //----------------------------------------------------------------------------
  1580. void cmLocalUnixMakefileGenerator2::AddLanguageFlags(std::string& flags,
  1581. const char* lang)
  1582. {
  1583. // Add language-specific flags.
  1584. std::string flagsVar = "CMAKE_";
  1585. flagsVar += lang;
  1586. flagsVar += "_FLAGS";
  1587. this->AddConfigVariableFlags(flags, flagsVar.c_str());
  1588. }
  1589. //----------------------------------------------------------------------------
  1590. void cmLocalUnixMakefileGenerator2::AddSharedFlags(std::string& flags,
  1591. const char* lang,
  1592. bool shared)
  1593. {
  1594. std::string flagsVar;
  1595. // Add flags for dealing with shared libraries for this language.
  1596. if(shared)
  1597. {
  1598. flagsVar = "CMAKE_SHARED_LIBRARY_";
  1599. flagsVar += lang;
  1600. flagsVar += "_FLAGS";
  1601. this->AppendFlags(flags, m_Makefile->GetDefinition(flagsVar.c_str()));
  1602. }
  1603. // Add flags specific to shared builds.
  1604. if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
  1605. {
  1606. flagsVar = "CMAKE_SHARED_BUILD_";
  1607. flagsVar += lang;
  1608. flagsVar += "_FLAGS";
  1609. this->AppendFlags(flags, m_Makefile->GetDefinition(flagsVar.c_str()));
  1610. }
  1611. }
  1612. //----------------------------------------------------------------------------
  1613. void cmLocalUnixMakefileGenerator2::AddConfigVariableFlags(std::string& flags,
  1614. const char* var)
  1615. {
  1616. // Add the flags from the variable itself.
  1617. std::string flagsVar = var;
  1618. this->AppendFlags(flags, m_Makefile->GetDefinition(flagsVar.c_str()));
  1619. // Add the flags from the build-type specific variable.
  1620. const char* buildType = m_Makefile->GetDefinition("CMAKE_BUILD_TYPE");
  1621. if(buildType && *buildType)
  1622. {
  1623. flagsVar += "_";
  1624. flagsVar += cmSystemTools::UpperCase(buildType);
  1625. this->AppendFlags(flags, m_Makefile->GetDefinition(flagsVar.c_str()));
  1626. }
  1627. }
  1628. //----------------------------------------------------------------------------
  1629. void cmLocalUnixMakefileGenerator2::AppendFlags(std::string& flags,
  1630. const char* newFlags)
  1631. {
  1632. if(newFlags && *newFlags)
  1633. {
  1634. if(flags.size())
  1635. {
  1636. flags += " ";
  1637. }
  1638. flags += newFlags;
  1639. }
  1640. }
  1641. //----------------------------------------------------------------------------
  1642. void
  1643. cmLocalUnixMakefileGenerator2
  1644. ::AppendLibDepends(const cmTarget& target,
  1645. std::vector<std::string>& depends)
  1646. {
  1647. // Do not bother with dependencies for static libraries.
  1648. if(target.GetType() == cmTarget::STATIC_LIBRARY)
  1649. {
  1650. return;
  1651. }
  1652. // Keep track of dependencies already listed.
  1653. std::set<cmStdString> emitted;
  1654. // A target should not depend on itself.
  1655. emitted.insert(target.GetName());
  1656. // Loop over all dependencies.
  1657. const cmTarget::LinkLibraries& tlibs = target.GetLinkLibraries();
  1658. for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
  1659. lib != tlibs.end(); ++lib)
  1660. {
  1661. // Don't emit the same library twice for this target.
  1662. if(emitted.insert(lib->first).second)
  1663. {
  1664. // Add this dependency.
  1665. this->AppendLibDepend(depends, lib->first.c_str());
  1666. }
  1667. }
  1668. }
  1669. //----------------------------------------------------------------------------
  1670. void
  1671. cmLocalUnixMakefileGenerator2
  1672. ::AppendLibDepend(std::vector<std::string>& depends, const char* name)
  1673. {
  1674. // There are a few cases for the name of the target:
  1675. // - CMake target in this directory: depend on it.
  1676. // - CMake target in another directory: depend and add jump-and-build.
  1677. // - Full path to an outside file: depend on it.
  1678. // - Other format (like -lm): do nothing.
  1679. // If it is a CMake target there will be a definition for it.
  1680. std::string dirVar = name;
  1681. dirVar += "_CMAKE_PATH";
  1682. const char* dir = m_Makefile->GetDefinition(dirVar.c_str());
  1683. if(dir && *dir)
  1684. {
  1685. // This is a CMake target somewhere in this project.
  1686. bool jumpAndBuild = false;
  1687. // Get the path to the library.
  1688. std::string libPath;
  1689. if(this->SamePath(m_Makefile->GetStartOutputDirectory(), dir))
  1690. {
  1691. // The target is in the current directory so this makefile will
  1692. // know about it already.
  1693. libPath = m_LibraryOutputPath;
  1694. }
  1695. else
  1696. {
  1697. // The target is in another directory. Get the path to it.
  1698. if(m_LibraryOutputPath.size())
  1699. {
  1700. libPath = m_LibraryOutputPath;
  1701. }
  1702. else
  1703. {
  1704. libPath = dir;
  1705. libPath += "/";
  1706. }
  1707. // We need to add a jump-and-build rule for this library.
  1708. jumpAndBuild = true;
  1709. }
  1710. // Add the name of the library's file. This depends on the type
  1711. // of the library.
  1712. std::string typeVar = name;
  1713. typeVar += "_LIBRARY_TYPE";
  1714. std::string libType = m_Makefile->GetSafeDefinition(typeVar.c_str());
  1715. std::string prefix;
  1716. std::string suffix;
  1717. if(libType == "SHARED")
  1718. {
  1719. prefix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_PREFIX");
  1720. suffix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX");
  1721. }
  1722. else if(libType == "MODULE")
  1723. {
  1724. prefix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_MODULE_PREFIX");
  1725. suffix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_MODULE_SUFFIX");
  1726. }
  1727. else if(libType == "STATIC")
  1728. {
  1729. prefix = m_Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
  1730. suffix = m_Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
  1731. }
  1732. libPath += prefix;
  1733. libPath += name;
  1734. libPath += suffix;
  1735. if(jumpAndBuild)
  1736. {
  1737. // We need to add a jump-and-build rule for this library.
  1738. cmLocalUnixMakefileGenerator2::RemoteTarget rt;
  1739. rt.m_BuildDirectory = dir;
  1740. rt.m_FilePath =libPath;
  1741. m_JumpAndBuild[name] = rt;
  1742. }
  1743. // Add a dependency on the library.
  1744. depends.push_back(this->ConvertToRelativeOutputPath(libPath.c_str()));
  1745. }
  1746. else
  1747. {
  1748. // This is not a CMake target. If it exists and is a full path we
  1749. // can depend on it.
  1750. if(cmSystemTools::FileExists(name) && cmSystemTools::FileIsFullPath(name))
  1751. {
  1752. depends.push_back(this->ConvertToRelativeOutputPath(name));
  1753. }
  1754. }
  1755. }
  1756. //----------------------------------------------------------------------------
  1757. std::string
  1758. cmLocalUnixMakefileGenerator2
  1759. ::GetRecursiveMakeCall(const char* tgt, bool silent)
  1760. {
  1761. // Call make on the given file.
  1762. std::string cmd;
  1763. if(silent)
  1764. {
  1765. cmd += "@";
  1766. }
  1767. cmd += "$(MAKE) -f Makefile2 ";
  1768. // Pass down verbosity level.
  1769. if(m_MakeSilentFlag.size())
  1770. {
  1771. cmd += m_MakeSilentFlag;
  1772. cmd += " ";
  1773. }
  1774. // Most unix makes will pass the command line flags to make down to
  1775. // sub-invoked makes via an environment variable. However, some
  1776. // makes do not support that, so you have to pass the flags
  1777. // explicitly.
  1778. if(m_PassMakeflags)
  1779. {
  1780. cmd += "-$(MAKEFLAGS) ";
  1781. }
  1782. // Add the target.
  1783. cmd += tgt;
  1784. return cmd;
  1785. }
  1786. //----------------------------------------------------------------------------
  1787. void
  1788. cmLocalUnixMakefileGenerator2
  1789. ::WriteJumpAndBuildRules(std::ostream& makefileStream)
  1790. {
  1791. // Write the header for this section.
  1792. if(!m_JumpAndBuild.empty())
  1793. {
  1794. this->WriteDivider(makefileStream);
  1795. makefileStream
  1796. << "# Targets to make sure needed libraries exist.\n"
  1797. << "# These will jump to other directories to build targets.\n"
  1798. << "\n";
  1799. }
  1800. std::vector<std::string> depends;
  1801. std::vector<std::string> commands;
  1802. for(std::map<cmStdString, RemoteTarget>::iterator
  1803. jump = m_JumpAndBuild.begin(); jump != m_JumpAndBuild.end(); ++jump)
  1804. {
  1805. const cmLocalUnixMakefileGenerator2::RemoteTarget& rt = jump->second;
  1806. const char* destination = rt.m_BuildDirectory.c_str();
  1807. // Construct the dependency and build target names.
  1808. std::string dep = jump->first;
  1809. dep += ".dir/";
  1810. dep += jump->first;
  1811. dep += ".depends";
  1812. dep = this->ConvertToRelativeOutputPath(dep.c_str());
  1813. std::string tgt = jump->first;
  1814. tgt += ".requires";
  1815. tgt = this->ConvertToRelativeOutputPath(tgt.c_str());
  1816. // Build the jump-and-build command list.
  1817. commands.clear();
  1818. if(m_WindowsShell)
  1819. {
  1820. // On Windows we must perform each step separately and then jump
  1821. // back because the shell keeps the working directory between
  1822. // commands.
  1823. std::string cmd = "@cd ";
  1824. cmd += this->ConvertToOutputForExisting(destination);
  1825. commands.push_back(cmd);
  1826. // Check the build system in destination directory.
  1827. commands.push_back(this->GetRecursiveMakeCall("cmake_check_build_system",
  1828. true));
  1829. // Build the targets's dependencies.
  1830. commands.push_back(this->GetRecursiveMakeCall(dep.c_str(), true));
  1831. // Build the target.
  1832. commands.push_back(this->GetRecursiveMakeCall(tgt.c_str(), true));
  1833. // Jump back to the starting directory.
  1834. cmd = "@cd ";
  1835. cmd += this->ConvertToOutputForExisting(m_Makefile->GetStartOutputDirectory());
  1836. commands.push_back(cmd);
  1837. }
  1838. else
  1839. {
  1840. // On UNIX we must construct a single shell command to jump and
  1841. // build because make resets the directory between each command.
  1842. std::string cmd = "@cd ";
  1843. cmd += this->ConvertToOutputForExisting(destination);
  1844. // Check the build system in destination directory.
  1845. cmd += " && ";
  1846. cmd += this->GetRecursiveMakeCall("cmake_check_build_system", false);
  1847. // Build the targets's dependencies.
  1848. cmd += " && ";
  1849. cmd += this->GetRecursiveMakeCall(dep.c_str(), false);
  1850. // Build the target.
  1851. cmd += " && ";
  1852. cmd += this->GetRecursiveMakeCall(tgt.c_str(), false);
  1853. // Add the command as a single line.
  1854. commands.push_back(cmd);
  1855. }
  1856. // Write the rule.
  1857. std::string jumpPreEcho = "Jumping to ";
  1858. jumpPreEcho += rt.m_BuildDirectory.c_str();
  1859. jumpPreEcho += " to build ";
  1860. jumpPreEcho += jump->first;
  1861. jumpPreEcho += "...";
  1862. std::string jumpPostEcho = "Returning to ";
  1863. jumpPostEcho += m_Makefile->GetStartOutputDirectory();
  1864. jumpPostEcho += "...";
  1865. this->WriteMakeRule(makefileStream, 0, jumpPreEcho.c_str(),
  1866. rt.m_FilePath.c_str(), depends, commands,
  1867. jumpPostEcho.c_str());
  1868. }
  1869. }
  1870. //----------------------------------------------------------------------------
  1871. bool
  1872. cmLocalUnixMakefileGenerator2
  1873. ::ScanDependencies(std::vector<std::string> const& args)
  1874. {
  1875. // Format of arguments is:
  1876. // $(CMAKE_COMMAND), cmake_depends, <lang>, <obj>, <src>, [include-flags]
  1877. // The caller has ensured that all required arguments exist.
  1878. // The file to which to write dependencies.
  1879. const char* objFile = args[3].c_str();
  1880. // The source file at which to start the scan.
  1881. const char* srcFile = args[4].c_str();
  1882. // Convert the include flags to full paths.
  1883. std::vector<std::string> includes;
  1884. for(unsigned int i=5; i < args.size(); ++i)
  1885. {
  1886. if(args[i].substr(0, 2) == "-I")
  1887. {
  1888. // Get the include path without the -I flag.
  1889. std::string inc = args[i].substr(2);
  1890. includes.push_back(cmSystemTools::CollapseFullPath(inc.c_str()));
  1891. }
  1892. }
  1893. // Dispatch the scan for each language.
  1894. std::string const& lang = args[2];
  1895. if(lang == "C" || lang == "CXX" || lang == "RC")
  1896. {
  1897. // TODO: Handle RC (resource files) dependencies correctly.
  1898. return cmLocalUnixMakefileGenerator2::ScanDependenciesC(objFile, srcFile,
  1899. includes);
  1900. }
  1901. return false;
  1902. }
  1903. //----------------------------------------------------------------------------
  1904. void
  1905. cmLocalUnixMakefileGenerator2ScanDependenciesC(
  1906. std::ifstream& fin,
  1907. std::set<cmStdString>& encountered,
  1908. std::queue<cmStdString>& unscanned)
  1909. {
  1910. // Regular expression to identify C preprocessor include directives.
  1911. cmsys::RegularExpression
  1912. includeLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
  1913. // Read one line at a time.
  1914. std::string line;
  1915. while(cmSystemTools::GetLineFromStream(fin, line))
  1916. {
  1917. // Match include directives. TODO: Support include regex and
  1918. // ignore regex. Possibly also support directory-based inclusion
  1919. // in dependencies.
  1920. if(includeLine.find(line.c_str()))
  1921. {
  1922. // Get the file being included.
  1923. std::string includeFile = includeLine.match(1);
  1924. // Queue the file if it has not yet been encountered.
  1925. if(encountered.find(includeFile) == encountered.end())
  1926. {
  1927. encountered.insert(includeFile);
  1928. unscanned.push(includeFile);
  1929. }
  1930. }
  1931. }
  1932. }
  1933. //----------------------------------------------------------------------------
  1934. bool
  1935. cmLocalUnixMakefileGenerator2
  1936. ::ScanDependenciesC(const char* objFile, const char* srcFile,
  1937. std::vector<std::string> const& includes)
  1938. {
  1939. // Walk the dependency graph starting with the source file.
  1940. std::set<cmStdString> dependencies;
  1941. std::set<cmStdString> encountered;
  1942. std::set<cmStdString> scanned;
  1943. std::queue<cmStdString> unscanned;
  1944. unscanned.push(srcFile);
  1945. encountered.insert(srcFile);
  1946. while(!unscanned.empty())
  1947. {
  1948. // Get the next file to scan.
  1949. std::string fname = unscanned.front();
  1950. unscanned.pop();
  1951. // If not a full path, find the file in the include path.
  1952. std::string fullName;
  1953. if(cmSystemTools::FileIsFullPath(fname.c_str()))
  1954. {
  1955. fullName = fname;
  1956. }
  1957. else
  1958. {
  1959. for(std::vector<std::string>::const_iterator i = includes.begin();
  1960. i != includes.end(); ++i)
  1961. {
  1962. std::string temp = *i;
  1963. temp += "/";
  1964. temp += fname;
  1965. if(cmSystemTools::FileExists(temp.c_str()))
  1966. {
  1967. fullName = temp;
  1968. break;
  1969. }
  1970. }
  1971. }
  1972. // Scan the file if it was found and has not been scanned already.
  1973. if(fullName.size() && (scanned.find(fullName) == scanned.end()))
  1974. {
  1975. // Record scanned files.
  1976. scanned.insert(fullName);
  1977. // Try to scan the file. Just leave it out if we cannot find
  1978. // it.
  1979. std::ifstream fin(fullName.c_str());
  1980. if(fin)
  1981. {
  1982. // Add this file as a dependency.
  1983. dependencies.insert(fullName);
  1984. // Scan this file for new dependencies.
  1985. cmLocalUnixMakefileGenerator2ScanDependenciesC(fin, encountered,
  1986. unscanned);
  1987. }
  1988. }
  1989. }
  1990. // Write the dependencies to the output file.
  1991. std::string depMarkFile = objFile;
  1992. std::string depMakeFile = objFile;
  1993. depMarkFile += ".depends";
  1994. depMakeFile += ".depends.make";
  1995. std::ofstream fout(depMakeFile.c_str());
  1996. fout << "# Dependencies for " << objFile << std::endl;
  1997. for(std::set<cmStdString>::iterator i=dependencies.begin();
  1998. i != dependencies.end(); ++i)
  1999. {
  2000. fout << objFile << ": "
  2001. << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
  2002. << std::endl;
  2003. }
  2004. fout << std::endl;
  2005. fout << "# Dependencies for " << depMarkFile.c_str() << std::endl;
  2006. for(std::set<cmStdString>::iterator i=dependencies.begin();
  2007. i != dependencies.end(); ++i)
  2008. {
  2009. fout << depMarkFile.c_str() << ": "
  2010. << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
  2011. << std::endl;
  2012. }
  2013. // If we could write the dependencies, touch the corresponding
  2014. // depends file to mark dependencies up to date.
  2015. if(fout)
  2016. {
  2017. std::ofstream fmark(depMarkFile.c_str());
  2018. fmark << "Dependencies updated for " << objFile << "\n";
  2019. }
  2020. return true;
  2021. }
  2022. //----------------------------------------------------------------------------
  2023. void
  2024. cmLocalUnixMakefileGenerator2
  2025. ::CheckDependencies(const char* depCheck)
  2026. {
  2027. // Get the list of files to scan. This is given through the command
  2028. // line hook cmake file.
  2029. std::vector<std::string> files;
  2030. cmSystemTools::ExpandListArgument(depCheck, files);
  2031. // Check each file. The current working directory is already
  2032. // correct.
  2033. for(std::vector<std::string>::iterator f = files.begin();
  2034. f != files.end(); ++f)
  2035. {
  2036. cmLocalUnixMakefileGenerator2::CheckDependencies(".", f->c_str());
  2037. }
  2038. }
  2039. //----------------------------------------------------------------------------
  2040. void
  2041. cmLocalUnixMakefileGenerator2
  2042. ::CheckDependencies(const char* dir, const char* file)
  2043. {
  2044. // Check the dependencies associated with the given file whose path
  2045. // is specified relative to the given directory. If any dependency
  2046. // is missing then dependencies should be regenerated.
  2047. bool regenerate = false;
  2048. // Construct the names of the mark and make files.
  2049. std::string depMarkFileFull = dir;
  2050. depMarkFileFull += "/";
  2051. depMarkFileFull += file;
  2052. depMarkFileFull += ".depends";
  2053. std::string depMakeFileFull = depMarkFileFull;
  2054. depMakeFileFull += ".make";
  2055. // Open the dependency makefile.
  2056. std::ifstream fin(depMakeFileFull.c_str());
  2057. if(fin)
  2058. {
  2059. // Parse dependencies.
  2060. std::string line;
  2061. std::string depender;
  2062. std::string dependee;
  2063. while(cmSystemTools::GetLineFromStream(fin, line))
  2064. {
  2065. // Skip empty lines and comments.
  2066. std::string::size_type pos = line.find_first_not_of(" \t\r\n");
  2067. if(pos == std::string::npos || line[pos] == '#')
  2068. {
  2069. continue;
  2070. }
  2071. // Strip leading whitespace.
  2072. if(pos > 0)
  2073. {
  2074. line = line.substr(pos);
  2075. }
  2076. // Skip lines too short to have a dependency.
  2077. if(line.size() < 3)
  2078. {
  2079. continue;
  2080. }
  2081. // Find the colon on the line. Skip the first two characters to
  2082. // avoid finding the colon in a drive letter on Windows. Ignore
  2083. // the line if a colon cannot be found.
  2084. if((pos = line.find(':', 2)) == std::string::npos)
  2085. {
  2086. continue;
  2087. }
  2088. // Split the line into depender and dependee.
  2089. depender = line.substr(0, pos);
  2090. dependee = line.substr(pos+1);
  2091. // Strip whitespace from the dependee.
  2092. if((pos = dependee.find_first_not_of(" \t\r\n")) != std::string::npos &&
  2093. pos > 0)
  2094. {
  2095. dependee = dependee.substr(pos);
  2096. }
  2097. if((pos = dependee.find_last_not_of(" \t\r\n")) != std::string::npos)
  2098. {
  2099. dependee = dependee.substr(0, pos+1);
  2100. }
  2101. // Convert dependee to a full path.
  2102. if(!cmSystemTools::FileIsFullPath(dependee.c_str()))
  2103. {
  2104. dependee = cmSystemTools::CollapseFullPath(dependee.c_str(), dir);
  2105. }
  2106. // If the dependee does not exist, we need to regenerate
  2107. // dependencies and the depender should be removed.
  2108. if(!cmSystemTools::FileExists(dependee.c_str()))
  2109. {
  2110. // Strip whitespace from the depender.
  2111. if((pos = depender.find_last_not_of(" \t\r\n")) != std::string::npos)
  2112. {
  2113. depender = depender.substr(0, pos+1);
  2114. }
  2115. // Convert depender to a full path.
  2116. if(!cmSystemTools::FileIsFullPath(depender.c_str()))
  2117. {
  2118. depender = cmSystemTools::CollapseFullPath(depender.c_str(), dir);
  2119. }
  2120. // Remove the depender.
  2121. cmSystemTools::RemoveFile(depender.c_str());
  2122. // Mark the need for regeneration.
  2123. regenerate = true;
  2124. }
  2125. }
  2126. }
  2127. else
  2128. {
  2129. // Could not open the dependencies file. It needs to be
  2130. // regenerated.
  2131. regenerate = true;
  2132. }
  2133. // If the dependencies file needs to be regenerated, create an empty
  2134. // one and delete the mark file.
  2135. if(regenerate)
  2136. {
  2137. cmLocalUnixMakefileGenerator2
  2138. ::WriteEmptyDependMakeFile(file, depMarkFileFull.c_str(),
  2139. depMakeFileFull.c_str());
  2140. }
  2141. }
  2142. //----------------------------------------------------------------------------
  2143. void
  2144. cmLocalUnixMakefileGenerator2
  2145. ::WriteEmptyDependMakeFile(const char* file,
  2146. const char* depMarkFileFull,
  2147. const char* depMakeFileFull)
  2148. {
  2149. // Remove the dependency mark file to be sure dependencies will be
  2150. // regenerated.
  2151. cmSystemTools::RemoveFile(depMarkFileFull);
  2152. // Write an empty dependency file.
  2153. std::ofstream depFileStream(depMakeFileFull);
  2154. depFileStream
  2155. << "# Empty dependencies file for " << file << ".\n"
  2156. << "# This may be replaced when dependencies are built.\n";
  2157. }