cmLocalVisualStudio6Generator.cxx 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  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()
  28. {
  29. std::set<cmStdString> lang;
  30. lang.insert("C");
  31. lang.insert("CXX");
  32. this->CreateCustomTargetsAndCommands(lang);
  33. this->OutputDSPFile();
  34. }
  35. void cmLocalVisualStudio6Generator::OutputDSPFile()
  36. {
  37. // If not an in source build, then create the output directory
  38. if(strcmp(this->Makefile->GetStartOutputDirectory(),
  39. this->Makefile->GetHomeDirectory()) != 0)
  40. {
  41. if(!cmSystemTools::MakeDirectory(this->Makefile->GetStartOutputDirectory()))
  42. {
  43. cmSystemTools::Error("Error creating directory ",
  44. this->Makefile->GetStartOutputDirectory());
  45. }
  46. }
  47. // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
  48. // truncates long include paths so make it as short as possible if
  49. // the length threatents this problem.
  50. unsigned int maxIncludeLength = 3000;
  51. bool useShortPath = false;
  52. for(int j=0; j < 2; ++j)
  53. {
  54. std::vector<std::string> includes;
  55. this->GetIncludeDirectories(includes);
  56. std::vector<std::string>::iterator i;
  57. for(i = includes.begin(); i != includes.end(); ++i)
  58. {
  59. std::string tmp =
  60. this->ConvertToOptionallyRelativeOutputPath(i->c_str());
  61. if(useShortPath)
  62. {
  63. cmSystemTools::GetShortPath(tmp.c_str(), tmp);
  64. }
  65. this->IncludeOptions += " /I ";
  66. // quote if not already quoted
  67. if (tmp[0] != '"')
  68. {
  69. this->IncludeOptions += "\"";
  70. this->IncludeOptions += tmp;
  71. this->IncludeOptions += "\"";
  72. }
  73. else
  74. {
  75. this->IncludeOptions += tmp;
  76. }
  77. }
  78. if(j == 0 && this->IncludeOptions.size() > maxIncludeLength)
  79. {
  80. this->IncludeOptions = "";
  81. useShortPath = true;
  82. }
  83. else
  84. {
  85. break;
  86. }
  87. }
  88. // Create the DSP or set of DSP's for libraries and executables
  89. // clear project names
  90. this->CreatedProjectNames.clear();
  91. // Call TraceVSDependencies on all targets
  92. cmTargets &tgts = this->Makefile->GetTargets();
  93. for(cmTargets::iterator l = tgts.begin();
  94. l != tgts.end(); l++)
  95. {
  96. // Add a rule to regenerate the build system when the target
  97. // specification source changes.
  98. const char* suppRegenRule =
  99. this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
  100. if (!cmSystemTools::IsOn(suppRegenRule))
  101. {
  102. this->AddDSPBuildRule(l->second);
  103. }
  104. // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
  105. // so don't build a projectfile for it
  106. if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  107. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
  108. && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
  109. {
  110. cmTarget& target = l->second;
  111. target.TraceVSDependencies(target.GetName(), this->Makefile);
  112. }
  113. }
  114. // now for all custom commands that are not used directly in a
  115. // target, add them to all targets in the current directory or
  116. // makefile
  117. std::vector<cmSourceFile*> & classesmf = this->Makefile->GetSourceFiles();
  118. for(std::vector<cmSourceFile*>::const_iterator i = classesmf.begin();
  119. i != classesmf.end(); i++)
  120. {
  121. if(cmCustomCommand* cc = (*i)->GetCustomCommand())
  122. {
  123. if(!cc->IsUsed())
  124. {
  125. for(cmTargets::iterator l = tgts.begin();
  126. l != tgts.end(); l++)
  127. {
  128. if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  129. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
  130. && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
  131. && (strcmp(l->first.c_str(), "ALL_BUILD") != 0)
  132. && (strcmp(l->first.c_str(), "RUN_TESTS") != 0)
  133. && (strcmp(l->first.c_str(), "INSTALL") != 0))
  134. {
  135. cmTarget& target = l->second;
  136. bool sameAsTarget = false;
  137. // make sure we don't add a custom command that depends on
  138. // this target
  139. for(unsigned int k =0; k < cc->GetDepends().size(); k++)
  140. {
  141. if(cmSystemTools::GetFilenameName(cc->GetDepends()[k]) == target.GetFullName())
  142. {
  143. sameAsTarget = true;
  144. }
  145. }
  146. if(!sameAsTarget)
  147. {
  148. target.GetSourceFiles().push_back(*i);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. }
  155. // build any targets
  156. for(cmTargets::iterator l = tgts.begin();
  157. l != tgts.end(); l++)
  158. {
  159. switch(l->second.GetType())
  160. {
  161. case cmTarget::STATIC_LIBRARY:
  162. this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
  163. break;
  164. case cmTarget::SHARED_LIBRARY:
  165. case cmTarget::MODULE_LIBRARY:
  166. this->SetBuildType(DLL, l->first.c_str(), l->second);
  167. break;
  168. case cmTarget::EXECUTABLE:
  169. this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
  170. break;
  171. case cmTarget::UTILITY:
  172. case cmTarget::GLOBAL_TARGET:
  173. this->SetBuildType(UTILITY, l->first.c_str(), l->second);
  174. break;
  175. case cmTarget::INSTALL_FILES:
  176. break;
  177. case cmTarget::INSTALL_PROGRAMS:
  178. break;
  179. default:
  180. cmSystemTools::Error("Bad target type", l->first.c_str());
  181. break;
  182. }
  183. // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
  184. // so don't build a projectfile for it
  185. if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  186. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
  187. && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
  188. {
  189. // check to see if the dsp is going into a sub-directory
  190. std::string::size_type pos = l->first.rfind('/');
  191. if(pos != std::string::npos)
  192. {
  193. std::string dir = this->Makefile->GetStartOutputDirectory();
  194. dir += "/";
  195. dir += l->first.substr(0, pos);
  196. if(!cmSystemTools::MakeDirectory(dir.c_str()))
  197. {
  198. cmSystemTools::Error("Error creating directory ", dir.c_str());
  199. }
  200. }
  201. this->CreateSingleDSP(l->first.c_str(),l->second);
  202. }
  203. }
  204. }
  205. void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname, cmTarget &target)
  206. {
  207. // add to the list of projects
  208. std::string pname = lname;
  209. this->CreatedProjectNames.push_back(pname);
  210. // create the dsp.cmake file
  211. std::string fname;
  212. fname = this->Makefile->GetStartOutputDirectory();
  213. fname += "/";
  214. fname += lname;
  215. fname += ".dsp";
  216. // save the name of the real dsp file
  217. std::string realDSP = fname;
  218. fname += ".cmake";
  219. std::ofstream fout(fname.c_str());
  220. if(!fout)
  221. {
  222. cmSystemTools::Error("Error Writing ", fname.c_str());
  223. cmSystemTools::ReportLastSystemError("");
  224. }
  225. this->WriteDSPFile(fout,lname,target);
  226. fout.close();
  227. // if the dsp file has changed, then write it.
  228. cmSystemTools::CopyFileIfDifferent(fname.c_str(), realDSP.c_str());
  229. }
  230. void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt)
  231. {
  232. std::string dspname = tgt.GetName();
  233. dspname += ".dsp.cmake";
  234. const char* dsprule = this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
  235. cmCustomCommandLine commandLine;
  236. commandLine.push_back(dsprule);
  237. std::string makefileIn = this->Makefile->GetStartDirectory();
  238. makefileIn += "/";
  239. makefileIn += "CMakeLists.txt";
  240. std::string args;
  241. args = "-H";
  242. args +=
  243. this->Convert(this->Makefile->GetHomeDirectory(),START_OUTPUT, SHELL, true);
  244. commandLine.push_back(args);
  245. args = "-B";
  246. args +=
  247. this->Convert(this->Makefile->GetHomeOutputDirectory(),
  248. START_OUTPUT, SHELL, true);
  249. commandLine.push_back(args);
  250. std::string configFile =
  251. this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
  252. configFile += "/Templates/CMakeWindowsSystemConfig.cmake";
  253. std::vector<std::string> listFiles = this->Makefile->GetListFiles();
  254. bool found = false;
  255. for(std::vector<std::string>::iterator i = listFiles.begin();
  256. i != listFiles.end(); ++i)
  257. {
  258. if(*i == configFile)
  259. {
  260. found = true;
  261. }
  262. }
  263. if(!found)
  264. {
  265. listFiles.push_back(configFile);
  266. }
  267. cmCustomCommandLines commandLines;
  268. commandLines.push_back(commandLine);
  269. const char* no_comment = 0;
  270. const char* no_working_directory = 0;
  271. this->Makefile->AddCustomCommandToOutput(dspname.c_str(), listFiles, makefileIn.c_str(),
  272. commandLines, no_comment, no_working_directory, true);
  273. if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
  274. {
  275. tgt.GetSourceFiles().push_back(file);
  276. }
  277. else
  278. {
  279. cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
  280. }
  281. }
  282. void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
  283. const char *libName,
  284. cmTarget &target)
  285. {
  286. // For utility targets need custom command since pre- and post-
  287. // build does not do anything in Visual Studio 6. In order for the
  288. // rules to run in the correct order as custom commands, we need
  289. // special care for dependencies. The first rule must depend on all
  290. // the dependencies of all the rules. The later rules must each
  291. // depend only on the previous rule.
  292. if ((target.GetType() == cmTarget::UTILITY ||
  293. target.GetType() == cmTarget::GLOBAL_TARGET) &&
  294. (!target.GetPreBuildCommands().empty() ||
  295. !target.GetPostBuildCommands().empty()))
  296. {
  297. // Accumulate the dependencies of all the commands.
  298. std::vector<std::string> depends;
  299. for (std::vector<cmCustomCommand>::const_iterator cr =
  300. target.GetPreBuildCommands().begin();
  301. cr != target.GetPreBuildCommands().end(); ++cr)
  302. {
  303. depends.insert(depends.end(),
  304. cr->GetDepends().begin(), cr->GetDepends().end());
  305. }
  306. for (std::vector<cmCustomCommand>::const_iterator cr =
  307. target.GetPostBuildCommands().begin();
  308. cr != target.GetPostBuildCommands().end(); ++cr)
  309. {
  310. depends.insert(depends.end(),
  311. cr->GetDepends().begin(), cr->GetDepends().end());
  312. }
  313. // Add the pre- and post-build commands in order.
  314. int count = 1;
  315. for (std::vector<cmCustomCommand>::const_iterator cr =
  316. target.GetPreBuildCommands().begin();
  317. cr != target.GetPreBuildCommands().end(); ++cr)
  318. {
  319. this->AddUtilityCommandHack(target, count++, depends, *cr);
  320. }
  321. for (std::vector<cmCustomCommand>::const_iterator cr =
  322. target.GetPostBuildCommands().begin();
  323. cr != target.GetPostBuildCommands().end(); ++cr)
  324. {
  325. this->AddUtilityCommandHack(target, count++, depends, *cr);
  326. }
  327. }
  328. // trace the visual studio dependencies
  329. std::string name = libName;
  330. name += ".dsp.cmake";
  331. // We may be modifying the source groups temporarily, so make a copy.
  332. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
  333. // get the classes from the source lists then add them to the groups
  334. std::vector<cmSourceFile*> & classes = target.GetSourceFiles();
  335. // now all of the source files have been properly assigned to the target
  336. // now stick them into source groups using the reg expressions
  337. for(std::vector<cmSourceFile*>::iterator i = classes.begin();
  338. i != classes.end(); i++)
  339. {
  340. // Add the file to the list of sources.
  341. std::string source = (*i)->GetFullPath();
  342. cmSourceGroup& sourceGroup = this->Makefile->FindSourceGroup(source.c_str(),
  343. sourceGroups);
  344. sourceGroup.AssignSource(*i);
  345. // while we are at it, if it is a .rule file then for visual studio 6 we
  346. // must generate it
  347. if ((*i)->GetSourceExtension() == "rule")
  348. {
  349. if(!cmSystemTools::FileExists(source.c_str()))
  350. {
  351. cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
  352. #if defined(_WIN32) || defined(__CYGWIN__)
  353. std::ofstream fout(source.c_str(),
  354. std::ios::binary | std::ios::out | std::ios::trunc);
  355. #else
  356. std::ofstream fout(source.c_str(),
  357. std::ios::out | std::ios::trunc);
  358. #endif
  359. if(fout)
  360. {
  361. fout.write("# generated from CMake",22);
  362. fout.flush();
  363. fout.close();
  364. }
  365. }
  366. }
  367. }
  368. // Write the DSP file's header.
  369. this->WriteDSPHeader(fout, libName, target, sourceGroups);
  370. // Loop through every source group.
  371. for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
  372. sg != sourceGroups.end(); ++sg)
  373. {
  374. this->WriteGroup(&(*sg), target, fout, libName);
  375. }
  376. // Write the DSP file's footer.
  377. this->WriteDSPFooter(fout);
  378. }
  379. void cmLocalVisualStudio6Generator::WriteGroup(const cmSourceGroup *sg, cmTarget target, std::ostream &fout, const char *libName)
  380. {
  381. const std::vector<const cmSourceFile *> &sourceFiles =
  382. sg->GetSourceFiles();
  383. // If the group is empty, don't write it at all.
  384. if(sourceFiles.empty())
  385. {
  386. return;
  387. }
  388. // If the group has a name, write the header.
  389. std::string name = sg->GetName();
  390. if(name != "")
  391. {
  392. this->WriteDSPBeginGroup(fout, name.c_str(), "");
  393. }
  394. // Loop through each source in the source group.
  395. for(std::vector<const cmSourceFile *>::const_iterator sf =
  396. sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
  397. {
  398. std::string source = (*sf)->GetFullPath();
  399. const cmCustomCommand *command =
  400. (*sf)->GetCustomCommand();
  401. std::string compileFlags;
  402. std::vector<std::string> depends;
  403. // Add per-source file flags.
  404. if(const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS"))
  405. {
  406. compileFlags += cflags;
  407. }
  408. const char* lang =
  409. this->GlobalGenerator->GetLanguageFromExtension((*sf)->GetSourceExtension().c_str());
  410. if(lang && strcmp(lang, "CXX") == 0)
  411. {
  412. // force a C++ file type
  413. compileFlags += " /TP ";
  414. }
  415. // Check for extra object-file dependencies.
  416. const char* dependsValue = (*sf)->GetProperty("OBJECT_DEPENDS");
  417. if(dependsValue)
  418. {
  419. cmSystemTools::ExpandListArgument(dependsValue, depends);
  420. }
  421. if (source != libName || target.GetType() == cmTarget::UTILITY ||
  422. target.GetType() == cmTarget::GLOBAL_TARGET)
  423. {
  424. fout << "# Begin Source File\n\n";
  425. // Tell MS-Dev what the source is. If the compiler knows how to
  426. // build it, then it will.
  427. fout << "SOURCE=" <<
  428. this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n";
  429. if(!depends.empty())
  430. {
  431. // Write out the dependencies for the rule.
  432. fout << "USERDEP__HACK=";
  433. for(std::vector<std::string>::const_iterator d = depends.begin();
  434. d != depends.end(); ++d)
  435. {
  436. fout << "\\\n\t" <<
  437. this->ConvertToOptionallyRelativeOutputPath(d->c_str());
  438. }
  439. fout << "\n";
  440. }
  441. if (command)
  442. {
  443. std::string script =
  444. this->ConstructScript(command->GetCommandLines(),
  445. command->GetWorkingDirectory(),
  446. "\\\n\t");
  447. const char* comment = command->GetComment();
  448. const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
  449. this->WriteCustomRule(fout, source.c_str(), script.c_str(),
  450. (*comment?comment:"Custom Rule"),
  451. command->GetDepends(),
  452. command->GetOutput(), flags);
  453. }
  454. else if(compileFlags.size())
  455. {
  456. for(std::vector<std::string>::iterator i
  457. = this->Configurations.begin(); i != this->Configurations.end(); ++i)
  458. {
  459. if (i == this->Configurations.begin())
  460. {
  461. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  462. }
  463. else
  464. {
  465. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  466. }
  467. fout << "\n# ADD CPP " << compileFlags << "\n\n";
  468. }
  469. fout << "!ENDIF\n\n";
  470. }
  471. fout << "# End Source File\n";
  472. }
  473. }
  474. std::vector<cmSourceGroup> children = sg->GetGroupChildren();
  475. for(unsigned int i=0;i<children.size();++i)
  476. {
  477. this->WriteGroup(&children[i], target, fout, libName);
  478. }
  479. // If the group has a name, write the footer.
  480. if(name != "")
  481. {
  482. this->WriteDSPEndGroup(fout);
  483. }
  484. }
  485. void
  486. cmLocalVisualStudio6Generator
  487. ::AddUtilityCommandHack(cmTarget& target, int count,
  488. std::vector<std::string>& depends,
  489. const cmCustomCommand& origCommand)
  490. {
  491. // Create a fake output that forces the rule to run.
  492. char* output = new char[(strlen(this->Makefile->GetStartOutputDirectory()) +
  493. strlen(target.GetName()) + 30)];
  494. sprintf(output,"%s/%s_force_%i", this->Makefile->GetStartOutputDirectory(),
  495. target.GetName(), count);
  496. // Add the rule with the given dependencies and commands.
  497. const char* no_main_dependency = 0;
  498. this->Makefile->AddCustomCommandToOutput(output,
  499. depends,
  500. no_main_dependency,
  501. origCommand.GetCommandLines(),
  502. origCommand.GetComment(),
  503. origCommand.GetWorkingDirectory());
  504. // Replace the dependencies with the output of this rule so that the
  505. // next rule added will run after this one.
  506. depends.clear();
  507. depends.push_back(output);
  508. // Add a source file representing this output to the project.
  509. cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output);
  510. target.GetSourceFiles().push_back(outsf);
  511. // Free the fake output name.
  512. delete [] output;
  513. }
  514. void cmLocalVisualStudio6Generator::WriteCustomRule(std::ostream& fout,
  515. const char* source,
  516. const char* command,
  517. const char* comment,
  518. const std::vector<std::string>& depends,
  519. const char *output,
  520. const char* flags
  521. )
  522. {
  523. std::vector<std::string>::iterator i;
  524. for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
  525. {
  526. if (i == this->Configurations.begin())
  527. {
  528. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  529. }
  530. else
  531. {
  532. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  533. }
  534. if(flags)
  535. {
  536. fout << "\n# ADD CPP " << flags << "\n\n";
  537. }
  538. // Write out the dependencies for the rule.
  539. fout << "USERDEP__HACK=";
  540. for(std::vector<std::string>::const_iterator d = depends.begin();
  541. d != depends.end(); ++d)
  542. {
  543. // Lookup the real name of the dependency in case it is a CMake target.
  544. std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
  545. fout << "\\\n\t" <<
  546. this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
  547. }
  548. fout << "\n";
  549. fout << "# PROP Ignore_Default_Tool 1\n";
  550. fout << "# Begin Custom Build - Building " << comment
  551. << " $(InputPath)\n\n";
  552. if(output == 0)
  553. {
  554. fout << source << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
  555. fout << command << "\n\n";
  556. }
  557. // Write a rule for every output generated by this command.
  558. fout << this->ConvertToOptionallyRelativeOutputPath(output)
  559. << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
  560. fout << command << "\n\n";
  561. fout << "# End Custom Build\n\n";
  562. }
  563. fout << "!ENDIF\n\n";
  564. }
  565. void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout,
  566. const char* group,
  567. const char* filter)
  568. {
  569. fout << "# Begin Group \"" << group << "\"\n"
  570. "# PROP Default_Filter \"" << filter << "\"\n";
  571. }
  572. void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
  573. {
  574. fout << "# End Group\n";
  575. }
  576. void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
  577. const char* libName,
  578. cmTarget& target)
  579. {
  580. std::string root= this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
  581. const char *def= this->Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
  582. if( def)
  583. {
  584. root = def;
  585. }
  586. else
  587. {
  588. root += "/Templates";
  589. }
  590. switch(b)
  591. {
  592. case STATIC_LIBRARY:
  593. this->DSPHeaderTemplate = root;
  594. this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
  595. this->DSPFooterTemplate = root;
  596. this->DSPFooterTemplate += "/staticLibFooter.dsptemplate";
  597. break;
  598. case DLL:
  599. this->DSPHeaderTemplate = root;
  600. this->DSPHeaderTemplate += "/DLLHeader.dsptemplate";
  601. this->DSPFooterTemplate = root;
  602. this->DSPFooterTemplate += "/DLLFooter.dsptemplate";
  603. break;
  604. case EXECUTABLE:
  605. if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
  606. {
  607. this->DSPHeaderTemplate = root;
  608. this->DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
  609. this->DSPFooterTemplate = root;
  610. this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
  611. }
  612. else
  613. {
  614. this->DSPHeaderTemplate = root;
  615. this->DSPHeaderTemplate += "/EXEHeader.dsptemplate";
  616. this->DSPFooterTemplate = root;
  617. this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
  618. }
  619. break;
  620. case UTILITY:
  621. this->DSPHeaderTemplate = root;
  622. this->DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
  623. this->DSPFooterTemplate = root;
  624. this->DSPFooterTemplate += "/UtilityFooter.dsptemplate";
  625. break;
  626. }
  627. // once the build type is set, determine what configurations are
  628. // possible
  629. std::ifstream fin(this->DSPHeaderTemplate.c_str());
  630. cmsys::RegularExpression reg("# Name ");
  631. if(!fin)
  632. {
  633. cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
  634. }
  635. // reset this->Configurations
  636. this->Configurations.erase(this->Configurations.begin(), this->Configurations.end());
  637. // now add all the configurations possible
  638. std::string line;
  639. while(cmSystemTools::GetLineFromStream(fin, line))
  640. {
  641. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  642. if (reg.find(line))
  643. {
  644. this->Configurations.push_back(line.substr(reg.end()));
  645. }
  646. }
  647. }
  648. // look for custom rules on a target and collect them together
  649. std::string
  650. cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
  651. const char * /* libName */)
  652. {
  653. std::string customRuleCode = "";
  654. if (target.GetType() >= cmTarget::UTILITY )
  655. {
  656. return customRuleCode;
  657. }
  658. // are there any rules?
  659. if (target.GetPreBuildCommands().size() +
  660. target.GetPreLinkCommands().size() +
  661. target.GetPostBuildCommands().size() == 0)
  662. {
  663. return customRuleCode;
  664. }
  665. customRuleCode = "# Begin Special Build Tool\n";
  666. // Write the pre-build and pre-link together (VS6 does not support
  667. // both). Make sure no continuation character is put on the last
  668. // line.
  669. int prelink_total = (static_cast<int>(target.GetPreBuildCommands().size())+
  670. static_cast<int>(target.GetPreLinkCommands().size()));
  671. int prelink_count = 0;
  672. if(prelink_total > 0)
  673. {
  674. // header stuff
  675. customRuleCode += "PreLink_Cmds=";
  676. }
  677. const char* prelink_newline = "\\\n\t";
  678. for (std::vector<cmCustomCommand>::const_iterator cr =
  679. target.GetPreBuildCommands().begin();
  680. cr != target.GetPreBuildCommands().end(); ++cr)
  681. {
  682. if(++prelink_count == prelink_total)
  683. {
  684. prelink_newline = "";
  685. }
  686. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  687. cr->GetWorkingDirectory(),
  688. prelink_newline);
  689. }
  690. for (std::vector<cmCustomCommand>::const_iterator cr =
  691. target.GetPreLinkCommands().begin();
  692. cr != target.GetPreLinkCommands().end(); ++cr)
  693. {
  694. if(++prelink_count == prelink_total)
  695. {
  696. prelink_newline = "";
  697. }
  698. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  699. cr->GetWorkingDirectory(),
  700. prelink_newline);
  701. }
  702. if(prelink_total > 0)
  703. {
  704. customRuleCode += "\n";
  705. }
  706. // Write the post-build rules. Make sure no continuation character
  707. // is put on the last line.
  708. int postbuild_total = static_cast<int>(target.GetPostBuildCommands().size());
  709. int postbuild_count = 0;
  710. const char* postbuild_newline = "\\\n\t";
  711. if(postbuild_total > 0)
  712. {
  713. customRuleCode += "PostBuild_Cmds=";
  714. }
  715. for (std::vector<cmCustomCommand>::const_iterator cr =
  716. target.GetPostBuildCommands().begin();
  717. cr != target.GetPostBuildCommands().end(); ++cr)
  718. {
  719. if(++postbuild_count == postbuild_total)
  720. {
  721. postbuild_newline = "";
  722. }
  723. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  724. cr->GetWorkingDirectory(),
  725. postbuild_newline);
  726. }
  727. if(postbuild_total > 0)
  728. {
  729. customRuleCode += "\n";
  730. }
  731. customRuleCode += "# End Special Build Tool\n";
  732. return customRuleCode;
  733. }
  734. inline std::string removeQuotes(const std::string& s)
  735. {
  736. if(s[0] == '\"' && s[s.size()-1] == '\"')
  737. {
  738. return s.substr(1, s.size()-2);
  739. }
  740. return s;
  741. }
  742. void cmLocalVisualStudio6Generator
  743. ::WriteDSPHeader(std::ostream& fout,
  744. const char *libName, cmTarget &target,
  745. std::vector<cmSourceGroup> &)
  746. {
  747. std::set<std::string> pathEmitted;
  748. // determine the link directories
  749. std::string libOptions;
  750. std::string libDebugOptions;
  751. std::string libOptimizedOptions;
  752. std::string libMultiLineOptions;
  753. std::string libMultiLineOptionsForDebug;
  754. std::string libMultiLineDebugOptions;
  755. std::string libMultiLineOptimizedOptions;
  756. // suppoirt override in output directory
  757. std::string libPath = "";
  758. if (this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
  759. {
  760. libPath = this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
  761. }
  762. std::string exePath = "";
  763. if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
  764. {
  765. exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  766. }
  767. if(libPath.size())
  768. {
  769. // make sure there is a trailing slash
  770. if(libPath[libPath.size()-1] != '/')
  771. {
  772. libPath += "/";
  773. }
  774. std::string lpath =
  775. this->ConvertToOptionallyRelativeOutputPath(libPath.c_str());
  776. if(lpath.size() == 0)
  777. {
  778. lpath = ".";
  779. }
  780. std::string lpathIntDir = libPath + "$(INTDIR)";
  781. lpathIntDir = this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  782. if(pathEmitted.insert(lpath).second)
  783. {
  784. libOptions += " /LIBPATH:";
  785. libOptions += lpathIntDir;
  786. libOptions += " ";
  787. libOptions += " /LIBPATH:";
  788. libOptions += lpath;
  789. libOptions += " ";
  790. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  791. libMultiLineOptions += lpathIntDir;
  792. libMultiLineOptions += " ";
  793. libMultiLineOptions += " /LIBPATH:";
  794. libMultiLineOptions += lpath;
  795. libMultiLineOptions += " \n";
  796. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  797. libMultiLineOptionsForDebug += lpathIntDir;
  798. libMultiLineOptionsForDebug += " ";
  799. libMultiLineOptionsForDebug += " /LIBPATH:";
  800. libMultiLineOptionsForDebug += lpath;
  801. libMultiLineOptionsForDebug += " \n";
  802. }
  803. }
  804. if(exePath.size())
  805. {
  806. // make sure there is a trailing slash
  807. if(exePath[exePath.size()-1] != '/')
  808. {
  809. exePath += "/";
  810. }
  811. std::string lpath =
  812. this->ConvertToOptionallyRelativeOutputPath(exePath.c_str());
  813. if(lpath.size() == 0)
  814. {
  815. lpath = ".";
  816. }
  817. std::string lpathIntDir = exePath + "$(INTDIR)";
  818. lpathIntDir = this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  819. if(pathEmitted.insert(lpath).second)
  820. {
  821. libOptions += " /LIBPATH:";
  822. libOptions += lpathIntDir;
  823. libOptions += " ";
  824. libOptions += " /LIBPATH:";
  825. libOptions += lpath;
  826. libOptions += " ";
  827. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  828. libMultiLineOptions += lpathIntDir;
  829. libMultiLineOptions += " ";
  830. libMultiLineOptions += " /LIBPATH:";
  831. libMultiLineOptions += lpath;
  832. libMultiLineOptions += " \n";
  833. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  834. libMultiLineOptionsForDebug += lpathIntDir;
  835. libMultiLineOptionsForDebug += " ";
  836. libMultiLineOptionsForDebug += " /LIBPATH:";
  837. libMultiLineOptionsForDebug += lpath;
  838. libMultiLineOptionsForDebug += " \n";
  839. }
  840. }
  841. std::vector<std::string>::const_iterator i;
  842. const std::vector<std::string>& libdirs = target.GetLinkDirectories();
  843. for(i = libdirs.begin(); i != libdirs.end(); ++i)
  844. {
  845. std::string path = *i;
  846. if(path[path.size()-1] != '/')
  847. {
  848. path += "/";
  849. }
  850. std::string lpath =
  851. this->ConvertToOptionallyRelativeOutputPath(path.c_str());
  852. if(lpath.size() == 0)
  853. {
  854. lpath = ".";
  855. }
  856. std::string lpathIntDir = path + "$(INTDIR)";
  857. lpathIntDir = this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  858. if(pathEmitted.insert(lpath).second)
  859. {
  860. libOptions += " /LIBPATH:";
  861. libOptions += lpathIntDir;
  862. libOptions += " ";
  863. libOptions += " /LIBPATH:";
  864. libOptions += lpath;
  865. libOptions += " ";
  866. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  867. libMultiLineOptions += lpathIntDir;
  868. libMultiLineOptions += " ";
  869. libMultiLineOptions += " /LIBPATH:";
  870. libMultiLineOptions += lpath;
  871. libMultiLineOptions += " \n";
  872. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  873. libMultiLineOptionsForDebug += lpathIntDir;
  874. libMultiLineOptionsForDebug += " ";
  875. libMultiLineOptionsForDebug += " /LIBPATH:";
  876. libMultiLineOptionsForDebug += lpath;
  877. libMultiLineOptionsForDebug += " \n";
  878. }
  879. }
  880. // find link libraries
  881. const cmTarget::LinkLibraryVectorType& libs = target.GetLinkLibraries();
  882. cmTarget::LinkLibraryVectorType::const_iterator j;
  883. for(j = libs.begin(); j != libs.end(); ++j)
  884. {
  885. // add libraries to executables and dlls (but never include
  886. // a library in a library, bad recursion)
  887. // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
  888. if ((target.GetType() != cmTarget::SHARED_LIBRARY
  889. && target.GetType() != cmTarget::STATIC_LIBRARY
  890. && target.GetType() != cmTarget::MODULE_LIBRARY) ||
  891. (target.GetType()==cmTarget::SHARED_LIBRARY && libName != j->first) ||
  892. (target.GetType()==cmTarget::MODULE_LIBRARY && libName != j->first))
  893. {
  894. // Compute the proper name to use to link this library.
  895. std::string lib;
  896. std::string libDebug;
  897. cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
  898. if(tgt)
  899. {
  900. lib = cmSystemTools::GetFilenameWithoutExtension(tgt->GetFullName().c_str());
  901. libDebug = cmSystemTools::GetFilenameWithoutExtension(tgt->GetFullName("Debug").c_str());
  902. lib += ".lib";
  903. libDebug += ".lib";
  904. }
  905. else
  906. {
  907. lib = j->first.c_str();
  908. libDebug = j->first.c_str();
  909. if(j->first.find(".lib") == std::string::npos)
  910. {
  911. lib += ".lib";
  912. libDebug += ".lib";
  913. }
  914. }
  915. lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
  916. libDebug = this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
  917. if (j->second == cmTarget::GENERAL)
  918. {
  919. libOptions += " ";
  920. libOptions += lib;
  921. libMultiLineOptions += "# ADD LINK32 ";
  922. libMultiLineOptions += lib;
  923. libMultiLineOptions += "\n";
  924. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  925. libMultiLineOptionsForDebug += libDebug;
  926. libMultiLineOptionsForDebug += "\n";
  927. }
  928. if (j->second == cmTarget::DEBUG)
  929. {
  930. libDebugOptions += " ";
  931. libDebugOptions += lib;
  932. libMultiLineDebugOptions += "# ADD LINK32 ";
  933. libMultiLineDebugOptions += libDebug;
  934. libMultiLineDebugOptions += "\n";
  935. }
  936. if (j->second == cmTarget::OPTIMIZED)
  937. {
  938. libOptimizedOptions += " ";
  939. libOptimizedOptions += lib;
  940. libMultiLineOptimizedOptions += "# ADD LINK32 ";
  941. libMultiLineOptimizedOptions += lib;
  942. libMultiLineOptimizedOptions += "\n";
  943. }
  944. }
  945. }
  946. std::string outputName = "(OUTPUT_NAME is for executables only)";
  947. std::string extraLinkOptions;
  948. // TODO: Fix construction of library/executable name through
  949. // cmTarget. OUTPUT_LIBNAMEDEBUG_POSTFIX should be replaced by the
  950. // library's debug configuration name. OUTPUT_LIBNAME should be
  951. // replaced by the non-debug configuration name. This generator
  952. // should just be re-written to not use template files and just
  953. // generate the code. Setting up these substitutions is a pain.
  954. if(target.GetType() == cmTarget::EXECUTABLE)
  955. {
  956. extraLinkOptions =
  957. this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
  958. // Use the OUTPUT_NAME property if it was set. This is supported
  959. // only for executables.
  960. if(const char* outName = target.GetProperty("OUTPUT_NAME"))
  961. {
  962. outputName = outName;
  963. }
  964. else
  965. {
  966. outputName = target.GetName();
  967. }
  968. outputName += ".exe";
  969. }
  970. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  971. {
  972. extraLinkOptions = this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
  973. }
  974. if(target.GetType() == cmTarget::MODULE_LIBRARY)
  975. {
  976. extraLinkOptions = this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
  977. }
  978. if(extraLinkOptions.size())
  979. {
  980. libOptions += " ";
  981. libOptions += extraLinkOptions;
  982. libOptions += " ";
  983. libMultiLineOptions += "# ADD LINK32 ";
  984. libMultiLineOptions += extraLinkOptions;
  985. libMultiLineOptions += " \n";
  986. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  987. libMultiLineOptionsForDebug += extraLinkOptions;
  988. libMultiLineOptionsForDebug += " \n";
  989. }
  990. if(const char* stdLibs = this->Makefile->GetDefinition("CMAKE_STANDARD_LIBRARIES"))
  991. {
  992. libOptions += " ";
  993. libOptions += stdLibs;
  994. libOptions += " ";
  995. libMultiLineOptions += "# ADD LINK32 ";
  996. libMultiLineOptions += stdLibs;
  997. libMultiLineOptions += " \n";
  998. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  999. libMultiLineOptionsForDebug += stdLibs;
  1000. libMultiLineOptionsForDebug += " \n";
  1001. }
  1002. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
  1003. {
  1004. libOptions += " ";
  1005. libOptions += targetLinkFlags;
  1006. libOptions += " ";
  1007. libMultiLineOptions += "# ADD LINK32 ";
  1008. libMultiLineOptions += targetLinkFlags;
  1009. libMultiLineOptions += " \n";
  1010. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  1011. libMultiLineOptionsForDebug += targetLinkFlags;
  1012. libMultiLineOptionsForDebug += " \n";
  1013. }
  1014. // are there any custom rules on the target itself
  1015. // only if the target is a lib or exe
  1016. std::string customRuleCode = this->CreateTargetRules(target, libName);
  1017. std::ifstream fin(this->DSPHeaderTemplate.c_str());
  1018. if(!fin)
  1019. {
  1020. cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
  1021. }
  1022. std::string staticLibOptions;
  1023. if(target.GetType() == cmTarget::STATIC_LIBRARY )
  1024. {
  1025. if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
  1026. {
  1027. staticLibOptions = libflags;
  1028. }
  1029. }
  1030. std::string exportSymbol;
  1031. if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
  1032. {
  1033. exportSymbol = custom_export_name;
  1034. }
  1035. else
  1036. {
  1037. std::string in = libName;
  1038. in += "_EXPORTS";
  1039. exportSymbol = cmSystemTools::MakeCindentifier(in.c_str());
  1040. }
  1041. std::string line;
  1042. while(cmSystemTools::GetLineFromStream(fin, line))
  1043. {
  1044. const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
  1045. if(!mfcFlag)
  1046. {
  1047. mfcFlag = "0";
  1048. }
  1049. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
  1050. exportSymbol.c_str());
  1051. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
  1052. customRuleCode.c_str());
  1053. cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
  1054. mfcFlag);
  1055. if(target.GetType() == cmTarget::STATIC_LIBRARY )
  1056. {
  1057. cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS",
  1058. staticLibOptions.c_str());
  1059. }
  1060. if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
  1061. {
  1062. cmSystemTools::ReplaceString(line, "/nologo", "");
  1063. }
  1064. cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
  1065. libOptions.c_str());
  1066. cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
  1067. libDebugOptions.c_str());
  1068. cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
  1069. libOptimizedOptions.c_str());
  1070. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
  1071. libMultiLineOptionsForDebug.c_str());
  1072. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
  1073. libMultiLineOptions.c_str());
  1074. cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
  1075. libMultiLineDebugOptions.c_str());
  1076. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
  1077. libMultiLineOptimizedOptions.c_str());
  1078. // Replace the template file text OUTPUT_NAME with the real output
  1079. // name that will be used. Only the executable template should
  1080. // have this text.
  1081. cmSystemTools::ReplaceString(line, "OUTPUT_NAME", outputName.c_str());
  1082. cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
  1083. this->IncludeOptions.c_str());
  1084. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  1085. // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
  1086. // are already quoted in the template file,
  1087. // we need to remove the quotes here, we still need
  1088. // to convert to output path for unix to win32 conversion
  1089. cmSystemTools::ReplaceString(line, "LIBRARY_OUTPUT_PATH",
  1090. removeQuotes(
  1091. this->ConvertToOptionallyRelativeOutputPath(libPath.c_str())).c_str());
  1092. cmSystemTools::ReplaceString(line, "EXECUTABLE_OUTPUT_PATH",
  1093. removeQuotes(
  1094. this->ConvertToOptionallyRelativeOutputPath(exePath.c_str())).c_str());
  1095. cmSystemTools::ReplaceString(line,
  1096. "EXTRA_DEFINES",
  1097. this->Makefile->GetDefineFlags());
  1098. const char* debugPostfix
  1099. = this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
  1100. cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
  1101. debugPostfix?debugPostfix:"");
  1102. // store flags for each configuration
  1103. std::string flags = " ";
  1104. std::string flagsRelease = " ";
  1105. std::string flagsMinSize = " ";
  1106. std::string flagsDebug = " ";
  1107. std::string flagsDebugRel = " ";
  1108. if(target.GetType() >= cmTarget::EXECUTABLE &&
  1109. target.GetType() <= cmTarget::MODULE_LIBRARY)
  1110. {
  1111. const char* linkLanguage = target.GetLinkerLanguage(this->GetGlobalGenerator());
  1112. if(!linkLanguage)
  1113. {
  1114. cmSystemTools::Error("CMake can not determine linker language for target:",
  1115. target.GetName());
  1116. return;
  1117. }
  1118. // if CXX is on and the target contains cxx code then add the cxx flags
  1119. std::string baseFlagVar = "CMAKE_";
  1120. baseFlagVar += linkLanguage;
  1121. baseFlagVar += "_FLAGS";
  1122. flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
  1123. std::string flagVar = baseFlagVar + "_RELEASE";
  1124. flagsRelease = this->Makefile->GetRequiredDefinition(flagVar.c_str());
  1125. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
  1126. flagVar = baseFlagVar + "_MINSIZEREL";
  1127. flagsMinSize = this->Makefile->GetRequiredDefinition(flagVar.c_str());
  1128. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
  1129. flagVar = baseFlagVar + "_DEBUG";
  1130. flagsDebug = this->Makefile->GetRequiredDefinition(flagVar.c_str());
  1131. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
  1132. flagVar = baseFlagVar + "_RELWITHDEBINFO";
  1133. flagsDebugRel = this->Makefile->GetRequiredDefinition(flagVar.c_str());
  1134. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
  1135. }
  1136. // if unicode is not found, then add -D_MBCS
  1137. std::string defs = this->Makefile->GetDefineFlags();
  1138. if(flags.find("D_UNICODE") == flags.npos &&
  1139. defs.find("D_UNICODE") == flags.npos)
  1140. {
  1141. flags += " /D \"_MBCS\"";
  1142. }
  1143. // Add per-target flags.
  1144. if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
  1145. {
  1146. flags += " ";
  1147. flags += targetFlags;
  1148. }
  1149. // The template files have CXX FLAGS in them, that need to be replaced.
  1150. // There are not separate CXX and C template files, so we use the same
  1151. // variable names. The previous code sets up flags* variables to contain
  1152. // the correct C or CXX flags
  1153. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", flagsMinSize.c_str());
  1154. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str());
  1155. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO", flagsDebugRel.c_str());
  1156. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str());
  1157. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
  1158. fout << line.c_str() << std::endl;
  1159. }
  1160. }
  1161. void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
  1162. {
  1163. std::ifstream fin(this->DSPFooterTemplate.c_str());
  1164. if(!fin)
  1165. {
  1166. cmSystemTools::Error("Error Reading ",
  1167. this->DSPFooterTemplate.c_str());
  1168. }
  1169. std::string line;
  1170. while(cmSystemTools::GetLineFromStream(fin, line))
  1171. {
  1172. fout << line << std::endl;
  1173. }
  1174. }