cmLocalBorlandMakefileGenerator.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 "cmLocalBorlandMakefileGenerator.h"
  14. #include "cmMakefile.h"
  15. #include "cmStandardIncludes.h"
  16. #include "cmSystemTools.h"
  17. #include "cmSourceFile.h"
  18. #include "cmMakeDepend.h"
  19. #include "cmCacheManager.h"
  20. #include "cmGeneratedFileStream.h"
  21. #include "windows.h"
  22. #include <stdio.h>
  23. cmLocalBorlandMakefileGenerator::cmLocalBorlandMakefileGenerator()
  24. {
  25. this->SetLibraryPathOption("-L");
  26. this->SetLibraryLinkOption("");
  27. }
  28. cmLocalBorlandMakefileGenerator::~cmLocalBorlandMakefileGenerator()
  29. {
  30. }
  31. void cmLocalBorlandMakefileGenerator::OutputMakeVariables(std::ostream& fout)
  32. {
  33. fout << "# NMake Makefile generated by cmake\n";
  34. const char* variables =
  35. "# general varibles used in the makefile\n"
  36. "\n"
  37. "CMAKE_STANDARD_WINDOWS_LIBRARIES = @CMAKE_STANDARD_WINDOWS_LIBRARIES@\n"
  38. "CMAKE_C_FLAGS = @CMAKE_C_FLAGS@ @BUILD_FLAGS@\n"
  39. "CMAKE_OBJECT_FILE_SUFFIX = @CMAKE_OBJECT_FILE_SUFFIX@\n"
  40. "CMAKE_EXECUTABLE_SUFFIX = @CMAKE_EXECUTABLE_SUFFIX@\n"
  41. "CMAKE_STATICLIB_SUFFIX = @CMAKE_STATICLIB_SUFFIX@\n"
  42. "CMAKE_SHLIB_SUFFIX = @CMAKE_SHLIB_SUFFIX@\n"
  43. "CMAKE_SHLIB_CFLAGS = -tWR\n"
  44. "CMAKE_LINKER_FLAGS = @CMAKE_LINKER_FLAGS@ @LINKER_BUILD_FLAGS@\n"
  45. "CMAKE_CXX_FLAGS = -P @CMAKE_CXX_FLAGS@ @BUILD_FLAGS@\n"
  46. "!IF \"$(OS)\" == \"Windows_NT\"\n"
  47. "NULL=\n"
  48. "!ELSE \n"
  49. "NULL=nul\n"
  50. "!ENDIF \n";
  51. std::string buildType = "CMAKE_CXX_FLAGS_";
  52. buildType += m_Makefile->GetDefinition("CMAKE_BUILD_TYPE");
  53. buildType = cmSystemTools::UpperCase(buildType);
  54. m_Makefile->AddDefinition("BUILD_FLAGS",
  55. m_Makefile->GetDefinition(
  56. buildType.c_str()));
  57. buildType = "CMAKE_LINKER_FLAGS_";
  58. buildType += m_Makefile->GetDefinition("CMAKE_BUILD_TYPE");
  59. buildType = cmSystemTools::UpperCase(buildType);
  60. m_Makefile->AddDefinition("LINKER_BUILD_FLAGS",
  61. m_Makefile->GetDefinition(
  62. buildType.c_str()));
  63. std::string replaceVars = variables;
  64. m_Makefile->ExpandVariablesInString(replaceVars);
  65. std::string ccompiler = m_Makefile->GetDefinition("CMAKE_C_COMPILER");
  66. fout << "CMAKE_C_COMPILER = "
  67. << cmSystemTools::ConvertToOutputPath(ccompiler.c_str())
  68. << "\n";
  69. std::string cxxcompiler = m_Makefile->GetDefinition("CMAKE_CXX_COMPILER");
  70. fout << "CMAKE_CXX_COMPILER = "
  71. << cmSystemTools::ConvertToOutputPath(cxxcompiler.c_str())
  72. << "\n";
  73. if(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
  74. {
  75. fout << "CMAKE_EDIT_COMMAND = "
  76. << this->ShortPath(m_Makefile->GetDefinition("CMAKE_EDIT_COMMAND"))
  77. << "\n";
  78. }
  79. std::string cmakecommand = m_Makefile->GetDefinition("CMAKE_COMMAND");
  80. fout << "CMAKE_COMMAND = "
  81. << this->ShortPath(cmakecommand.c_str()) << "\n";
  82. fout << "RM = " << this->ShortPath(cmakecommand.c_str()) << " -E remove -f\n";
  83. fout << replaceVars.c_str();
  84. fout << "CMAKE_CURRENT_SOURCE = "
  85. << ShortPath(m_Makefile->GetStartDirectory() )
  86. << "\n";
  87. fout << "CMAKE_CURRENT_BINARY = "
  88. << ShortPath(m_Makefile->GetStartOutputDirectory())
  89. << "\n";
  90. fout << "CMAKE_SOURCE_DIR = "
  91. << ShortPath(m_Makefile->GetHomeDirectory()) << "\n";
  92. fout << "CMAKE_BINARY_DIR = "
  93. << ShortPath(m_Makefile->GetHomeOutputDirectory() )
  94. << "\n";
  95. // Output Include paths
  96. fout << "INCLUDE_FLAGS = ";
  97. std::vector<std::string>& includes = m_Makefile->GetIncludeDirectories();
  98. std::vector<std::string>::iterator i;
  99. fout << "-I" <<
  100. this->ShortPath(m_Makefile->GetStartDirectory()) << " ";
  101. for(i = includes.begin(); i != includes.end(); ++i)
  102. {
  103. std::string include = *i;
  104. // Don't output a -I for the standard include path "/usr/include".
  105. // This can cause problems with certain standard library
  106. // implementations because the wrong headers may be found first.
  107. fout << "-I" << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << " ";
  108. }
  109. fout << m_Makefile->GetDefineFlags();
  110. fout << "\n\n";
  111. }
  112. void
  113. cmLocalBorlandMakefileGenerator::
  114. OutputBuildObjectFromSource(std::ostream& fout,
  115. const char* shortName,
  116. const cmSourceFile& source,
  117. const char* extraCompileFlags,
  118. bool shared)
  119. {
  120. // force shared flag if building shared libraries
  121. if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
  122. {
  123. shared = true;
  124. }
  125. // Header files shouldn't have build rules.
  126. if(source.GetPropertyAsBool("HEADER_FILE_ONLY"))
  127. {
  128. return;
  129. }
  130. std::string comment = "Build ";
  131. std::string objectFile = std::string(shortName) +
  132. this->GetOutputExtension(source.GetSourceExtension().c_str());
  133. objectFile = cmSystemTools::ConvertToOutputPath(objectFile.c_str());
  134. comment += objectFile + " From ";
  135. comment += source.GetFullPath();
  136. std::string compileCommand;
  137. std::string ext = source.GetSourceExtension();
  138. if(ext == "c" )
  139. {
  140. compileCommand = "$(CMAKE_C_COMPILER) $(CMAKE_C_FLAGS) ";
  141. compileCommand += extraCompileFlags;
  142. if(shared)
  143. {
  144. compileCommand += "$(CMAKE_SHLIB_CFLAGS) ";
  145. }
  146. compileCommand += " -o";
  147. compileCommand += objectFile;
  148. compileCommand += " $(INCLUDE_FLAGS) -c ";
  149. compileCommand +=
  150. cmSystemTools::ConvertToOutputPath(source.GetFullPath().c_str());
  151. }
  152. else if (ext == "rc")
  153. {
  154. compileCommand = "$(RC) $(INCLUDE_FLAGS) -o\"";
  155. compileCommand += objectFile;
  156. compileCommand += "\" ";
  157. compileCommand +=
  158. cmSystemTools::ConvertToOutputPath(source.GetFullPath().c_str());
  159. }
  160. else if (ext == "def")
  161. {
  162. // no rule to output for this one
  163. return;
  164. }
  165. // assume c++ if not c rc or def
  166. else
  167. {
  168. compileCommand = "$(CMAKE_CXX_COMPILER) $(CMAKE_CXX_FLAGS) ";
  169. compileCommand += extraCompileFlags;
  170. if(shared)
  171. {
  172. compileCommand += "$(CMAKE_SHLIB_CFLAGS) ";
  173. }
  174. compileCommand += " -o";
  175. compileCommand += objectFile;
  176. compileCommand += " $(INCLUDE_FLAGS) -c ";
  177. compileCommand +=
  178. cmSystemTools::ConvertToOutputPath(source.GetFullPath().c_str());
  179. }
  180. this->OutputMakeRule(fout,
  181. comment.c_str(),
  182. objectFile.c_str(),
  183. cmSystemTools::ConvertToOutputPath(
  184. source.GetFullPath().c_str()).c_str(),
  185. compileCommand.c_str());
  186. }
  187. void cmLocalBorlandMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
  188. const char* name,
  189. const cmTarget &t)
  190. {
  191. std::string target = m_LibraryOutputPath + name;
  192. std::string libpath = target + ".lib";
  193. target += ".dll";
  194. target = cmSystemTools::ConvertToOutputPath(target.c_str());
  195. libpath = cmSystemTools::ConvertToOutputPath(libpath.c_str());
  196. std::string depend = "$(";
  197. depend += this->CreateMakeVariable(name, "_SRC_OBJS");
  198. depend += ") $(" + this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
  199. std::string command = "$(CMAKE_CXX_COMPILER) -tWD $(CMAKE_SHLIB_CFLAGS) $(CMAKE_LINKER_FLAGS) @&&|\n";
  200. // must be executable name
  201. command += "-e";
  202. command += target;
  203. command += " ";
  204. cmStringStream linklibs;
  205. this->OutputLinkLibraries(linklibs, name, t);
  206. // then the linker options -L and libraries (any other order will fail!)
  207. command += linklibs.str();
  208. // then list of object files
  209. command += " $(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
  210. std::string command2 = "implib -w ";
  211. command2 += libpath + " " + target;
  212. const std::vector<cmSourceFile*>& sources = t.GetSourceFiles();
  213. for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
  214. i != sources.end(); ++i)
  215. {
  216. if((*i)->GetSourceExtension() == "def")
  217. {
  218. command += "";
  219. command += (*i)->GetFullPath();
  220. }
  221. }
  222. command += "\n|\n";
  223. std::string customCommands = this->CreateTargetRules(t, name);
  224. const char* cc = 0;
  225. if(customCommands.size() > 0)
  226. {
  227. cc = customCommands.c_str();
  228. }
  229. this->OutputMakeRule(fout, "rules for a shared library",
  230. target.c_str(),
  231. depend.c_str(),
  232. command.c_str(),
  233. command2.c_str(),
  234. cc);
  235. }
  236. void cmLocalBorlandMakefileGenerator::OutputModuleLibraryRule(std::ostream& fout,
  237. const char* name,
  238. const cmTarget &target)
  239. {
  240. this->OutputSharedLibraryRule(fout, name, target);
  241. }
  242. void cmLocalBorlandMakefileGenerator::OutputStaticLibraryRule(std::ostream& fout,
  243. const char* name,
  244. const cmTarget &t)
  245. {
  246. std::string target = m_LibraryOutputPath + std::string(name) + ".lib";
  247. target = cmSystemTools::ConvertToOutputPath(target.c_str());
  248. std::string depend = "$(";
  249. depend += this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
  250. std::string command = "tlib @&&|\n\t /p512 /a ";
  251. command += target;
  252. command += " ";
  253. std::string deleteCommand = "if exist ";
  254. deleteCommand += target;
  255. deleteCommand += " del ";
  256. deleteCommand += target;
  257. command += " $(";
  258. command += this->CreateMakeVariable(name, "_SRC_OBJS_QUOTED") + ")";
  259. command += "\n|\n";
  260. std::string comment = "rule to build static library: ";
  261. comment += name;
  262. std::string customCommands = this->CreateTargetRules(t, name);
  263. const char* cc = 0;
  264. if(customCommands.size() > 0)
  265. {
  266. cc = customCommands.c_str();
  267. }
  268. this->OutputMakeRule(fout,
  269. comment.c_str(),
  270. target.c_str(),
  271. depend.c_str(),
  272. deleteCommand.c_str(),
  273. command.c_str(), cc);
  274. }
  275. void cmLocalBorlandMakefileGenerator::OutputExecutableRule(std::ostream& fout,
  276. const char* name,
  277. const cmTarget &t)
  278. {
  279. std::string target = m_ExecutableOutputPath + name + m_ExecutableExtension;
  280. target = cmSystemTools::ConvertToOutputPath(target.c_str());
  281. std::string depend = "$(";
  282. depend += this->CreateMakeVariable(name, "_SRC_OBJS") + ") $(" +
  283. this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
  284. std::string command =
  285. "$(CMAKE_CXX_COMPILER) ";
  286. command += " $(CMAKE_LINKER_FLAGS) -e" + target;
  287. if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
  288. {
  289. command += " $(CMAKE_SHLIB_CFLAGS) ";
  290. }
  291. if(t.GetType() == cmTarget::WIN32_EXECUTABLE)
  292. {
  293. command += " -tWM ";
  294. }
  295. else
  296. {
  297. command += " -tWC ";
  298. }
  299. cmStringStream linklibs;
  300. this->OutputLinkLibraries(linklibs, 0, t);
  301. command += linklibs.str();
  302. command += " $(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ")";
  303. std::string comment = "rule to build executable: ";
  304. comment += name;
  305. std::string customCommands = this->CreateTargetRules(t, name);
  306. const char* cc = 0;
  307. if(customCommands.size() > 0)
  308. {
  309. cc = customCommands.c_str();
  310. }
  311. this->OutputMakeRule(fout,
  312. comment.c_str(),
  313. target.c_str(),
  314. depend.c_str(),
  315. command.c_str(), cc);
  316. }
  317. std::string cmLocalBorlandMakefileGenerator::GetOutputExtension(const char* s)
  318. {
  319. std::string sourceExtension = s;
  320. if(sourceExtension == "def")
  321. {
  322. return "";
  323. }
  324. if(sourceExtension == "ico" || sourceExtension == "rc2")
  325. {
  326. return "";
  327. }
  328. if(sourceExtension == "rc")
  329. {
  330. return ".res";
  331. }
  332. return ".obj";
  333. }
  334. bool cmLocalBorlandMakefileGenerator::SamePath(const char* path1, const char* path2)
  335. {
  336. // first check to see if they are the same anyway
  337. if (strcmp(path1, path2) == 0)
  338. {
  339. return true;
  340. }
  341. // next short path and lower case both of them for the compare
  342. return
  343. cmSystemTools::LowerCase(ShortPath(path1)) ==
  344. cmSystemTools::LowerCase(ShortPath(path2));
  345. }
  346. // borland make does not support variables that are longer than 32
  347. // so use this function to rename any long ones
  348. std::string cmLocalBorlandMakefileGenerator::CreateMakeVariable(const char* s, const char* s2)
  349. {
  350. std::string unmodified = s;
  351. unmodified += s2;
  352. // see if th
  353. std::map<cmStdString, cmStdString>::iterator i = m_MakeVariableMap.find(unmodified);
  354. if(i != m_MakeVariableMap.end())
  355. {
  356. return i->second;
  357. }
  358. std::string ret = unmodified;
  359. // if the string is greater the 32 chars it is an invalid vairable name
  360. // for borland make
  361. if(ret.size() > 32)
  362. {
  363. std::string str1 = s;
  364. std::string str2 = s2;
  365. // we must shorten the combined string by 4 charactors
  366. // keep no more than 24 charactors from the second string
  367. if(str2.size() > 24)
  368. {
  369. str2 = str2.substr(0, 24);
  370. }
  371. if(str1.size() + str2.size() > 27)
  372. {
  373. str1 = str1.substr(0, 27 - str2.size());
  374. }
  375. char buffer[5];
  376. int i = 0;
  377. sprintf(buffer, "%04d", i);
  378. ret = str1 + str2 + buffer;
  379. while(m_ShortMakeVariableMap.count(ret) && i < 1000)
  380. {
  381. ++i;
  382. sprintf(buffer, "%04d", i);
  383. ret = str1 + str2 + buffer;
  384. }
  385. if(i == 1000)
  386. {
  387. cmSystemTools::Error("Borland makefile varible length too long");
  388. return unmodified;
  389. }
  390. // once an unused variable is found
  391. m_ShortMakeVariableMap[ret] = "1";
  392. }
  393. // always make an entry into the unmodified to varible map
  394. m_MakeVariableMap[unmodified] = ret;
  395. return ret;
  396. }