cmLocalVisualStudio6Generator.cxx 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  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. if (j->second == cmTarget::GENERAL)
  812. {
  813. libOptions += " ";
  814. libOptions += lib;
  815. libMultiLineOptions += "# ADD LINK32 ";
  816. libMultiLineOptions += lib;
  817. libMultiLineOptions += "\n";
  818. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  819. libMultiLineOptionsForDebug += libDebug;
  820. libMultiLineOptionsForDebug += "\n";
  821. }
  822. if (j->second == cmTarget::DEBUG)
  823. {
  824. libDebugOptions += " ";
  825. libDebugOptions += lib;
  826. libMultiLineDebugOptions += "# ADD LINK32 ";
  827. libMultiLineDebugOptions += libDebug;
  828. libMultiLineDebugOptions += "\n";
  829. }
  830. if (j->second == cmTarget::OPTIMIZED)
  831. {
  832. libOptimizedOptions += " ";
  833. libOptimizedOptions += lib;
  834. libMultiLineOptimizedOptions += "# ADD LINK32 ";
  835. libMultiLineOptimizedOptions += lib;
  836. libMultiLineOptimizedOptions += "\n";
  837. }
  838. }
  839. }
  840. std::string extraLinkOptions;
  841. if(target.GetType() == cmTarget::EXECUTABLE)
  842. {
  843. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
  844. }
  845. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  846. {
  847. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_SHARED_LINKER_FLAGS");
  848. }
  849. if(target.GetType() == cmTarget::MODULE_LIBRARY)
  850. {
  851. extraLinkOptions = m_Makefile->GetDefinition("CMAKE_MODULE_LINKER_FLAGS");
  852. }
  853. if(extraLinkOptions.size())
  854. {
  855. libOptions += " ";
  856. libOptions += extraLinkOptions;
  857. libOptions += " ";
  858. libMultiLineOptions += "# ADD LINK32 ";
  859. libMultiLineOptions += extraLinkOptions;
  860. libMultiLineOptions += " \n";
  861. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  862. libMultiLineOptionsForDebug += extraLinkOptions;
  863. libMultiLineOptionsForDebug += " \n";
  864. }
  865. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
  866. {
  867. libOptions += " ";
  868. libOptions += targetLinkFlags;
  869. libOptions += " ";
  870. libMultiLineOptions += "# ADD LINK32 ";
  871. libMultiLineOptions += targetLinkFlags;
  872. libMultiLineOptions += " \n";
  873. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  874. libMultiLineOptionsForDebug += targetLinkFlags;
  875. libMultiLineOptionsForDebug += " \n";
  876. }
  877. // are there any custom rules on the target itself
  878. // only if the target is a lib or exe
  879. std::string customRuleCode = this->CreateTargetRules(target, libName);
  880. std::ifstream fin(m_DSPHeaderTemplate.c_str());
  881. if(!fin)
  882. {
  883. cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
  884. }
  885. std::string line;
  886. while(cmSystemTools::GetLineFromStream(fin, line))
  887. {
  888. const char* mfcFlag = m_Makefile->GetDefinition("CMAKE_MFC_FLAG");
  889. if(!mfcFlag)
  890. {
  891. mfcFlag = "0";
  892. }
  893. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
  894. customRuleCode.c_str());
  895. cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
  896. mfcFlag);
  897. cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
  898. libOptions.c_str());
  899. cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
  900. libDebugOptions.c_str());
  901. cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
  902. libOptimizedOptions.c_str());
  903. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
  904. libMultiLineOptionsForDebug.c_str());
  905. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
  906. libMultiLineOptions.c_str());
  907. cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
  908. libMultiLineDebugOptions.c_str());
  909. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
  910. libMultiLineOptimizedOptions.c_str());
  911. cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
  912. m_IncludeOptions.c_str());
  913. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  914. // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
  915. // are already quoted in the template file,
  916. // we need to remove the quotes here, we still need
  917. // to convert to output path for unix to win32 conversion
  918. cmSystemTools::ReplaceString(line, "LIBRARY_OUTPUT_PATH",
  919. removeQuotes(
  920. cmSystemTools::ConvertToOutputPath(libPath.c_str())).c_str());
  921. cmSystemTools::ReplaceString(line, "EXECUTABLE_OUTPUT_PATH",
  922. removeQuotes(
  923. cmSystemTools::ConvertToOutputPath(exePath.c_str())).c_str());
  924. cmSystemTools::ReplaceString(line,
  925. "EXTRA_DEFINES",
  926. m_Makefile->GetDefineFlags());
  927. const char* debugPostfix
  928. = m_Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
  929. cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
  930. debugPostfix?debugPostfix:"");
  931. cmGlobalGenerator* gen = this->GetGlobalGenerator();
  932. // store flags for each configuration
  933. std::string flags = " ";
  934. std::string flagsRelease = " ";
  935. std::string flagsMinSize = " ";
  936. std::string flagsDebug = " ";
  937. std::string flagsDebugRel = " ";
  938. // if CXX is on and the target contains cxx code then add the cxx flags
  939. if ( gen->GetLanguageEnabled("CXX") && target.HasCxx() )
  940. {
  941. flagsRelease = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELEASE");
  942. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
  943. flagsMinSize = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_MINSIZEREL");
  944. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
  945. flagsDebug = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_DEBUG");
  946. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
  947. flagsDebugRel = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS_RELWITHDEBINFO");
  948. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
  949. flags = " ";
  950. flags = m_Makefile->GetDefinition("CMAKE_CXX_FLAGS");
  951. }
  952. // if C and the target is not CXX
  953. else if(gen->GetLanguageEnabled("C") && !target.HasCxx())
  954. {
  955. flagsRelease += m_Makefile->GetDefinition("CMAKE_C_FLAGS_RELEASE");
  956. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\"";
  957. flagsMinSize += m_Makefile->GetDefinition("CMAKE_C_FLAGS_MINSIZEREL");
  958. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\"";
  959. flagsDebug += m_Makefile->GetDefinition("CMAKE_C_FLAGS_DEBUG");
  960. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\"";
  961. flagsDebugRel += m_Makefile->GetDefinition("CMAKE_C_FLAGS_RELWITHDEBINFO");
  962. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\"";
  963. flags = " ";
  964. flags = m_Makefile->GetDefinition("CMAKE_C_FLAGS");
  965. }
  966. // if unicode is not found, then add -D_MBCS
  967. if(flags.find("D_UNICODE") == flags.npos)
  968. {
  969. flags += " /D \"_MBCS\"";
  970. }
  971. // The template files have CXX FLAGS in them, that need to be replaced.
  972. // There are not separate CXX and C template files, so we use the same
  973. // variable names. The previous code sets up flags* variables to contain
  974. // the correct C or CXX flags
  975. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str());
  976. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", flagsMinSize.c_str());
  977. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str());
  978. cmSystemTools::ReplaceString(line,"CMAKE_CXX_FLAGS_RELWITHDEBINFO", flagsDebugRel.c_str());
  979. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
  980. fout << line.c_str() << std::endl;
  981. }
  982. }
  983. void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
  984. {
  985. std::ifstream fin(m_DSPFooterTemplate.c_str());
  986. if(!fin)
  987. {
  988. cmSystemTools::Error("Error Reading ",
  989. m_DSPFooterTemplate.c_str());
  990. }
  991. std::string line;
  992. while(cmSystemTools::GetLineFromStream(fin, line))
  993. {
  994. fout << line << std::endl;
  995. }
  996. }