cmLocalUnixMakefileGenerator2.cxx 86 KB

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