cmLocalVisualStudio6Generator.cxx 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  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 "cmGlobalGenerator.h"
  14. #include "cmLocalVisualStudio6Generator.h"
  15. #include "cmMakefile.h"
  16. #include "cmSystemTools.h"
  17. #include "cmSourceFile.h"
  18. #include "cmCacheManager.h"
  19. cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
  20. {
  21. }
  22. cmLocalVisualStudio6Generator::~cmLocalVisualStudio6Generator()
  23. {
  24. }
  25. void cmLocalVisualStudio6Generator::Generate(bool /* fromTheTop */)
  26. {
  27. this->OutputDSPFile();
  28. }
  29. void cmLocalVisualStudio6Generator::OutputDSPFile()
  30. {
  31. // If not an in source build, then create the output directory
  32. if(strcmp(m_Makefile->GetStartOutputDirectory(),
  33. m_Makefile->GetHomeDirectory()) != 0)
  34. {
  35. if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
  36. {
  37. cmSystemTools::Error("Error creating directory ",
  38. m_Makefile->GetStartOutputDirectory());
  39. }
  40. }
  41. // Setup /I and /LIBPATH options for the resulting DSP file
  42. std::vector<std::string>& includes = m_Makefile->GetIncludeDirectories();
  43. std::vector<std::string>::iterator i;
  44. for(i = includes.begin(); i != includes.end(); ++i)
  45. {
  46. m_IncludeOptions += " /I ";
  47. std::string tmp = cmSystemTools::ConvertToOutputPath(i->c_str());
  48. // quote if not already quoted
  49. if (tmp[0] != '"')
  50. {
  51. m_IncludeOptions += "\"";
  52. m_IncludeOptions += tmp;
  53. m_IncludeOptions += "\"";
  54. }
  55. else
  56. {
  57. m_IncludeOptions += tmp;
  58. }
  59. }
  60. // Create the DSP or set of DSP's for libraries and executables
  61. // clear project names
  62. m_CreatedProjectNames.clear();
  63. // build any targets
  64. cmTargets &tgts = m_Makefile->GetTargets();
  65. for(cmTargets::iterator l = tgts.begin();
  66. l != tgts.end(); l++)
  67. {
  68. switch(l->second.GetType())
  69. {
  70. case cmTarget::STATIC_LIBRARY:
  71. this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
  72. break;
  73. case cmTarget::SHARED_LIBRARY:
  74. case cmTarget::MODULE_LIBRARY:
  75. this->SetBuildType(DLL, l->first.c_str(), l->second);
  76. break;
  77. case cmTarget::EXECUTABLE:
  78. this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
  79. break;
  80. case cmTarget::WIN32_EXECUTABLE:
  81. this->SetBuildType(WIN32_EXECUTABLE,l->first.c_str(), l->second);
  82. break;
  83. case cmTarget::UTILITY:
  84. this->SetBuildType(UTILITY, l->first.c_str(), l->second);
  85. break;
  86. case cmTarget::INSTALL_FILES:
  87. break;
  88. case cmTarget::INSTALL_PROGRAMS:
  89. break;
  90. default:
  91. cmSystemTools::Error("Bad target type", l->first.c_str());
  92. break;
  93. }
  94. // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
  95. // so don't build a projectfile for it
  96. if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  97. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
  98. && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
  99. {
  100. // check to see if the dsp is going into a sub-directory
  101. std::string::size_type pos = l->first.rfind('/');
  102. if(pos != std::string::npos)
  103. {
  104. std::string dir = m_Makefile->GetStartOutputDirectory();
  105. dir += "/";
  106. dir += l->first.substr(0, pos);
  107. if(!cmSystemTools::MakeDirectory(dir.c_str()))
  108. {
  109. cmSystemTools::Error("Error creating directory ", dir.c_str());
  110. }
  111. }
  112. this->CreateSingleDSP(l->first.c_str(),l->second);
  113. }
  114. }
  115. }
  116. void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname, cmTarget &target)
  117. {
  118. // add to the list of projects
  119. std::string pname = lname;
  120. m_CreatedProjectNames.push_back(pname);
  121. // create the dsp.cmake file
  122. std::string fname;
  123. fname = m_Makefile->GetStartOutputDirectory();
  124. fname += "/";
  125. fname += lname;
  126. fname += ".dsp";
  127. // save the name of the real dsp file
  128. std::string realDSP = fname;
  129. fname += ".cmake";
  130. std::ofstream fout(fname.c_str());
  131. if(!fout)
  132. {
  133. cmSystemTools::Error("Error Writing ", fname.c_str());
  134. }
  135. this->WriteDSPFile(fout,lname,target);
  136. fout.close();
  137. // if the dsp file has changed, then write it.
  138. cmSystemTools::CopyFileIfDifferent(fname.c_str(), realDSP.c_str());
  139. }
  140. void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmSourceGroup& sourceGroup)
  141. {
  142. std::string dspname = *(m_CreatedProjectNames.end()-1);
  143. if(dspname == "ALL_BUILD")
  144. {
  145. return;
  146. }
  147. dspname += ".dsp.cmake";
  148. std::string makefileIn = m_Makefile->GetStartDirectory();
  149. makefileIn += "/";
  150. makefileIn += "CMakeLists.txt";
  151. makefileIn = cmSystemTools::ConvertToOutputPath(makefileIn.c_str());
  152. std::string dsprule = "${CMAKE_COMMAND}";
  153. m_Makefile->ExpandVariablesInString(dsprule);
  154. dsprule = cmSystemTools::ConvertToOutputPath(dsprule.c_str());
  155. std::string args = makefileIn;
  156. args += " -H";
  157. args +=
  158. cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeDirectory());
  159. args += " -S";
  160. args +=
  161. cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartDirectory());
  162. args += " -O";
  163. args +=
  164. cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartOutputDirectory());
  165. args += " -B";
  166. args +=
  167. cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory());
  168. m_Makefile->ExpandVariablesInString(args);
  169. std::string configFile =
  170. m_Makefile->GetDefinition("CMAKE_ROOT");
  171. configFile += "/Templates/CMakeWindowsSystemConfig.cmake";
  172. std::vector<std::string> listFiles = m_Makefile->GetListFiles();
  173. bool found = false;
  174. for(std::vector<std::string>::iterator i = listFiles.begin();
  175. i != listFiles.end(); ++i)
  176. {
  177. if(*i == configFile)
  178. {
  179. found = true;
  180. }
  181. }
  182. if(!found)
  183. {
  184. listFiles.push_back(configFile);
  185. }
  186. std::vector<std::string> outputs;
  187. outputs.push_back(dspname);
  188. cmCustomCommand cc(makefileIn.c_str(), dsprule.c_str(),
  189. args.c_str(),
  190. listFiles,
  191. outputs);
  192. sourceGroup.AddCustomCommand(cc);
  193. }
  194. void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
  195. const char *libName,
  196. cmTarget &target)
  197. {
  198. // We may be modifying the source groups temporarily, so make a copy.
  199. std::vector<cmSourceGroup> sourceGroups = m_Makefile->GetSourceGroups();
  200. // get the classes from the source lists then add them to the groups
  201. std::vector<cmSourceFile*> classes = target.GetSourceFiles();
  202. for(std::vector<cmSourceFile*>::iterator i = classes.begin();
  203. i != classes.end(); i++)
  204. {
  205. // Add the file to the list of sources.
  206. std::string source = (*i)->GetFullPath();
  207. cmSourceGroup& sourceGroup = m_Makefile->FindSourceGroup(source.c_str(),
  208. sourceGroups);
  209. sourceGroup.AddSource(source.c_str(), *i);
  210. }
  211. // add any custom rules to the source groups
  212. for (std::vector<cmCustomCommand>::const_iterator cr =
  213. target.GetCustomCommands().begin();
  214. cr != target.GetCustomCommands().end(); ++cr)
  215. {
  216. cmSourceGroup& sourceGroup =
  217. m_Makefile->FindSourceGroup(cr->GetSourceName().c_str(),
  218. sourceGroups);
  219. cmCustomCommand cc(*cr);
  220. cc.ExpandVariables(*m_Makefile);
  221. sourceGroup.AddCustomCommand(cc);
  222. }
  223. // Write the DSP file's header.
  224. this->WriteDSPHeader(fout, libName, target, sourceGroups);
  225. // if we should add regen rule then...
  226. const char *suppRegenRule =
  227. m_Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
  228. // Find the group in which the CMakeLists.txt source belongs, and add
  229. // the rule to generate this DSP file.
  230. if (!cmSystemTools::IsOn(suppRegenRule))
  231. {
  232. for(std::vector<cmSourceGroup>::reverse_iterator sg = sourceGroups.rbegin();
  233. sg != sourceGroups.rend(); ++sg)
  234. {
  235. if(sg->Matches("CMakeLists.txt"))
  236. {
  237. this->AddDSPBuildRule(*sg);
  238. break;
  239. }
  240. }
  241. }
  242. // Loop through every source group.
  243. for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
  244. sg != sourceGroups.end(); ++sg)
  245. {
  246. const cmSourceGroup::BuildRules& buildRules = sg->GetBuildRules();
  247. // If the group is empty, don't write it at all.
  248. if(buildRules.empty())
  249. { continue; }
  250. // If the group has a name, write the header.
  251. std::string name = sg->GetName();
  252. if(name != "")
  253. {
  254. this->WriteDSPBeginGroup(fout, name.c_str(), "");
  255. }
  256. // Loop through each build rule in the source group.
  257. for(cmSourceGroup::BuildRules::const_iterator cc =
  258. buildRules.begin(); cc != buildRules.end(); ++ cc)
  259. {
  260. std::string source = cc->first;
  261. const cmSourceGroup::Commands& commands = cc->second.m_Commands;
  262. std::vector<std::string> depends;
  263. std::string compileFlags;
  264. if(cc->second.m_SourceFile)
  265. {
  266. // Check for extra compiler flags.
  267. const char* cflags = cc->second.m_SourceFile->GetProperty("COMPILE_FLAGS");
  268. if(cflags)
  269. {
  270. compileFlags = cflags;
  271. }
  272. if(cmSystemTools::GetFileFormat(
  273. cc->second.m_SourceFile->GetSourceExtension().c_str())
  274. == cmSystemTools::CXX_FILE_FORMAT)
  275. {
  276. // force a C++ file type
  277. compileFlags += " /TP ";
  278. }
  279. // Check for extra object-file dependencies.
  280. const char* dependsValue =
  281. cc->second.m_SourceFile->GetProperty("OBJECT_DEPENDS");
  282. if(dependsValue)
  283. {
  284. cmSystemTools::ExpandListArgument(dependsValue, depends);
  285. }
  286. }
  287. if (source != libName || target.GetType() == cmTarget::UTILITY)
  288. {
  289. fout << "# Begin Source File\n\n";
  290. // Tell MS-Dev what the source is. If the compiler knows how to
  291. // build it, then it will.
  292. fout << "SOURCE=" <<
  293. cmSystemTools::ConvertToOutputPath(source.c_str()) << "\n\n";
  294. if(!depends.empty())
  295. {
  296. // Write out the dependencies for the rule.
  297. fout << "USERDEP__HACK=";
  298. for(std::vector<std::string>::const_iterator d = depends.begin();
  299. d != depends.end(); ++d)
  300. {
  301. fout << "\\\n\t" <<
  302. cmSystemTools::ConvertToOutputPath(d->c_str());
  303. }
  304. fout << "\n";
  305. }
  306. if (!commands.empty())
  307. {
  308. cmSourceGroup::CommandFiles totalCommand;
  309. std::string totalCommandStr;
  310. totalCommandStr = this->CombineCommands(commands, totalCommand,
  311. source.c_str());
  312. const char* comment = totalCommand.m_Comment.c_str();
  313. const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
  314. this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(),
  315. (*comment?comment:"Custom Rule"),
  316. totalCommand.m_Depends,
  317. totalCommand.m_Outputs, flags);
  318. }
  319. else if(compileFlags.size())
  320. {
  321. for(std::vector<std::string>::iterator i
  322. = m_Configurations.begin(); i != m_Configurations.end(); ++i)
  323. {
  324. if (i == m_Configurations.begin())
  325. {
  326. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  327. }
  328. else
  329. {
  330. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  331. }
  332. fout << "\n# ADD CPP " << compileFlags << "\n\n";
  333. }
  334. fout << "!ENDIF\n\n";
  335. }
  336. fout << "# End Source File\n";
  337. }
  338. }
  339. // If the group has a name, write the footer.
  340. if(name != "")
  341. {
  342. this->WriteDSPEndGroup(fout);
  343. }
  344. }
  345. // Write the DSP file's footer.
  346. this->WriteDSPFooter(fout);
  347. }
  348. void cmLocalVisualStudio6Generator::WriteCustomRule(std::ostream& fout,
  349. const char* source,
  350. const char* command,
  351. const char* comment,
  352. const std::set<std::string>& depends,
  353. const std::set<std::string>& outputs,
  354. const char* flags
  355. )
  356. {
  357. std::vector<std::string>::iterator i;
  358. for(i = m_Configurations.begin(); i != m_Configurations.end(); ++i)
  359. {
  360. if (i == m_Configurations.begin())
  361. {
  362. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  363. }
  364. else
  365. {
  366. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  367. }
  368. if(flags)
  369. {
  370. fout << "\n# ADD CPP " << flags << "\n\n";
  371. }
  372. // Write out the dependencies for the rule.
  373. fout << "USERDEP__HACK=";
  374. for(std::set<std::string>::const_iterator d = depends.begin();
  375. d != depends.end(); ++d)
  376. {
  377. fout << "\\\n\t" <<
  378. cmSystemTools::ConvertToOutputPath(d->c_str());
  379. }
  380. fout << "\n";
  381. fout << "# PROP Ignore_Default_Tool 1\n";
  382. fout << "# Begin Custom Build - Building " << comment
  383. << " $(InputPath)\n\n";
  384. if(outputs.size() == 0)
  385. {
  386. fout << source << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
  387. fout << command << "\n\n";
  388. }
  389. // Write a rule for every output generated by this command.
  390. for(std::set<std::string>::const_iterator output = outputs.begin();
  391. output != outputs.end(); ++output)
  392. {
  393. fout << cmSystemTools::ConvertToOutputPath(output->c_str())
  394. << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
  395. fout << command << "\n\n";
  396. }
  397. fout << "# End Custom Build\n\n";
  398. }
  399. fout << "!ENDIF\n\n";
  400. }
  401. void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout,
  402. const char* group,
  403. const char* filter)
  404. {
  405. fout << "# Begin Group \"" << group << "\"\n"
  406. "# PROP Default_Filter \"" << filter << "\"\n";
  407. }
  408. void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
  409. {
  410. fout << "# End Group\n";
  411. }
  412. void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
  413. const char* libName,
  414. const cmTarget& target)
  415. {
  416. std::string root= m_Makefile->GetDefinition("CMAKE_ROOT");
  417. const char *def= m_Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
  418. std::string exportSymbol;
  419. if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
  420. {
  421. exportSymbol = custom_export_name;
  422. }
  423. else
  424. {
  425. std::string in = libName;
  426. in += "_EXPORTS";
  427. exportSymbol = cmSystemTools::MakeCindentifier(in.c_str());
  428. }
  429. if( def)
  430. {
  431. root = def;
  432. }
  433. else
  434. {
  435. root += "/Templates";
  436. }
  437. switch(b)
  438. {
  439. case STATIC_LIBRARY:
  440. m_DSPHeaderTemplate = root;
  441. m_DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
  442. m_DSPFooterTemplate = root;
  443. m_DSPFooterTemplate += "/staticLibFooter.dsptemplate";
  444. break;
  445. case DLL:
  446. m_DSPHeaderTemplate = root;
  447. m_DSPHeaderTemplate += "/DLLHeader.dsptemplate";
  448. m_DSPFooterTemplate = root;
  449. m_DSPFooterTemplate += "/DLLFooter.dsptemplate";
  450. break;
  451. case EXECUTABLE:
  452. m_DSPHeaderTemplate = root;
  453. m_DSPHeaderTemplate += "/EXEHeader.dsptemplate";
  454. m_DSPFooterTemplate = root;
  455. m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
  456. break;
  457. case WIN32_EXECUTABLE:
  458. m_DSPHeaderTemplate = root;
  459. m_DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
  460. m_DSPFooterTemplate = root;
  461. m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
  462. break;
  463. case UTILITY:
  464. m_DSPHeaderTemplate = root;
  465. m_DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
  466. m_DSPFooterTemplate = root;
  467. m_DSPFooterTemplate += "/UtilityFooter.dsptemplate";
  468. break;
  469. }
  470. // once the build type is set, determine what configurations are
  471. // possible
  472. std::ifstream fin(m_DSPHeaderTemplate.c_str());
  473. cmRegularExpression reg("# Name ");
  474. if(!fin)
  475. {
  476. cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
  477. }
  478. // reset m_Configurations
  479. m_Configurations.erase(m_Configurations.begin(), m_Configurations.end());
  480. // now add all the configurations possible
  481. char buffer[2048];
  482. std::string line;
  483. while(cmSystemTools::GetLineFromStream(fin, line))
  484. {
  485. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
  486. exportSymbol.c_str());
  487. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  488. if (reg.find(line))
  489. {
  490. m_Configurations.push_back(line.substr(reg.end()));
  491. }
  492. }
  493. }
  494. std::string
  495. cmLocalVisualStudio6Generator::CombineCommands(const cmSourceGroup::Commands &commands,
  496. cmSourceGroup::CommandFiles &totalCommand,
  497. const char *source)
  498. {
  499. // Loop through every custom command generating code from the
  500. // current source.
  501. // build up the depends and outputs and commands
  502. std::string totalCommandStr = "";
  503. std::string temp;
  504. for(cmSourceGroup::Commands::const_iterator c = commands.begin();
  505. c != commands.end(); ++c)
  506. {
  507. totalCommandStr += "\n\t";
  508. temp= c->second.m_Command;
  509. temp = cmSystemTools::ConvertToOutputPath(temp.c_str());
  510. totalCommandStr += temp;
  511. totalCommandStr += " ";
  512. totalCommandStr += c->second.m_Arguments;
  513. totalCommand.Merge(c->second);
  514. totalCommand.m_Comment = c->second.m_Comment.c_str();
  515. }
  516. // Create a dummy file with the name of the source if it does
  517. // not exist
  518. if(totalCommand.m_Outputs.empty())
  519. {
  520. std::string dummyFile = m_Makefile->GetStartOutputDirectory();
  521. dummyFile += "/";
  522. dummyFile += source;
  523. if(!cmSystemTools::FileExists(dummyFile.c_str()))
  524. {
  525. std::ofstream fout(dummyFile.c_str());
  526. fout << "Dummy file created by cmake as unused source for utility command.\n";
  527. }
  528. }
  529. return totalCommandStr;
  530. }
  531. // look for custom rules on a target and collect them together
  532. std::string
  533. cmLocalVisualStudio6Generator::CreateTargetRules(const cmTarget &target,
  534. const char *libName)
  535. {
  536. std::string customRuleCode = "";
  537. if (target.GetType() >= cmTarget::UTILITY)
  538. {
  539. return customRuleCode;
  540. }
  541. // Find the group in which the lix exe custom rules belong
  542. bool init = false;
  543. for (std::vector<cmCustomCommand>::const_iterator cr =
  544. target.GetCustomCommands().begin();
  545. cr != target.GetCustomCommands().end(); ++cr)
  546. {
  547. cmCustomCommand cc(*cr);
  548. cc.ExpandVariables(*m_Makefile);
  549. if (cc.GetSourceName() == libName)
  550. {
  551. if (!init)
  552. {
  553. // header stuff
  554. customRuleCode = "# Begin Special Build Tool\nPostBuild_Cmds=";
  555. init = true;
  556. }
  557. else
  558. {
  559. customRuleCode += "\t";
  560. }
  561. customRuleCode += cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) + " " + cc.GetArguments();
  562. }
  563. }
  564. if (init)
  565. {
  566. customRuleCode += "\n# End Special Build Tool\n";
  567. }
  568. return customRuleCode;
  569. }
  570. inline std::string removeQuotes(const std::string& s)
  571. {
  572. if(s[0] == '\"' && s[s.size()-1] == '\"')
  573. {
  574. return s.substr(1, s.size()-2);
  575. }
  576. return s;
  577. }
  578. void cmLocalVisualStudio6Generator::WriteDSPHeader(std::ostream& fout, const char *libName,
  579. const cmTarget &target,
  580. std::vector<cmSourceGroup> &)
  581. {
  582. std::set<std::string> pathEmitted;
  583. // determine the link directories
  584. std::string libOptions;
  585. std::string libDebugOptions;
  586. std::string libOptimizedOptions;
  587. std::string libMultiLineOptions;
  588. std::string libMultiLineDebugOptions;
  589. std::string libMultiLineOptimizedOptions;
  590. // suppoirt override in output directory
  591. std::string libPath = "";
  592. if (m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
  593. {
  594. libPath = m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
  595. }
  596. std::string exePath = "";
  597. if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
  598. {
  599. exePath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  600. }
  601. if(libPath.size())
  602. {
  603. // make sure there is a trailing slash
  604. if(libPath[libPath.size()-1] != '/')
  605. {
  606. libPath += "/";
  607. }
  608. std::string lpath =
  609. cmSystemTools::ConvertToOutputPath(libPath.c_str());
  610. std::string lpathIntDir = libPath + "$(INTDIR)";
  611. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  612. if(pathEmitted.insert(lpath).second)
  613. {
  614. libOptions += " /LIBPATH:";
  615. libOptions += lpathIntDir;
  616. libOptions += " ";
  617. libOptions += " /LIBPATH:";
  618. libOptions += lpath;
  619. libOptions += " ";
  620. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  621. libMultiLineOptions += lpathIntDir;
  622. libMultiLineOptions += " ";
  623. libMultiLineOptions += " /LIBPATH:";
  624. libMultiLineOptions += lpath;
  625. libMultiLineOptions += " \n";
  626. }
  627. }
  628. if(exePath.size())
  629. {
  630. // make sure there is a trailing slash
  631. if(exePath[exePath.size()-1] != '/')
  632. {
  633. exePath += "/";
  634. }
  635. std::string lpath =
  636. cmSystemTools::ConvertToOutputPath(exePath.c_str());
  637. std::string lpathIntDir = exePath + "$(INTDIR)";
  638. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  639. if(pathEmitted.insert(lpath).second)
  640. {
  641. libOptions += " /LIBPATH:";
  642. libOptions += lpathIntDir;
  643. libOptions += " ";
  644. libOptions += " /LIBPATH:";
  645. libOptions += lpath;
  646. libOptions += " ";
  647. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  648. libMultiLineOptions += lpathIntDir;
  649. libMultiLineOptions += " ";
  650. libMultiLineOptions += " /LIBPATH:";
  651. libMultiLineOptions += lpath;
  652. libMultiLineOptions += " \n";
  653. }
  654. }
  655. std::vector<std::string>::const_iterator i;
  656. const std::vector<std::string>& libdirs = target.GetLinkDirectories();
  657. for(i = libdirs.begin(); i != libdirs.end(); ++i)
  658. {
  659. std::string path = *i;
  660. if(path[path.size()-1] != '/')
  661. {
  662. path += "/";
  663. }
  664. std::string lpath =
  665. cmSystemTools::ConvertToOutputPath(path.c_str());
  666. std::string lpathIntDir = path + "$(INTDIR)";
  667. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  668. if(pathEmitted.insert(lpath).second)
  669. {
  670. libOptions += " /LIBPATH:";
  671. libOptions += lpathIntDir;
  672. libOptions += " ";
  673. libOptions += " /LIBPATH:";
  674. libOptions += lpath;
  675. libOptions += " ";
  676. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  677. libMultiLineOptions += lpathIntDir;
  678. libMultiLineOptions += " ";
  679. libMultiLineOptions += " /LIBPATH:";
  680. libMultiLineOptions += lpath;
  681. libMultiLineOptions += " \n";
  682. }
  683. }
  684. // find link libraries
  685. const cmTarget::LinkLibraries& libs = target.GetLinkLibraries();
  686. cmTarget::LinkLibraries::const_iterator j;
  687. for(j = libs.begin(); j != libs.end(); ++j)
  688. {
  689. // add libraries to executables and dlls (but never include
  690. // a library in a library, bad recursion)
  691. if ((target.GetType() != cmTarget::SHARED_LIBRARY
  692. && target.GetType() != cmTarget::STATIC_LIBRARY
  693. && target.GetType() != cmTarget::MODULE_LIBRARY) ||
  694. (target.GetType()==cmTarget::SHARED_LIBRARY && libName != j->first) ||
  695. (target.GetType()==cmTarget::MODULE_LIBRARY && libName != j->first))
  696. {
  697. std::string lib = j->first;
  698. if(j->first.find(".lib") == std::string::npos)
  699. {
  700. lib += ".lib";
  701. }
  702. lib = cmSystemTools::ConvertToOutputPath(lib.c_str());
  703. if (j->second == cmTarget::GENERAL)
  704. {
  705. libOptions += " ";
  706. libOptions += lib;
  707. libMultiLineOptions += "# ADD LINK32 ";
  708. libMultiLineOptions += lib;
  709. libMultiLineOptions += "\n";
  710. }
  711. if (j->second == cmTarget::DEBUG)
  712. {
  713. libDebugOptions += " ";
  714. libDebugOptions += lib;
  715. libMultiLineDebugOptions += "# ADD LINK32 ";
  716. libMultiLineDebugOptions += lib;
  717. libMultiLineDebugOptions += "\n";
  718. }
  719. if (j->second == cmTarget::OPTIMIZED)
  720. {
  721. libOptimizedOptions += " ";
  722. libOptimizedOptions += lib;
  723. libMultiLineOptimizedOptions += "# ADD LINK32 ";
  724. libMultiLineOptimizedOptions += lib;
  725. libMultiLineOptimizedOptions += "\n";
  726. }
  727. }
  728. }
  729. std::string extraLinkOptions;
  730. if(target.GetType() == cmTarget::EXECUTABLE)
  731. {
  732. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
  733. }
  734. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  735. {
  736. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_SHARED_LINKER_FLAGS");
  737. }
  738. if(extraLinkOptions.size())
  739. {
  740. libOptions += " ";
  741. libOptions += extraLinkOptions;
  742. libOptions += " ";
  743. libMultiLineOptions += "# ADD LINK32 ";
  744. libMultiLineOptions += extraLinkOptions;
  745. libMultiLineOptions += " \n";
  746. }
  747. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
  748. {
  749. libOptions += " ";
  750. libOptions += targetLinkFlags;
  751. libOptions += " ";
  752. libMultiLineOptions += "# ADD LINK32 ";
  753. libMultiLineOptions += targetLinkFlags;
  754. libMultiLineOptions += " \n";
  755. }
  756. // are there any custom rules on the target itself
  757. // only if the target is a lib or exe
  758. std::string customRuleCode = this->CreateTargetRules(target, libName);
  759. std::ifstream fin(m_DSPHeaderTemplate.c_str());
  760. if(!fin)
  761. {
  762. cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
  763. }
  764. char buffer[2048];
  765. std::string line;
  766. while(cmSystemTools::GetLineFromStream(fin, line))
  767. {
  768. const char* mfcFlag = m_Makefile->GetDefinition("CMAKE_MFC_FLAG");
  769. if(!mfcFlag)
  770. {
  771. mfcFlag = "0";
  772. }
  773. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
  774. customRuleCode.c_str());
  775. cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
  776. mfcFlag);
  777. cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
  778. libOptions.c_str());
  779. cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
  780. libDebugOptions.c_str());
  781. cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
  782. libOptimizedOptions.c_str());
  783. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
  784. libMultiLineOptions.c_str());
  785. cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
  786. libMultiLineDebugOptions.c_str());
  787. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
  788. libMultiLineOptimizedOptions.c_str());
  789. cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
  790. m_IncludeOptions.c_str());
  791. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  792. // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
  793. // are already quoted in the template file,
  794. // we need to remove the quotes here, we still need
  795. // to convert to output path for unix to win32 conversion
  796. cmSystemTools::ReplaceString(line, "LIBRARY_OUTPUT_PATH",
  797. removeQuotes(
  798. cmSystemTools::ConvertToOutputPath(libPath.c_str())).c_str());
  799. cmSystemTools::ReplaceString(line, "EXECUTABLE_OUTPUT_PATH",
  800. removeQuotes(
  801. cmSystemTools::ConvertToOutputPath(exePath.c_str())).c_str());
  802. cmSystemTools::ReplaceString(line,
  803. "EXTRA_DEFINES",
  804. m_Makefile->GetDefineFlags());
  805. cmGlobalGenerator* gen = this->GetGlobalGenerator();
  806. // store flags for each configuration
  807. std::string flags = " ";
  808. std::string flagsRelease = " ";
  809. std::string flagsMinSize = " ";
  810. std::string flagsDebug = " ";
  811. std::string flagsDebugRel = " ";
  812. // if CXX is on and the target contains cxx code then add the cxx flags
  813. if ( gen->GetLanguageEnabled("CXX") && target.HasCxx() )
  814. {
  815. flagsRelease = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELEASE");
  816. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
  817. flagsMinSize = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_MINSIZEREL");
  818. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
  819. flagsDebug = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_DEBUG");
  820. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
  821. flagsDebugRel = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELWITHDEBINFO");
  822. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
  823. flags = " ";
  824. flags = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS");
  825. }
  826. // if C and the target is not CXX
  827. else if(gen->GetLanguageEnabled("C") && !target.HasCxx())
  828. {
  829. flagsRelease += m_Makefile->GetDefinition("CMAKE_C_FLAGS_RELEASE");
  830. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\"";
  831. flagsMinSize += m_Makefile->GetDefinition("CMAKE_C_FLAGS_MINSIZEREL");
  832. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\"";
  833. flagsDebug += m_Makefile->GetDefinition("CMAKE_C_FLAGS_DEBUG");
  834. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\"";
  835. flagsDebugRel += m_Makefile->GetDefinition("CMAKE_C_FLAGS_RELWITHDEBINFO");
  836. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\"";
  837. flags = " ";
  838. flags = m_Makefile->GetDefinition("CMAKE_C_FLAGS");
  839. }
  840. // The template files have CXX FLAGS in them, that need to be replaced.
  841. // There are not separate CXX and C template files, so we use the same
  842. // variable names. The previous code sets up flags* variables to contain
  843. // the correct C or CXX flags
  844. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str());
  845. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", flagsMinSize.c_str());
  846. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str());
  847. cmSystemTools::ReplaceString(line,"CMAKE_CXX_FLAGS_RELWITHDEBINFO", flagsDebugRel.c_str());
  848. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
  849. fout << line.c_str() << std::endl;
  850. }
  851. }
  852. void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
  853. {
  854. std::ifstream fin(m_DSPFooterTemplate.c_str());
  855. if(!fin)
  856. {
  857. cmSystemTools::Error("Error Reading ",
  858. m_DSPFooterTemplate.c_str());
  859. }
  860. std::string line;
  861. while(cmSystemTools::GetLineFromStream(fin, line))
  862. {
  863. fout << line << std::endl;
  864. }
  865. }