cmLocalUnixMakefileGenerator2.cxx 89 KB

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