cmLocalVisualStudio6Generator.cxx 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  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. const char* compileFlags = 0;
  264. if(cc->second.m_SourceFile)
  265. {
  266. // Check for extra compiler flags.
  267. compileFlags = cc->second.m_SourceFile->GetProperty("COMPILE_FLAGS");
  268. // Check for extra object-file dependencies.
  269. const char* dependsValue =
  270. cc->second.m_SourceFile->GetProperty("OBJECT_DEPENDS");
  271. if(dependsValue)
  272. {
  273. cmSystemTools::ExpandListArgument(dependsValue, depends);
  274. }
  275. }
  276. if (source != libName || target.GetType() == cmTarget::UTILITY)
  277. {
  278. fout << "# Begin Source File\n\n";
  279. // Tell MS-Dev what the source is. If the compiler knows how to
  280. // build it, then it will.
  281. fout << "SOURCE=" <<
  282. cmSystemTools::ConvertToOutputPath(source.c_str()) << "\n\n";
  283. if(!depends.empty())
  284. {
  285. // Write out the dependencies for the rule.
  286. fout << "USERDEP__HACK=";
  287. for(std::vector<std::string>::const_iterator d = depends.begin();
  288. d != depends.end(); ++d)
  289. {
  290. fout << "\\\n\t" <<
  291. cmSystemTools::ConvertToOutputPath(d->c_str());
  292. }
  293. fout << "\n";
  294. }
  295. if (!commands.empty())
  296. {
  297. cmSourceGroup::CommandFiles totalCommand;
  298. std::string totalCommandStr;
  299. totalCommandStr = this->CombineCommands(commands, totalCommand,
  300. source.c_str());
  301. const char* comment = totalCommand.m_Comment.c_str();
  302. this->WriteCustomRule(fout, source.c_str(), totalCommandStr.c_str(),
  303. (*comment?comment:"Custom Rule"),
  304. totalCommand.m_Depends,
  305. totalCommand.m_Outputs, compileFlags);
  306. }
  307. else if(compileFlags)
  308. {
  309. for(std::vector<std::string>::iterator i
  310. = m_Configurations.begin(); i != m_Configurations.end(); ++i)
  311. {
  312. if (i == m_Configurations.begin())
  313. {
  314. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  315. }
  316. else
  317. {
  318. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  319. }
  320. fout << "\n# ADD CPP " << compileFlags << "\n\n";
  321. }
  322. fout << "!ENDIF\n\n";
  323. }
  324. fout << "# End Source File\n";
  325. }
  326. }
  327. // If the group has a name, write the footer.
  328. if(name != "")
  329. {
  330. this->WriteDSPEndGroup(fout);
  331. }
  332. }
  333. // Write the DSP file's footer.
  334. this->WriteDSPFooter(fout);
  335. }
  336. void cmLocalVisualStudio6Generator::WriteCustomRule(std::ostream& fout,
  337. const char* source,
  338. const char* command,
  339. const char* comment,
  340. const std::set<std::string>& depends,
  341. const std::set<std::string>& outputs,
  342. const char* flags
  343. )
  344. {
  345. std::vector<std::string>::iterator i;
  346. for(i = m_Configurations.begin(); i != m_Configurations.end(); ++i)
  347. {
  348. if (i == m_Configurations.begin())
  349. {
  350. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  351. }
  352. else
  353. {
  354. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  355. }
  356. if(flags)
  357. {
  358. fout << "\n# ADD CPP " << flags << "\n\n";
  359. }
  360. // Write out the dependencies for the rule.
  361. fout << "USERDEP__HACK=";
  362. for(std::set<std::string>::const_iterator d = depends.begin();
  363. d != depends.end(); ++d)
  364. {
  365. fout << "\\\n\t" <<
  366. cmSystemTools::ConvertToOutputPath(d->c_str());
  367. }
  368. fout << "\n";
  369. fout << "# PROP Ignore_Default_Tool 1\n";
  370. fout << "# Begin Custom Build - Building " << comment
  371. << " $(InputPath)\n\n";
  372. if(outputs.size() == 0)
  373. {
  374. fout << source << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
  375. fout << command << "\n\n";
  376. }
  377. // Write a rule for every output generated by this command.
  378. for(std::set<std::string>::const_iterator output = outputs.begin();
  379. output != outputs.end(); ++output)
  380. {
  381. fout << cmSystemTools::ConvertToOutputPath(output->c_str())
  382. << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"";
  383. fout << command << "\n\n";
  384. }
  385. fout << "# End Custom Build\n\n";
  386. }
  387. fout << "!ENDIF\n\n";
  388. }
  389. void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout,
  390. const char* group,
  391. const char* filter)
  392. {
  393. fout << "# Begin Group \"" << group << "\"\n"
  394. "# PROP Default_Filter \"" << filter << "\"\n";
  395. }
  396. void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
  397. {
  398. fout << "# End Group\n";
  399. }
  400. void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
  401. const char* libName,
  402. const cmTarget& target)
  403. {
  404. std::string root= m_Makefile->GetDefinition("CMAKE_ROOT");
  405. const char *def= m_Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
  406. std::string exportSymbol;
  407. if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
  408. {
  409. exportSymbol = custom_export_name;
  410. }
  411. else
  412. {
  413. std::string in = libName;
  414. in += "_EXPORTS";
  415. exportSymbol = cmSystemTools::MakeCindentifier(in.c_str());
  416. }
  417. if( def)
  418. {
  419. root = def;
  420. }
  421. else
  422. {
  423. root += "/Templates";
  424. }
  425. switch(b)
  426. {
  427. case STATIC_LIBRARY:
  428. m_DSPHeaderTemplate = root;
  429. m_DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
  430. m_DSPFooterTemplate = root;
  431. m_DSPFooterTemplate += "/staticLibFooter.dsptemplate";
  432. break;
  433. case DLL:
  434. m_DSPHeaderTemplate = root;
  435. m_DSPHeaderTemplate += "/DLLHeader.dsptemplate";
  436. m_DSPFooterTemplate = root;
  437. m_DSPFooterTemplate += "/DLLFooter.dsptemplate";
  438. break;
  439. case EXECUTABLE:
  440. m_DSPHeaderTemplate = root;
  441. m_DSPHeaderTemplate += "/EXEHeader.dsptemplate";
  442. m_DSPFooterTemplate = root;
  443. m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
  444. break;
  445. case WIN32_EXECUTABLE:
  446. m_DSPHeaderTemplate = root;
  447. m_DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
  448. m_DSPFooterTemplate = root;
  449. m_DSPFooterTemplate += "/EXEFooter.dsptemplate";
  450. break;
  451. case UTILITY:
  452. m_DSPHeaderTemplate = root;
  453. m_DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
  454. m_DSPFooterTemplate = root;
  455. m_DSPFooterTemplate += "/UtilityFooter.dsptemplate";
  456. break;
  457. }
  458. // once the build type is set, determine what configurations are
  459. // possible
  460. std::ifstream fin(m_DSPHeaderTemplate.c_str());
  461. cmRegularExpression reg("# Name ");
  462. if(!fin)
  463. {
  464. cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
  465. }
  466. // reset m_Configurations
  467. m_Configurations.erase(m_Configurations.begin(), m_Configurations.end());
  468. // now add all the configurations possible
  469. char buffer[2048];
  470. while(fin)
  471. {
  472. fin.getline(buffer, 2048);
  473. std::string line = buffer;
  474. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
  475. exportSymbol.c_str());
  476. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  477. if (reg.find(line))
  478. {
  479. m_Configurations.push_back(line.substr(reg.end()));
  480. }
  481. }
  482. }
  483. std::string
  484. cmLocalVisualStudio6Generator::CombineCommands(const cmSourceGroup::Commands &commands,
  485. cmSourceGroup::CommandFiles &totalCommand,
  486. const char *source)
  487. {
  488. // Loop through every custom command generating code from the
  489. // current source.
  490. // build up the depends and outputs and commands
  491. std::string totalCommandStr = "";
  492. std::string temp;
  493. for(cmSourceGroup::Commands::const_iterator c = commands.begin();
  494. c != commands.end(); ++c)
  495. {
  496. totalCommandStr += "\n\t";
  497. temp= c->second.m_Command;
  498. temp = cmSystemTools::ConvertToOutputPath(temp.c_str());
  499. totalCommandStr += temp;
  500. totalCommandStr += " ";
  501. totalCommandStr += c->second.m_Arguments;
  502. totalCommand.Merge(c->second);
  503. totalCommand.m_Comment = c->second.m_Comment.c_str();
  504. }
  505. // Create a dummy file with the name of the source if it does
  506. // not exist
  507. if(totalCommand.m_Outputs.empty())
  508. {
  509. std::string dummyFile = m_Makefile->GetStartOutputDirectory();
  510. dummyFile += "/";
  511. dummyFile += source;
  512. if(!cmSystemTools::FileExists(dummyFile.c_str()))
  513. {
  514. std::ofstream fout(dummyFile.c_str());
  515. fout << "Dummy file created by cmake as unused source for utility command.\n";
  516. }
  517. }
  518. return totalCommandStr;
  519. }
  520. // look for custom rules on a target and collect them together
  521. std::string
  522. cmLocalVisualStudio6Generator::CreateTargetRules(const cmTarget &target,
  523. const char *libName)
  524. {
  525. std::string customRuleCode = "";
  526. if (target.GetType() >= cmTarget::UTILITY)
  527. {
  528. return customRuleCode;
  529. }
  530. // Find the group in which the lix exe custom rules belong
  531. bool init = false;
  532. for (std::vector<cmCustomCommand>::const_iterator cr =
  533. target.GetCustomCommands().begin();
  534. cr != target.GetCustomCommands().end(); ++cr)
  535. {
  536. cmCustomCommand cc(*cr);
  537. cc.ExpandVariables(*m_Makefile);
  538. if (cc.GetSourceName() == libName)
  539. {
  540. if (!init)
  541. {
  542. // header stuff
  543. customRuleCode = "# Begin Special Build Tool\nPostBuild_Cmds=";
  544. init = true;
  545. }
  546. else
  547. {
  548. customRuleCode += "\t";
  549. }
  550. customRuleCode += cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()) + " " + cc.GetArguments();
  551. }
  552. }
  553. if (init)
  554. {
  555. customRuleCode += "\n# End Special Build Tool\n";
  556. }
  557. return customRuleCode;
  558. }
  559. inline std::string removeQuotes(const std::string& s)
  560. {
  561. if(s[0] == '\"' && s[s.size()-1] == '\"')
  562. {
  563. return s.substr(1, s.size()-2);
  564. }
  565. return s;
  566. }
  567. void cmLocalVisualStudio6Generator::WriteDSPHeader(std::ostream& fout, const char *libName,
  568. const cmTarget &target,
  569. std::vector<cmSourceGroup> &)
  570. {
  571. std::set<std::string> pathEmitted;
  572. // determine the link directories
  573. std::string libOptions;
  574. std::string libDebugOptions;
  575. std::string libOptimizedOptions;
  576. std::string libMultiLineOptions;
  577. std::string libMultiLineDebugOptions;
  578. std::string libMultiLineOptimizedOptions;
  579. // suppoirt override in output directory
  580. std::string libPath = "";
  581. if (m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
  582. {
  583. libPath = m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
  584. }
  585. std::string exePath = "";
  586. if (m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
  587. {
  588. exePath = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  589. }
  590. if(libPath.size())
  591. {
  592. // make sure there is a trailing slash
  593. if(libPath[libPath.size()-1] != '/')
  594. {
  595. libPath += "/";
  596. }
  597. std::string lpath =
  598. cmSystemTools::ConvertToOutputPath(libPath.c_str());
  599. std::string lpathIntDir = libPath + "$(INTDIR)";
  600. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  601. if(pathEmitted.insert(lpath).second)
  602. {
  603. libOptions += " /LIBPATH:";
  604. libOptions += lpathIntDir;
  605. libOptions += " ";
  606. libOptions += " /LIBPATH:";
  607. libOptions += lpath;
  608. libOptions += " ";
  609. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  610. libMultiLineOptions += lpathIntDir;
  611. libMultiLineOptions += " ";
  612. libMultiLineOptions += " /LIBPATH:";
  613. libMultiLineOptions += lpath;
  614. libMultiLineOptions += " \n";
  615. }
  616. }
  617. if(exePath.size())
  618. {
  619. // make sure there is a trailing slash
  620. if(exePath[exePath.size()-1] != '/')
  621. {
  622. exePath += "/";
  623. }
  624. std::string lpath =
  625. cmSystemTools::ConvertToOutputPath(exePath.c_str());
  626. std::string lpathIntDir = exePath + "$(INTDIR)";
  627. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  628. if(pathEmitted.insert(lpath).second)
  629. {
  630. libOptions += " /LIBPATH:";
  631. libOptions += lpathIntDir;
  632. libOptions += " ";
  633. libOptions += " /LIBPATH:";
  634. libOptions += lpath;
  635. libOptions += " ";
  636. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  637. libMultiLineOptions += lpathIntDir;
  638. libMultiLineOptions += " ";
  639. libMultiLineOptions += " /LIBPATH:";
  640. libMultiLineOptions += lpath;
  641. libMultiLineOptions += " \n";
  642. }
  643. }
  644. std::vector<std::string>::const_iterator i;
  645. const std::vector<std::string>& libdirs = target.GetLinkDirectories();
  646. for(i = libdirs.begin(); i != libdirs.end(); ++i)
  647. {
  648. std::string path = *i;
  649. if(path[path.size()-1] != '/')
  650. {
  651. path += "/";
  652. }
  653. std::string lpath =
  654. cmSystemTools::ConvertToOutputPath(path.c_str());
  655. std::string lpathIntDir = path + "$(INTDIR)";
  656. lpathIntDir = cmSystemTools::ConvertToOutputPath(lpathIntDir.c_str());
  657. if(pathEmitted.insert(lpath).second)
  658. {
  659. libOptions += " /LIBPATH:";
  660. libOptions += lpathIntDir;
  661. libOptions += " ";
  662. libOptions += " /LIBPATH:";
  663. libOptions += lpath;
  664. libOptions += " ";
  665. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  666. libMultiLineOptions += lpathIntDir;
  667. libMultiLineOptions += " ";
  668. libMultiLineOptions += " /LIBPATH:";
  669. libMultiLineOptions += lpath;
  670. libMultiLineOptions += " \n";
  671. }
  672. }
  673. // find link libraries
  674. const cmTarget::LinkLibraries& libs = target.GetLinkLibraries();
  675. cmTarget::LinkLibraries::const_iterator j;
  676. for(j = libs.begin(); j != libs.end(); ++j)
  677. {
  678. // add libraries to executables and dlls (but never include
  679. // a library in a library, bad recursion)
  680. if ((target.GetType() != cmTarget::SHARED_LIBRARY
  681. && target.GetType() != cmTarget::STATIC_LIBRARY
  682. && target.GetType() != cmTarget::MODULE_LIBRARY) ||
  683. (target.GetType()==cmTarget::SHARED_LIBRARY && libName != j->first) ||
  684. (target.GetType()==cmTarget::MODULE_LIBRARY && libName != j->first))
  685. {
  686. std::string lib = j->first;
  687. if(j->first.find(".lib") == std::string::npos)
  688. {
  689. lib += ".lib";
  690. }
  691. lib = cmSystemTools::ConvertToOutputPath(lib.c_str());
  692. if (j->second == cmTarget::GENERAL)
  693. {
  694. libOptions += " ";
  695. libOptions += lib;
  696. libMultiLineOptions += "# ADD LINK32 ";
  697. libMultiLineOptions += lib;
  698. libMultiLineOptions += "\n";
  699. }
  700. if (j->second == cmTarget::DEBUG)
  701. {
  702. libDebugOptions += " ";
  703. libDebugOptions += lib;
  704. libMultiLineDebugOptions += "# ADD LINK32 ";
  705. libMultiLineDebugOptions += lib;
  706. libMultiLineDebugOptions += "\n";
  707. }
  708. if (j->second == cmTarget::OPTIMIZED)
  709. {
  710. libOptimizedOptions += " ";
  711. libOptimizedOptions += lib;
  712. libMultiLineOptimizedOptions += "# ADD LINK32 ";
  713. libMultiLineOptimizedOptions += lib;
  714. libMultiLineOptimizedOptions += "\n";
  715. }
  716. }
  717. }
  718. std::string extraLinkOptions;
  719. if(target.GetType() == cmTarget::EXECUTABLE)
  720. {
  721. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
  722. }
  723. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  724. {
  725. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_SHARED_LINKER_FLAGS");
  726. }
  727. if(extraLinkOptions.size())
  728. {
  729. libOptions += " ";
  730. libOptions += extraLinkOptions;
  731. libOptions += " ";
  732. libMultiLineOptions += "# ADD LINK32 ";
  733. libMultiLineOptions += extraLinkOptions;
  734. libMultiLineOptions += " \n";
  735. }
  736. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
  737. {
  738. libOptions += " ";
  739. libOptions += targetLinkFlags;
  740. libOptions += " ";
  741. libMultiLineOptions += "# ADD LINK32 ";
  742. libMultiLineOptions += targetLinkFlags;
  743. libMultiLineOptions += " \n";
  744. }
  745. // are there any custom rules on the target itself
  746. // only if the target is a lib or exe
  747. std::string customRuleCode = this->CreateTargetRules(target, libName);
  748. std::ifstream fin(m_DSPHeaderTemplate.c_str());
  749. if(!fin)
  750. {
  751. cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
  752. }
  753. char buffer[2048];
  754. while(fin)
  755. {
  756. fin.getline(buffer, 2048);
  757. std::string line = buffer;
  758. const char* mfcFlag = m_Makefile->GetDefinition("CMAKE_MFC_FLAG");
  759. if(!mfcFlag)
  760. {
  761. mfcFlag = "0";
  762. }
  763. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
  764. customRuleCode.c_str());
  765. cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
  766. mfcFlag);
  767. cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
  768. libOptions.c_str());
  769. cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
  770. libDebugOptions.c_str());
  771. cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
  772. libOptimizedOptions.c_str());
  773. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
  774. libMultiLineOptions.c_str());
  775. cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
  776. libMultiLineDebugOptions.c_str());
  777. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
  778. libMultiLineOptimizedOptions.c_str());
  779. cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
  780. m_IncludeOptions.c_str());
  781. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  782. // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
  783. // are already quoted in the template file,
  784. // we need to remove the quotes here, we still need
  785. // to convert to output path for unix to win32 conversion
  786. cmSystemTools::ReplaceString(line, "LIBRARY_OUTPUT_PATH",
  787. removeQuotes(
  788. cmSystemTools::ConvertToOutputPath(libPath.c_str())).c_str());
  789. cmSystemTools::ReplaceString(line, "EXECUTABLE_OUTPUT_PATH",
  790. removeQuotes(
  791. cmSystemTools::ConvertToOutputPath(exePath.c_str())).c_str());
  792. cmSystemTools::ReplaceString(line,
  793. "EXTRA_DEFINES",
  794. m_Makefile->GetDefineFlags());
  795. cmGlobalGenerator* gen = this->GetGlobalGenerator();
  796. // store flags for each configuration
  797. std::string flags = " ";
  798. std::string flagsRelease = " ";
  799. std::string flagsMinSize = " ";
  800. std::string flagsDebug = " ";
  801. std::string flagsDebugRel = " ";
  802. // if CXX is on and the target contains cxx code then add the cxx flags
  803. if ( gen->GetLanguageEnabled("CXX") && target.HasCxx() )
  804. {
  805. flagsRelease = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELEASE");
  806. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
  807. flagsMinSize = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_MINSIZEREL");
  808. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
  809. flagsDebug = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_DEBUG");
  810. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
  811. flagsDebugRel = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELWITHDEBINFO");
  812. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
  813. flags = " ";
  814. flags = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS");
  815. flags += " ";
  816. }
  817. // if C and the target is not CXX
  818. else if(gen->GetLanguageEnabled("C") && !target.HasCxx())
  819. {
  820. flagsRelease += m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELEASE");
  821. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\"";
  822. flagsMinSize += m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_MINSIZEREL");
  823. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\"";
  824. flagsDebug += m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_DEBUG");
  825. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\"";
  826. flagsDebugRel += m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELWITHDEBINFO");
  827. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\"";
  828. flags = " ";
  829. flags = m_Makefile->GetDefinition("CMAKE_C_FLAGS");
  830. }
  831. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str());
  832. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", flagsMinSize.c_str());
  833. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str());
  834. cmSystemTools::ReplaceString(line,"CMAKE_CXX_FLAGS_RELWITHDEBINFO", flagsDebugRel.c_str());
  835. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
  836. fout << line.c_str() << std::endl;
  837. }
  838. }
  839. void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
  840. {
  841. std::ifstream fin(m_DSPFooterTemplate.c_str());
  842. if(!fin)
  843. {
  844. cmSystemTools::Error("Error Reading ",
  845. m_DSPFooterTemplate.c_str());
  846. }
  847. char buffer[2048];
  848. while(fin)
  849. {
  850. fin.getline(buffer, 2048);
  851. fout << buffer << std::endl;
  852. }
  853. }