cmLocalVisualStudio6Generator.cxx 53 KB

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