cmLocalVisualStudio6Generator.cxx 36 KB

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