You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1586 lines
53 KiB

23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
19 years ago
23 years ago
19 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
22 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
  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::AddHelperCommands()
  28. {
  29. std::set<cmStdString> lang;
  30. lang.insert("C");
  31. lang.insert("CXX");
  32. this->CreateCustomTargetsAndCommands(lang);
  33. }
  34. void cmLocalVisualStudio6Generator::Generate()
  35. {
  36. this->OutputDSPFile();
  37. }
  38. void cmLocalVisualStudio6Generator::OutputDSPFile()
  39. {
  40. // If not an in source build, then create the output directory
  41. if(strcmp(this->Makefile->GetStartOutputDirectory(),
  42. this->Makefile->GetHomeDirectory()) != 0)
  43. {
  44. if(!cmSystemTools::MakeDirectory
  45. (this->Makefile->GetStartOutputDirectory()))
  46. {
  47. cmSystemTools::Error("Error creating directory ",
  48. this->Makefile->GetStartOutputDirectory());
  49. }
  50. }
  51. // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
  52. // truncates long include paths so make it as short as possible if
  53. // the length threatents this problem.
  54. unsigned int maxIncludeLength = 3000;
  55. bool useShortPath = false;
  56. for(int j=0; j < 2; ++j)
  57. {
  58. std::vector<std::string> includes;
  59. this->GetIncludeDirectories(includes);
  60. std::vector<std::string>::iterator i;
  61. for(i = includes.begin(); i != includes.end(); ++i)
  62. {
  63. std::string tmp =
  64. this->ConvertToOptionallyRelativeOutputPath(i->c_str());
  65. if(useShortPath)
  66. {
  67. cmSystemTools::GetShortPath(tmp.c_str(), tmp);
  68. }
  69. this->IncludeOptions += " /I ";
  70. // quote if not already quoted
  71. if (tmp[0] != '"')
  72. {
  73. this->IncludeOptions += "\"";
  74. this->IncludeOptions += tmp;
  75. this->IncludeOptions += "\"";
  76. }
  77. else
  78. {
  79. this->IncludeOptions += tmp;
  80. }
  81. }
  82. if(j == 0 && this->IncludeOptions.size() > maxIncludeLength)
  83. {
  84. this->IncludeOptions = "";
  85. useShortPath = true;
  86. }
  87. else
  88. {
  89. break;
  90. }
  91. }
  92. // Create the DSP or set of DSP's for libraries and executables
  93. // clear project names
  94. this->CreatedProjectNames.clear();
  95. cmTargets &tgts = this->Makefile->GetTargets();
  96. for(cmTargets::iterator l = tgts.begin();
  97. l != tgts.end(); l++)
  98. {
  99. // Add a rule to regenerate the build system when the target
  100. // specification source changes.
  101. const char* suppRegenRule =
  102. this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
  103. if (!cmSystemTools::IsOn(suppRegenRule))
  104. {
  105. this->AddDSPBuildRule(l->second);
  106. }
  107. }
  108. // build any targets
  109. for(cmTargets::iterator l = tgts.begin();
  110. l != tgts.end(); l++)
  111. {
  112. switch(l->second.GetType())
  113. {
  114. case cmTarget::STATIC_LIBRARY:
  115. this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
  116. break;
  117. case cmTarget::SHARED_LIBRARY:
  118. case cmTarget::MODULE_LIBRARY:
  119. this->SetBuildType(DLL, l->first.c_str(), l->second);
  120. break;
  121. case cmTarget::EXECUTABLE:
  122. this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
  123. break;
  124. case cmTarget::UTILITY:
  125. case cmTarget::GLOBAL_TARGET:
  126. this->SetBuildType(UTILITY, l->first.c_str(), l->second);
  127. break;
  128. default:
  129. cmSystemTools::Error("Bad target type", l->first.c_str());
  130. break;
  131. }
  132. // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
  133. // so don't build a projectfile for it
  134. if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
  135. {
  136. // check to see if the dsp is going into a sub-directory
  137. std::string::size_type pos = l->first.rfind('/');
  138. if(pos != std::string::npos)
  139. {
  140. std::string dir = this->Makefile->GetStartOutputDirectory();
  141. dir += "/";
  142. dir += l->first.substr(0, pos);
  143. if(!cmSystemTools::MakeDirectory(dir.c_str()))
  144. {
  145. cmSystemTools::Error("Error creating directory ", dir.c_str());
  146. }
  147. }
  148. this->CreateSingleDSP(l->first.c_str(),l->second);
  149. }
  150. }
  151. }
  152. void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname,
  153. cmTarget &target)
  154. {
  155. // add to the list of projects
  156. std::string pname = lname;
  157. this->CreatedProjectNames.push_back(pname);
  158. // create the dsp.cmake file
  159. std::string fname;
  160. fname = this->Makefile->GetStartOutputDirectory();
  161. fname += "/";
  162. fname += lname;
  163. fname += ".dsp";
  164. // save the name of the real dsp file
  165. std::string realDSP = fname;
  166. fname += ".cmake";
  167. std::ofstream fout(fname.c_str());
  168. if(!fout)
  169. {
  170. cmSystemTools::Error("Error Writing ", fname.c_str());
  171. cmSystemTools::ReportLastSystemError("");
  172. }
  173. this->WriteDSPFile(fout,lname,target);
  174. fout.close();
  175. // if the dsp file has changed, then write it.
  176. cmSystemTools::CopyFileIfDifferent(fname.c_str(), realDSP.c_str());
  177. }
  178. void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt)
  179. {
  180. std::string dspname = tgt.GetName();
  181. dspname += ".dsp.cmake";
  182. const char* dsprule =
  183. this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
  184. cmCustomCommandLine commandLine;
  185. commandLine.push_back(dsprule);
  186. std::string makefileIn = this->Makefile->GetStartDirectory();
  187. makefileIn += "/";
  188. makefileIn += "CMakeLists.txt";
  189. std::string comment = "Building Custom Rule ";
  190. comment += makefileIn;
  191. std::string args;
  192. args = "-H";
  193. args += this->Convert(this->Makefile->GetHomeDirectory(),
  194. START_OUTPUT, UNCHANGED, true);
  195. commandLine.push_back(args);
  196. args = "-B";
  197. args +=
  198. this->Convert(this->Makefile->GetHomeOutputDirectory(),
  199. START_OUTPUT, UNCHANGED, true);
  200. commandLine.push_back(args);
  201. std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
  202. cmCustomCommandLines commandLines;
  203. commandLines.push_back(commandLine);
  204. const char* no_working_directory = 0;
  205. this->Makefile->AddCustomCommandToOutput(dspname.c_str(), listFiles,
  206. makefileIn.c_str(), commandLines,
  207. comment.c_str(),
  208. no_working_directory, true);
  209. if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
  210. {
  211. tgt.AddSourceFile(file);
  212. }
  213. else
  214. {
  215. cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
  216. }
  217. }
  218. void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
  219. const char *libName,
  220. cmTarget &target)
  221. {
  222. // For utility targets need custom command since pre- and post-
  223. // build does not do anything in Visual Studio 6. In order for the
  224. // rules to run in the correct order as custom commands, we need
  225. // special care for dependencies. The first rule must depend on all
  226. // the dependencies of all the rules. The later rules must each
  227. // depend only on the previous rule.
  228. if ((target.GetType() == cmTarget::UTILITY ||
  229. target.GetType() == cmTarget::GLOBAL_TARGET) &&
  230. (!target.GetPreBuildCommands().empty() ||
  231. !target.GetPostBuildCommands().empty()))
  232. {
  233. // Accumulate the dependencies of all the commands.
  234. std::vector<std::string> depends;
  235. for (std::vector<cmCustomCommand>::const_iterator cr =
  236. target.GetPreBuildCommands().begin();
  237. cr != target.GetPreBuildCommands().end(); ++cr)
  238. {
  239. depends.insert(depends.end(),
  240. cr->GetDepends().begin(), cr->GetDepends().end());
  241. }
  242. for (std::vector<cmCustomCommand>::const_iterator cr =
  243. target.GetPostBuildCommands().begin();
  244. cr != target.GetPostBuildCommands().end(); ++cr)
  245. {
  246. depends.insert(depends.end(),
  247. cr->GetDepends().begin(), cr->GetDepends().end());
  248. }
  249. // Add the pre- and post-build commands in order.
  250. int count = 1;
  251. for (std::vector<cmCustomCommand>::const_iterator cr =
  252. target.GetPreBuildCommands().begin();
  253. cr != target.GetPreBuildCommands().end(); ++cr)
  254. {
  255. this->AddUtilityCommandHack(target, count++, depends, *cr);
  256. }
  257. for (std::vector<cmCustomCommand>::const_iterator cr =
  258. target.GetPostBuildCommands().begin();
  259. cr != target.GetPostBuildCommands().end(); ++cr)
  260. {
  261. this->AddUtilityCommandHack(target, count++, depends, *cr);
  262. }
  263. }
  264. // trace the visual studio dependencies
  265. std::string name = libName;
  266. name += ".dsp.cmake";
  267. // We may be modifying the source groups temporarily, so make a copy.
  268. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
  269. // get the classes from the source lists then add them to the groups
  270. std::vector<cmSourceFile*> const & classes = target.GetSourceFiles();
  271. // now all of the source files have been properly assigned to the target
  272. // now stick them into source groups using the reg expressions
  273. for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
  274. i != classes.end(); i++)
  275. {
  276. // Add the file to the list of sources.
  277. std::string source = (*i)->GetFullPath();
  278. cmSourceGroup& sourceGroup =
  279. this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
  280. sourceGroup.AssignSource(*i);
  281. // while we are at it, if it is a .rule file then for visual studio 6 we
  282. // must generate it
  283. if ((*i)->GetExtension() == "rule")
  284. {
  285. if(!cmSystemTools::FileExists(source.c_str()))
  286. {
  287. cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
  288. #if defined(_WIN32) || defined(__CYGWIN__)
  289. std::ofstream fout(source.c_str(),
  290. std::ios::binary | std::ios::out
  291. | std::ios::trunc);
  292. #else
  293. std::ofstream fout(source.c_str(),
  294. std::ios::out | std::ios::trunc);
  295. #endif
  296. if(fout)
  297. {
  298. fout.write("# generated from CMake",22);
  299. fout.flush();
  300. fout.close();
  301. }
  302. }
  303. }
  304. }
  305. // Compute which sources need unique object computation.
  306. this->ComputeObjectNameRequirements(sourceGroups);
  307. // Write the DSP file's header.
  308. this->WriteDSPHeader(fout, libName, target, sourceGroups);
  309. // Loop through every source group.
  310. for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
  311. sg != sourceGroups.end(); ++sg)
  312. {
  313. this->WriteGroup(&(*sg), target, fout, libName);
  314. }
  315. // Write the DSP file's footer.
  316. this->WriteDSPFooter(fout);
  317. }
  318. void cmLocalVisualStudio6Generator
  319. ::WriteGroup(const cmSourceGroup *sg, cmTarget target,
  320. std::ostream &fout, const char *libName)
  321. {
  322. const std::vector<const cmSourceFile *> &sourceFiles =
  323. sg->GetSourceFiles();
  324. // If the group is empty, don't write it at all.
  325. if(sourceFiles.empty())
  326. {
  327. return;
  328. }
  329. // If the group has a name, write the header.
  330. std::string name = sg->GetName();
  331. if(name != "")
  332. {
  333. this->WriteDSPBeginGroup(fout, name.c_str(), "");
  334. }
  335. // Compute the maximum length of a configuration name.
  336. std::string::size_type config_len_max = 0;
  337. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  338. i != this->Configurations.end(); ++i)
  339. {
  340. // Strip the subdirectory name out of the configuration name.
  341. std::string config = this->GetConfigName(*i);
  342. if(config.size() > config_len_max)
  343. {
  344. config_len_max = config.size();
  345. }
  346. }
  347. // Compute the maximum length of the full path to the intermediate
  348. // files directory for any configuration. This is used to construct
  349. // object file names that do not produce paths that are too long.
  350. std::string::size_type dir_len = 0;
  351. dir_len += strlen(this->Makefile->GetCurrentOutputDirectory());
  352. dir_len += 1;
  353. dir_len += config_len_max;
  354. dir_len += 1;
  355. // Loop through each source in the source group.
  356. for(std::vector<const cmSourceFile *>::const_iterator sf =
  357. sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
  358. {
  359. std::string source = (*sf)->GetFullPath();
  360. const cmCustomCommand *command =
  361. (*sf)->GetCustomCommand();
  362. std::string compileFlags;
  363. std::vector<std::string> depends;
  364. std::string objectNameDir;
  365. if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
  366. {
  367. objectNameDir =
  368. cmSystemTools::GetFilenamePath(
  369. this->GetObjectFileNameWithoutTarget(*(*sf), dir_len));
  370. }
  371. // Add per-source file flags.
  372. if(const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS"))
  373. {
  374. compileFlags += cflags;
  375. }
  376. const char* lang = this->GetSourceFileLanguage(*(*sf));
  377. if(lang)
  378. {
  379. if(strcmp(lang, "CXX") == 0)
  380. {
  381. // force a C++ file type
  382. compileFlags += " /TP ";
  383. }
  384. else if(strcmp(lang, "C") == 0)
  385. {
  386. // force to c file type
  387. compileFlags += " /TC ";
  388. }
  389. }
  390. bool excludedFromBuild =
  391. (lang && (*sf)->GetPropertyAsBool("HEADER_FILE_ONLY"));
  392. // Check for extra object-file dependencies.
  393. const char* dependsValue = (*sf)->GetProperty("OBJECT_DEPENDS");
  394. if(dependsValue)
  395. {
  396. cmSystemTools::ExpandListArgument(dependsValue, depends);
  397. }
  398. if (source != libName || target.GetType() == cmTarget::UTILITY ||
  399. target.GetType() == cmTarget::GLOBAL_TARGET)
  400. {
  401. fout << "# Begin Source File\n\n";
  402. // Tell MS-Dev what the source is. If the compiler knows how to
  403. // build it, then it will.
  404. fout << "SOURCE=" <<
  405. this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n";
  406. if(!depends.empty())
  407. {
  408. // Write out the dependencies for the rule.
  409. fout << "USERDEP__HACK=";
  410. for(std::vector<std::string>::const_iterator d = depends.begin();
  411. d != depends.end(); ++d)
  412. {
  413. fout << "\\\n\t" <<
  414. this->ConvertToOptionallyRelativeOutputPath(d->c_str());
  415. }
  416. fout << "\n";
  417. }
  418. if (command)
  419. {
  420. const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
  421. this->WriteCustomRule(fout, source.c_str(), *command, flags);
  422. }
  423. else if(!compileFlags.empty() || !objectNameDir.empty() ||
  424. excludedFromBuild)
  425. {
  426. for(std::vector<std::string>::iterator i
  427. = this->Configurations.begin();
  428. i != this->Configurations.end(); ++i)
  429. {
  430. if (i == this->Configurations.begin())
  431. {
  432. fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
  433. }
  434. else
  435. {
  436. fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
  437. }
  438. if(excludedFromBuild)
  439. {
  440. fout << "# PROP Exclude_From_Build 1\n";
  441. }
  442. if(!compileFlags.empty())
  443. {
  444. fout << "\n# ADD CPP " << compileFlags << "\n\n";
  445. }
  446. if(!objectNameDir.empty())
  447. {
  448. // Strip the subdirectory name out of the configuration name.
  449. std::string config = this->GetConfigName(*i);
  450. // Setup an alternate object file directory.
  451. fout << "\n# PROP Intermediate_Dir \""
  452. << config << "/" << objectNameDir << "\"\n\n";
  453. }
  454. }
  455. fout << "!ENDIF\n\n";
  456. }
  457. fout << "# End Source File\n";
  458. }
  459. }
  460. std::vector<cmSourceGroup> children = sg->GetGroupChildren();
  461. for(unsigned int i=0;i<children.size();++i)
  462. {
  463. this->WriteGroup(&children[i], target, fout, libName);
  464. }
  465. // If the group has a name, write the footer.
  466. if(name != "")
  467. {
  468. this->WriteDSPEndGroup(fout);
  469. }
  470. }
  471. void
  472. cmLocalVisualStudio6Generator
  473. ::AddUtilityCommandHack(cmTarget& target, int count,
  474. std::vector<std::string>& depends,
  475. const cmCustomCommand& origCommand)
  476. {
  477. // Create a fake output that forces the rule to run.
  478. char* output = new char[(strlen(this->Makefile->GetStartOutputDirectory()) +
  479. strlen(target.GetName()) + 30)];
  480. sprintf(output,"%s/%s_force_%i", this->Makefile->GetStartOutputDirectory(),
  481. target.GetName(), count);
  482. std::string comment = this->ConstructComment(origCommand, "<hack>");
  483. // Add the rule with the given dependencies and commands.
  484. const char* no_main_dependency = 0;
  485. this->Makefile->AddCustomCommandToOutput(output,
  486. depends,
  487. no_main_dependency,
  488. origCommand.GetCommandLines(),
  489. comment.c_str(),
  490. origCommand.GetWorkingDirectory());
  491. // Replace the dependencies with the output of this rule so that the
  492. // next rule added will run after this one.
  493. depends.clear();
  494. depends.push_back(output);
  495. // Add a source file representing this output to the project.
  496. cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output);
  497. target.AddSourceFile(outsf);
  498. // Free the fake output name.
  499. delete [] output;
  500. }
  501. void
  502. cmLocalVisualStudio6Generator
  503. ::WriteCustomRule(std::ostream& fout,
  504. const char* source,
  505. const cmCustomCommand& command,
  506. const char* flags)
  507. {
  508. std::string comment =
  509. this->ConstructComment(command, "Building Custom Rule $(InputPath)");
  510. if(comment == "<hack>")
  511. {
  512. comment = "";
  513. }
  514. // Write the rule for each configuration.
  515. std::vector<std::string>::iterator i;
  516. for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
  517. {
  518. std::string config = this->GetConfigName(*i);
  519. std::string script =
  520. this->ConstructScript(command.GetCommandLines(),
  521. command.GetWorkingDirectory(),
  522. config.c_str(),
  523. command.GetEscapeOldStyle(),
  524. command.GetEscapeAllowMakeVars(),
  525. "\\\n\t");
  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 =
  541. command.GetDepends().begin();
  542. d != command.GetDepends().end();
  543. ++d)
  544. {
  545. // Lookup the real name of the dependency in case it is a CMake target.
  546. std::string dep = this->GetRealDependency(d->c_str(),
  547. config.c_str());
  548. fout << "\\\n\t" <<
  549. this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
  550. }
  551. fout << "\n";
  552. fout << "# PROP Ignore_Default_Tool 1\n";
  553. fout << "# Begin Custom Build -";
  554. if(!comment.empty())
  555. {
  556. fout << " " << comment.c_str();
  557. }
  558. fout << "\n\n";
  559. if(command.GetOutputs().empty())
  560. {
  561. fout << source
  562. << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
  563. fout << script.c_str() << "\n\n";
  564. }
  565. else
  566. {
  567. for(std::vector<std::string>::const_iterator o =
  568. command.GetOutputs().begin();
  569. o != command.GetOutputs().end();
  570. ++o)
  571. {
  572. // Write a rule for every output generated by this command.
  573. fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str())
  574. << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
  575. fout << script.c_str() << "\n\n";
  576. }
  577. }
  578. fout << "# End Custom Build\n\n";
  579. }
  580. fout << "!ENDIF\n\n";
  581. }
  582. void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout,
  583. const char* group,
  584. const char* filter)
  585. {
  586. fout << "# Begin Group \"" << group << "\"\n"
  587. "# PROP Default_Filter \"" << filter << "\"\n";
  588. }
  589. void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
  590. {
  591. fout << "# End Group\n";
  592. }
  593. void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
  594. const char* libName,
  595. cmTarget& target)
  596. {
  597. std::string root= this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
  598. const char *def=
  599. this->Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
  600. if( def)
  601. {
  602. root = def;
  603. }
  604. else
  605. {
  606. root += "/Templates";
  607. }
  608. switch(b)
  609. {
  610. case STATIC_LIBRARY:
  611. this->DSPHeaderTemplate = root;
  612. this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
  613. this->DSPFooterTemplate = root;
  614. this->DSPFooterTemplate += "/staticLibFooter.dsptemplate";
  615. break;
  616. case DLL:
  617. this->DSPHeaderTemplate = root;
  618. this->DSPHeaderTemplate += "/DLLHeader.dsptemplate";
  619. this->DSPFooterTemplate = root;
  620. this->DSPFooterTemplate += "/DLLFooter.dsptemplate";
  621. break;
  622. case EXECUTABLE:
  623. if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
  624. {
  625. this->DSPHeaderTemplate = root;
  626. this->DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
  627. this->DSPFooterTemplate = root;
  628. this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
  629. }
  630. else
  631. {
  632. this->DSPHeaderTemplate = root;
  633. this->DSPHeaderTemplate += "/EXEHeader.dsptemplate";
  634. this->DSPFooterTemplate = root;
  635. this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
  636. }
  637. break;
  638. case UTILITY:
  639. this->DSPHeaderTemplate = root;
  640. this->DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
  641. this->DSPFooterTemplate = root;
  642. this->DSPFooterTemplate += "/UtilityFooter.dsptemplate";
  643. break;
  644. }
  645. // once the build type is set, determine what configurations are
  646. // possible
  647. std::ifstream fin(this->DSPHeaderTemplate.c_str());
  648. cmsys::RegularExpression reg("# Name ");
  649. if(!fin)
  650. {
  651. cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
  652. }
  653. // reset this->Configurations
  654. this->Configurations.erase(this->Configurations.begin(),
  655. this->Configurations.end());
  656. // now add all the configurations possible
  657. std::string line;
  658. while(cmSystemTools::GetLineFromStream(fin, line))
  659. {
  660. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  661. if (reg.find(line))
  662. {
  663. this->Configurations.push_back(line.substr(reg.end()));
  664. }
  665. }
  666. }
  667. // look for custom rules on a target and collect them together
  668. std::string
  669. cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
  670. const char* configName,
  671. const char * /* libName */)
  672. {
  673. std::string customRuleCode = "";
  674. if (target.GetType() >= cmTarget::UTILITY )
  675. {
  676. return customRuleCode;
  677. }
  678. // are there any rules?
  679. if (target.GetPreBuildCommands().size() +
  680. target.GetPreLinkCommands().size() +
  681. target.GetPostBuildCommands().size() == 0)
  682. {
  683. return customRuleCode;
  684. }
  685. customRuleCode = "# Begin Special Build Tool\n";
  686. // Write the pre-build and pre-link together (VS6 does not support
  687. // both). Make sure no continuation character is put on the last
  688. // line.
  689. int prelink_total = (static_cast<int>(target.GetPreBuildCommands().size())+
  690. static_cast<int>(target.GetPreLinkCommands().size()));
  691. int prelink_count = 0;
  692. if(prelink_total > 0)
  693. {
  694. // header stuff
  695. customRuleCode += "PreLink_Cmds=";
  696. }
  697. for (std::vector<cmCustomCommand>::const_iterator cr =
  698. target.GetPreBuildCommands().begin();
  699. cr != target.GetPreBuildCommands().end(); ++cr)
  700. {
  701. if(prelink_count++ > 0)
  702. {
  703. customRuleCode += "\\\n\t";
  704. }
  705. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  706. cr->GetWorkingDirectory(),
  707. configName,
  708. cr->GetEscapeOldStyle(),
  709. cr->GetEscapeAllowMakeVars(),
  710. "\\\n\t");
  711. }
  712. for (std::vector<cmCustomCommand>::const_iterator cr =
  713. target.GetPreLinkCommands().begin();
  714. cr != target.GetPreLinkCommands().end(); ++cr)
  715. {
  716. if(prelink_count++ > 0)
  717. {
  718. customRuleCode += "\\\n\t";
  719. }
  720. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  721. cr->GetWorkingDirectory(),
  722. configName,
  723. cr->GetEscapeOldStyle(),
  724. cr->GetEscapeAllowMakeVars(),
  725. "\\\n\t");
  726. }
  727. if(prelink_total > 0)
  728. {
  729. customRuleCode += "\n";
  730. }
  731. // Write the post-build rules. Make sure no continuation character
  732. // is put on the last line.
  733. int postbuild_total =
  734. static_cast<int>(target.GetPostBuildCommands().size());
  735. int postbuild_count = 0;
  736. if(postbuild_total > 0)
  737. {
  738. customRuleCode += "PostBuild_Cmds=";
  739. }
  740. for (std::vector<cmCustomCommand>::const_iterator cr =
  741. target.GetPostBuildCommands().begin();
  742. cr != target.GetPostBuildCommands().end(); ++cr)
  743. {
  744. if(postbuild_count++ > 0)
  745. {
  746. customRuleCode += "\\\n\t";
  747. }
  748. customRuleCode += this->ConstructScript(cr->GetCommandLines(),
  749. cr->GetWorkingDirectory(),
  750. configName,
  751. cr->GetEscapeOldStyle(),
  752. cr->GetEscapeAllowMakeVars(),
  753. "\\\n\t");
  754. }
  755. if(postbuild_total > 0)
  756. {
  757. customRuleCode += "\n";
  758. }
  759. customRuleCode += "# End Special Build Tool\n";
  760. return customRuleCode;
  761. }
  762. inline std::string removeQuotes(const std::string& s)
  763. {
  764. if(s[0] == '\"' && s[s.size()-1] == '\"')
  765. {
  766. return s.substr(1, s.size()-2);
  767. }
  768. return s;
  769. }
  770. // Code in blocks surrounded by a test for this definition is needed
  771. // only for compatibility with user project's replacement DSP
  772. // templates. The CMake templates no longer use them.
  773. #define CM_USE_OLD_VS6
  774. void cmLocalVisualStudio6Generator
  775. ::WriteDSPHeader(std::ostream& fout,
  776. const char *libName, cmTarget &target,
  777. std::vector<cmSourceGroup> &)
  778. {
  779. // Lookup the output directory for the target.
  780. std::string outPath = target.GetDirectory();
  781. #ifdef CM_USE_OLD_VS6
  782. // Lookup the library and executable output directories.
  783. std::string libPath;
  784. if(this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
  785. {
  786. libPath = this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
  787. }
  788. std::string exePath;
  789. if(this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
  790. {
  791. exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  792. }
  793. // Make sure there are trailing slashes.
  794. if(!libPath.empty())
  795. {
  796. if(libPath[libPath.size()-1] != '/')
  797. {
  798. libPath += "/";
  799. }
  800. }
  801. if(!exePath.empty())
  802. {
  803. if(exePath[exePath.size()-1] != '/')
  804. {
  805. exePath += "/";
  806. }
  807. }
  808. std::set<std::string> pathEmitted;
  809. // determine the link directories
  810. std::string libOptions;
  811. std::string libDebugOptions;
  812. std::string libOptimizedOptions;
  813. std::string libMultiLineOptions;
  814. std::string libMultiLineOptionsForDebug;
  815. std::string libMultiLineDebugOptions;
  816. std::string libMultiLineOptimizedOptions;
  817. if(libPath.size())
  818. {
  819. std::string lpath =
  820. this->ConvertToOptionallyRelativeOutputPath(libPath.c_str());
  821. if(lpath.size() == 0)
  822. {
  823. lpath = ".";
  824. }
  825. std::string lpathIntDir = libPath + "$(INTDIR)";
  826. lpathIntDir =
  827. this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  828. if(pathEmitted.insert(lpath).second)
  829. {
  830. libOptions += " /LIBPATH:";
  831. libOptions += lpathIntDir;
  832. libOptions += " ";
  833. libOptions += " /LIBPATH:";
  834. libOptions += lpath;
  835. libOptions += " ";
  836. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  837. libMultiLineOptions += lpathIntDir;
  838. libMultiLineOptions += " ";
  839. libMultiLineOptions += " /LIBPATH:";
  840. libMultiLineOptions += lpath;
  841. libMultiLineOptions += " \n";
  842. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  843. libMultiLineOptionsForDebug += lpathIntDir;
  844. libMultiLineOptionsForDebug += " ";
  845. libMultiLineOptionsForDebug += " /LIBPATH:";
  846. libMultiLineOptionsForDebug += lpath;
  847. libMultiLineOptionsForDebug += " \n";
  848. }
  849. }
  850. if(exePath.size())
  851. {
  852. std::string lpath =
  853. this->ConvertToOptionallyRelativeOutputPath(exePath.c_str());
  854. if(lpath.size() == 0)
  855. {
  856. lpath = ".";
  857. }
  858. std::string lpathIntDir = exePath + "$(INTDIR)";
  859. lpathIntDir =
  860. this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  861. if(pathEmitted.insert(lpath).second)
  862. {
  863. libOptions += " /LIBPATH:";
  864. libOptions += lpathIntDir;
  865. libOptions += " ";
  866. libOptions += " /LIBPATH:";
  867. libOptions += lpath;
  868. libOptions += " ";
  869. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  870. libMultiLineOptions += lpathIntDir;
  871. libMultiLineOptions += " ";
  872. libMultiLineOptions += " /LIBPATH:";
  873. libMultiLineOptions += lpath;
  874. libMultiLineOptions += " \n";
  875. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  876. libMultiLineOptionsForDebug += lpathIntDir;
  877. libMultiLineOptionsForDebug += " ";
  878. libMultiLineOptionsForDebug += " /LIBPATH:";
  879. libMultiLineOptionsForDebug += lpath;
  880. libMultiLineOptionsForDebug += " \n";
  881. }
  882. }
  883. std::vector<std::string>::const_iterator i;
  884. const std::vector<std::string>& libdirs = target.GetLinkDirectories();
  885. for(i = libdirs.begin(); i != libdirs.end(); ++i)
  886. {
  887. std::string path = *i;
  888. if(path[path.size()-1] != '/')
  889. {
  890. path += "/";
  891. }
  892. std::string lpath =
  893. this->ConvertToOptionallyRelativeOutputPath(path.c_str());
  894. if(lpath.size() == 0)
  895. {
  896. lpath = ".";
  897. }
  898. std::string lpathIntDir = path + "$(INTDIR)";
  899. lpathIntDir =
  900. this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
  901. if(pathEmitted.insert(lpath).second)
  902. {
  903. libOptions += " /LIBPATH:";
  904. libOptions += lpathIntDir;
  905. libOptions += " ";
  906. libOptions += " /LIBPATH:";
  907. libOptions += lpath;
  908. libOptions += " ";
  909. libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
  910. libMultiLineOptions += lpathIntDir;
  911. libMultiLineOptions += " ";
  912. libMultiLineOptions += " /LIBPATH:";
  913. libMultiLineOptions += lpath;
  914. libMultiLineOptions += " \n";
  915. libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
  916. libMultiLineOptionsForDebug += lpathIntDir;
  917. libMultiLineOptionsForDebug += " ";
  918. libMultiLineOptionsForDebug += " /LIBPATH:";
  919. libMultiLineOptionsForDebug += lpath;
  920. libMultiLineOptionsForDebug += " \n";
  921. }
  922. }
  923. // find link libraries
  924. const cmTarget::LinkLibraryVectorType& libs = target.GetLinkLibraries();
  925. cmTarget::LinkLibraryVectorType::const_iterator j;
  926. for(j = libs.begin(); j != libs.end(); ++j)
  927. {
  928. // add libraries to executables and dlls (but never include
  929. // a library in a library, bad recursion)
  930. // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
  931. if ((target.GetType() != cmTarget::SHARED_LIBRARY
  932. && target.GetType() != cmTarget::STATIC_LIBRARY
  933. && target.GetType() != cmTarget::MODULE_LIBRARY) ||
  934. (target.GetType()==cmTarget::SHARED_LIBRARY && libName != j->first) ||
  935. (target.GetType()==cmTarget::MODULE_LIBRARY && libName != j->first))
  936. {
  937. // Compute the proper name to use to link this library.
  938. std::string lib;
  939. std::string libDebug;
  940. cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str(),
  941. false);
  942. if(tgt)
  943. {
  944. lib = cmSystemTools::GetFilenameWithoutExtension
  945. (tgt->GetFullName().c_str());
  946. libDebug = cmSystemTools::GetFilenameWithoutExtension
  947. (tgt->GetFullName("Debug").c_str());
  948. lib += ".lib";
  949. libDebug += ".lib";
  950. }
  951. else
  952. {
  953. lib = j->first.c_str();
  954. libDebug = j->first.c_str();
  955. if(j->first.find(".lib") == std::string::npos)
  956. {
  957. lib += ".lib";
  958. libDebug += ".lib";
  959. }
  960. }
  961. lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
  962. libDebug =
  963. this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
  964. if (j->second == cmTarget::GENERAL)
  965. {
  966. libOptions += " ";
  967. libOptions += lib;
  968. libMultiLineOptions += "# ADD LINK32 ";
  969. libMultiLineOptions += lib;
  970. libMultiLineOptions += "\n";
  971. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  972. libMultiLineOptionsForDebug += libDebug;
  973. libMultiLineOptionsForDebug += "\n";
  974. }
  975. if (j->second == cmTarget::DEBUG)
  976. {
  977. libDebugOptions += " ";
  978. libDebugOptions += lib;
  979. libMultiLineDebugOptions += "# ADD LINK32 ";
  980. libMultiLineDebugOptions += libDebug;
  981. libMultiLineDebugOptions += "\n";
  982. }
  983. if (j->second == cmTarget::OPTIMIZED)
  984. {
  985. libOptimizedOptions += " ";
  986. libOptimizedOptions += lib;
  987. libMultiLineOptimizedOptions += "# ADD LINK32 ";
  988. libMultiLineOptimizedOptions += lib;
  989. libMultiLineOptimizedOptions += "\n";
  990. }
  991. }
  992. }
  993. #endif
  994. // Get extra linker options for this target type.
  995. std::string extraLinkOptions;
  996. if(target.GetType() == cmTarget::EXECUTABLE)
  997. {
  998. extraLinkOptions =
  999. this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
  1000. }
  1001. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  1002. {
  1003. extraLinkOptions =
  1004. this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
  1005. }
  1006. if(target.GetType() == cmTarget::MODULE_LIBRARY)
  1007. {
  1008. extraLinkOptions =
  1009. this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
  1010. }
  1011. // Get extra linker options for this target.
  1012. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
  1013. {
  1014. extraLinkOptions += " ";
  1015. extraLinkOptions += targetLinkFlags;
  1016. }
  1017. // Get standard libraries for this language.
  1018. if(target.GetType() >= cmTarget::EXECUTABLE &&
  1019. target.GetType() <= cmTarget::MODULE_LIBRARY)
  1020. {
  1021. // Get the language to use for linking.
  1022. const char* linkLanguage =
  1023. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1024. if(!linkLanguage)
  1025. {
  1026. cmSystemTools::Error
  1027. ("CMake can not determine linker language for target:",
  1028. target.GetName());
  1029. return;
  1030. }
  1031. // Compute the variable name to lookup standard libraries for this
  1032. // language.
  1033. std::string standardLibsVar = "CMAKE_";
  1034. standardLibsVar += linkLanguage;
  1035. standardLibsVar += "_STANDARD_LIBRARIES";
  1036. // Add standard libraries.
  1037. if(const char* stdLibs =
  1038. this->Makefile->GetDefinition(standardLibsVar.c_str()))
  1039. {
  1040. extraLinkOptions += " ";
  1041. extraLinkOptions += stdLibs;
  1042. }
  1043. }
  1044. // Compute version number information.
  1045. std::string targetVersionFlag;
  1046. if(target.GetType() == cmTarget::EXECUTABLE ||
  1047. target.GetType() == cmTarget::SHARED_LIBRARY ||
  1048. target.GetType() == cmTarget::MODULE_LIBRARY)
  1049. {
  1050. int major;
  1051. int minor;
  1052. target.GetTargetVersion(major, minor);
  1053. cmOStringStream targetVersionStream;
  1054. targetVersionStream << "/version:" << major << "." << minor;
  1055. targetVersionFlag = targetVersionStream.str();
  1056. }
  1057. // Compute the real name of the target.
  1058. std::string outputName =
  1059. "(OUTPUT_NAME is for libraries and executables only)";
  1060. std::string outputNameDebug = outputName;
  1061. std::string outputNameRelease = outputName;
  1062. std::string outputNameMinSizeRel = outputName;
  1063. std::string outputNameRelWithDebInfo = outputName;
  1064. if(target.GetType() == cmTarget::EXECUTABLE ||
  1065. target.GetType() == cmTarget::STATIC_LIBRARY ||
  1066. target.GetType() == cmTarget::SHARED_LIBRARY ||
  1067. target.GetType() == cmTarget::MODULE_LIBRARY)
  1068. {
  1069. outputName = target.GetFullName();
  1070. outputNameDebug = target.GetFullName("Debug");
  1071. outputNameRelease = target.GetFullName("Release");
  1072. outputNameMinSizeRel = target.GetFullName("MinSizeRel");
  1073. outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
  1074. }
  1075. // Compute the proper link information for the target.
  1076. std::string optionsDebug;
  1077. std::string optionsRelease;
  1078. std::string optionsMinSizeRel;
  1079. std::string optionsRelWithDebInfo;
  1080. if(target.GetType() == cmTarget::EXECUTABLE ||
  1081. target.GetType() == cmTarget::SHARED_LIBRARY ||
  1082. target.GetType() == cmTarget::MODULE_LIBRARY)
  1083. {
  1084. this->ComputeLinkOptions(target, "Debug", extraLinkOptions,
  1085. optionsDebug);
  1086. this->ComputeLinkOptions(target, "Release", extraLinkOptions,
  1087. optionsRelease);
  1088. this->ComputeLinkOptions(target, "MinSizeRel", extraLinkOptions,
  1089. optionsMinSizeRel);
  1090. this->ComputeLinkOptions(target, "RelWithDebInfo", extraLinkOptions,
  1091. optionsRelWithDebInfo);
  1092. }
  1093. // Compute the path of the import library.
  1094. std::string targetImplibFlagDebug;
  1095. std::string targetImplibFlagRelease;
  1096. std::string targetImplibFlagMinSizeRel;
  1097. std::string targetImplibFlagRelWithDebInfo;
  1098. if(target.GetType() == cmTarget::SHARED_LIBRARY ||
  1099. target.GetType() == cmTarget::MODULE_LIBRARY ||
  1100. target.GetType() == cmTarget::EXECUTABLE)
  1101. {
  1102. std::string fullPathImpDebug = target.GetDirectory("Debug", true);
  1103. std::string fullPathImpRelease = target.GetDirectory("Release", true);
  1104. std::string fullPathImpMinSizeRel =
  1105. target.GetDirectory("MinSizeRel", true);
  1106. std::string fullPathImpRelWithDebInfo =
  1107. target.GetDirectory("RelWithDebInfo", true);
  1108. fullPathImpDebug += "/";
  1109. fullPathImpRelease += "/";
  1110. fullPathImpMinSizeRel += "/";
  1111. fullPathImpRelWithDebInfo += "/";
  1112. fullPathImpDebug += target.GetFullName("Debug", true);
  1113. fullPathImpRelease += target.GetFullName("Release", true);
  1114. fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true);
  1115. fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true);
  1116. targetImplibFlagDebug = "/implib:";
  1117. targetImplibFlagRelease = "/implib:";
  1118. targetImplibFlagMinSizeRel = "/implib:";
  1119. targetImplibFlagRelWithDebInfo = "/implib:";
  1120. targetImplibFlagDebug +=
  1121. this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug.c_str());
  1122. targetImplibFlagRelease +=
  1123. this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease.c_str());
  1124. targetImplibFlagMinSizeRel +=
  1125. this->ConvertToOptionallyRelativeOutputPath(
  1126. fullPathImpMinSizeRel.c_str());
  1127. targetImplibFlagRelWithDebInfo +=
  1128. this->ConvertToOptionallyRelativeOutputPath(
  1129. fullPathImpRelWithDebInfo.c_str());
  1130. }
  1131. #ifdef CM_USE_OLD_VS6
  1132. // Compute link information for the target.
  1133. if(extraLinkOptions.size())
  1134. {
  1135. libOptions += " ";
  1136. libOptions += extraLinkOptions;
  1137. libOptions += " ";
  1138. libMultiLineOptions += "# ADD LINK32 ";
  1139. libMultiLineOptions += extraLinkOptions;
  1140. libMultiLineOptions += " \n";
  1141. libMultiLineOptionsForDebug += "# ADD LINK32 ";
  1142. libMultiLineOptionsForDebug += extraLinkOptions;
  1143. libMultiLineOptionsForDebug += " \n";
  1144. }
  1145. #endif
  1146. // are there any custom rules on the target itself
  1147. // only if the target is a lib or exe
  1148. std::string customRuleCodeRelease
  1149. = this->CreateTargetRules(target, "RELEASE", libName);
  1150. std::string customRuleCodeDebug
  1151. = this->CreateTargetRules(target, "DEBUG", libName);
  1152. std::string customRuleCodeMinSizeRel
  1153. = this->CreateTargetRules(target, "MINSIZEREL", libName);
  1154. std::string customRuleCodeRelWithDebInfo
  1155. = this->CreateTargetRules(target, "RELWITHDEBINFO", libName);
  1156. std::ifstream fin(this->DSPHeaderTemplate.c_str());
  1157. if(!fin)
  1158. {
  1159. cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
  1160. }
  1161. std::string staticLibOptions;
  1162. if(target.GetType() == cmTarget::STATIC_LIBRARY )
  1163. {
  1164. if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
  1165. {
  1166. staticLibOptions = libflags;
  1167. }
  1168. }
  1169. // Add the export symbol definition for shared library objects.
  1170. std::string exportSymbol;
  1171. if(const char* exportMacro = target.GetExportMacro())
  1172. {
  1173. exportSymbol = exportMacro;
  1174. }
  1175. std::string line;
  1176. while(cmSystemTools::GetLineFromStream(fin, line))
  1177. {
  1178. const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
  1179. if(!mfcFlag)
  1180. {
  1181. mfcFlag = "0";
  1182. }
  1183. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
  1184. exportSymbol.c_str());
  1185. cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
  1186. mfcFlag);
  1187. if(target.GetType() == cmTarget::STATIC_LIBRARY )
  1188. {
  1189. cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS",
  1190. staticLibOptions.c_str());
  1191. }
  1192. if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
  1193. {
  1194. cmSystemTools::ReplaceString(line, "/nologo", "");
  1195. }
  1196. #ifdef CM_USE_OLD_VS6
  1197. cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
  1198. libOptions.c_str());
  1199. cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
  1200. libDebugOptions.c_str());
  1201. cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
  1202. libOptimizedOptions.c_str());
  1203. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
  1204. libMultiLineOptionsForDebug.c_str());
  1205. cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
  1206. libMultiLineOptions.c_str());
  1207. cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
  1208. libMultiLineDebugOptions.c_str());
  1209. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
  1210. libMultiLineOptimizedOptions.c_str());
  1211. #endif
  1212. // Substitute the rules for custom command. When specifying just the
  1213. // target name for the command the command can be different for
  1214. // different configs
  1215. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
  1216. customRuleCodeRelease.c_str());
  1217. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
  1218. customRuleCodeDebug.c_str());
  1219. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
  1220. customRuleCodeMinSizeRel.c_str());
  1221. cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
  1222. customRuleCodeRelWithDebInfo.c_str());
  1223. // Substitute the real output name into the template.
  1224. cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG",
  1225. outputNameDebug.c_str());
  1226. cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELEASE",
  1227. outputNameRelease.c_str());
  1228. cmSystemTools::ReplaceString(line, "OUTPUT_NAME_MINSIZEREL",
  1229. outputNameMinSizeRel.c_str());
  1230. cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELWITHDEBINFO",
  1231. outputNameRelWithDebInfo.c_str());
  1232. cmSystemTools::ReplaceString(line, "OUTPUT_NAME", outputName.c_str());
  1233. // Substitute the proper link information into the template.
  1234. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_DEBUG",
  1235. optionsDebug.c_str());
  1236. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELEASE",
  1237. optionsRelease.c_str());
  1238. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_MINSIZEREL",
  1239. optionsMinSizeRel.c_str());
  1240. cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
  1241. optionsRelWithDebInfo.c_str());
  1242. cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
  1243. this->IncludeOptions.c_str());
  1244. cmSystemTools::ReplaceString(line, "TARGET_VERSION_FLAG",
  1245. targetVersionFlag.c_str());
  1246. cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_DEBUG",
  1247. targetImplibFlagDebug.c_str());
  1248. cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELEASE",
  1249. targetImplibFlagRelease.c_str());
  1250. cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_MINSIZEREL",
  1251. targetImplibFlagMinSizeRel.c_str());
  1252. cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
  1253. targetImplibFlagRelWithDebInfo.c_str());
  1254. cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
  1255. #ifdef CM_USE_OLD_VS6
  1256. // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
  1257. // are already quoted in the template file,
  1258. // we need to remove the quotes here, we still need
  1259. // to convert to output path for unix to win32 conversion
  1260. cmSystemTools::ReplaceString
  1261. (line, "LIBRARY_OUTPUT_PATH",
  1262. removeQuotes(this->ConvertToOptionallyRelativeOutputPath
  1263. (libPath.c_str())).c_str());
  1264. cmSystemTools::ReplaceString
  1265. (line, "EXECUTABLE_OUTPUT_PATH",
  1266. removeQuotes(this->ConvertToOptionallyRelativeOutputPath
  1267. (exePath.c_str())).c_str());
  1268. #endif
  1269. cmSystemTools::ReplaceString
  1270. (line, "OUTPUT_DIRECTORY",
  1271. removeQuotes(this->ConvertToOptionallyRelativeOutputPath
  1272. (outPath.c_str())).c_str());
  1273. cmSystemTools::ReplaceString(line,
  1274. "EXTRA_DEFINES",
  1275. this->Makefile->GetDefineFlags());
  1276. const char* debugPostfix
  1277. = this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
  1278. cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
  1279. debugPostfix?debugPostfix:"");
  1280. // store flags for each configuration
  1281. std::string flags = " ";
  1282. std::string flagsRelease = " ";
  1283. std::string flagsMinSize = " ";
  1284. std::string flagsDebug = " ";
  1285. std::string flagsDebugRel = " ";
  1286. if(target.GetType() >= cmTarget::EXECUTABLE &&
  1287. target.GetType() <= cmTarget::MODULE_LIBRARY)
  1288. {
  1289. const char* linkLanguage =
  1290. target.GetLinkerLanguage(this->GetGlobalGenerator());
  1291. if(!linkLanguage)
  1292. {
  1293. cmSystemTools::Error
  1294. ("CMake can not determine linker language for target:",
  1295. target.GetName());
  1296. return;
  1297. }
  1298. // if CXX is on and the target contains cxx code then add the cxx flags
  1299. std::string baseFlagVar = "CMAKE_";
  1300. baseFlagVar += linkLanguage;
  1301. baseFlagVar += "_FLAGS";
  1302. flags = this->Makefile->GetSafeDefinition(baseFlagVar.c_str());
  1303. std::string flagVar = baseFlagVar + "_RELEASE";
  1304. flagsRelease = this->Makefile->GetSafeDefinition(flagVar.c_str());
  1305. flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
  1306. if(const char* targetLinkFlags =
  1307. target.GetProperty("LINK_FLAGS_RELEASE"))
  1308. {
  1309. flagsRelease += targetLinkFlags;
  1310. flagsRelease += " ";
  1311. }
  1312. flagVar = baseFlagVar + "_MINSIZEREL";
  1313. flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str());
  1314. flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
  1315. if(const char* targetLinkFlags =
  1316. target.GetProperty("LINK_FLAGS_MINSIZEREL"))
  1317. {
  1318. flagsMinSize += targetLinkFlags;
  1319. flagsMinSize += " ";
  1320. }
  1321. flagVar = baseFlagVar + "_DEBUG";
  1322. flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str());
  1323. flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
  1324. if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS_DEBUG"))
  1325. {
  1326. flagsDebug += targetLinkFlags;
  1327. flagsDebug += " ";
  1328. }
  1329. flagVar = baseFlagVar + "_RELWITHDEBINFO";
  1330. flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
  1331. flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
  1332. if(const char* targetLinkFlags =
  1333. target.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
  1334. {
  1335. flagsDebugRel += targetLinkFlags;
  1336. flagsDebugRel += " ";
  1337. }
  1338. }
  1339. // if unicode is not found, then add -D_MBCS
  1340. std::string defs = this->Makefile->GetDefineFlags();
  1341. if(flags.find("D_UNICODE") == flags.npos &&
  1342. defs.find("D_UNICODE") == flags.npos)
  1343. {
  1344. flags += " /D \"_MBCS\"";
  1345. }
  1346. // Add per-target flags.
  1347. if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
  1348. {
  1349. flags += " ";
  1350. flags += targetFlags;
  1351. }
  1352. // The template files have CXX FLAGS in them, that need to be replaced.
  1353. // There are not separate CXX and C template files, so we use the same
  1354. // variable names. The previous code sets up flags* variables to contain
  1355. // the correct C or CXX flags
  1356. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
  1357. flagsMinSize.c_str());
  1358. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
  1359. flagsDebug.c_str());
  1360. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
  1361. flagsDebugRel.c_str());
  1362. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
  1363. flagsRelease.c_str());
  1364. cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
  1365. fout << line.c_str() << std::endl;
  1366. }
  1367. }
  1368. void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
  1369. {
  1370. std::ifstream fin(this->DSPFooterTemplate.c_str());
  1371. if(!fin)
  1372. {
  1373. cmSystemTools::Error("Error Reading ",
  1374. this->DSPFooterTemplate.c_str());
  1375. }
  1376. std::string line;
  1377. while(cmSystemTools::GetLineFromStream(fin, line))
  1378. {
  1379. fout << line << std::endl;
  1380. }
  1381. }
  1382. //----------------------------------------------------------------------------
  1383. void cmLocalVisualStudio6Generator
  1384. ::ComputeLinkOptions(cmTarget& target,
  1385. const char* configName,
  1386. const std::string extraOptions,
  1387. std::string& options)
  1388. {
  1389. // Compute the link information for this configuration.
  1390. std::vector<cmStdString> linkLibs;
  1391. std::vector<cmStdString> linkDirs;
  1392. this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
  1393. // Build the link options code.
  1394. for(std::vector<cmStdString>::const_iterator d = linkDirs.begin();
  1395. d != linkDirs.end(); ++d)
  1396. {
  1397. std::string dir = *d;
  1398. if(!dir.empty())
  1399. {
  1400. if(dir[dir.size()-1] != '/')
  1401. {
  1402. dir += "/";
  1403. }
  1404. dir += "$(IntDir)";
  1405. options += "# ADD LINK32 /LIBPATH:";
  1406. options += this->ConvertToOptionallyRelativeOutputPath(dir.c_str());
  1407. options += " /LIBPATH:";
  1408. options += this->ConvertToOptionallyRelativeOutputPath(d->c_str());
  1409. options += "\n";
  1410. }
  1411. }
  1412. for(std::vector<cmStdString>::const_iterator l = linkLibs.begin();
  1413. l != linkLibs.end(); ++l)
  1414. {
  1415. options += "# ADD LINK32 ";
  1416. options += this->ConvertToOptionallyRelativeOutputPath(l->c_str());
  1417. options += "\n";
  1418. }
  1419. // Add extra options if any.
  1420. if(!extraOptions.empty())
  1421. {
  1422. options += "# ADD LINK32 ";
  1423. options += extraOptions;
  1424. options += "\n";
  1425. }
  1426. }
  1427. std::string
  1428. cmLocalVisualStudio6Generator
  1429. ::GetTargetDirectory(cmTarget const&) const
  1430. {
  1431. // No per-target directory for this generator (yet).
  1432. return "";
  1433. }
  1434. void cmLocalVisualStudio6Generator
  1435. ::GetTargetObjectFileDirectories(cmTarget* ,
  1436. std::vector<std::string>&
  1437. dirs)
  1438. {
  1439. std::string dir = this->Makefile->GetCurrentOutputDirectory();
  1440. dir += "/";
  1441. dir += this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
  1442. dirs.push_back(dir);
  1443. }
  1444. std::string
  1445. cmLocalVisualStudio6Generator
  1446. ::GetConfigName(std::string const& configuration) const
  1447. {
  1448. // Strip the subdirectory name out of the configuration name.
  1449. std::string config = configuration;
  1450. std::string::size_type pos = config.find_last_of(" ");
  1451. config = config.substr(pos+1, std::string::npos);
  1452. config = config.substr(0, config.size()-1);
  1453. return config;
  1454. }