cmExportFileGenerator.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmExportFileGenerator.h"
  11. #include "cmGeneratedFileStream.h"
  12. #include "cmMakefile.h"
  13. #include "cmSystemTools.h"
  14. #include "cmTarget.h"
  15. #include "cmVersion.h"
  16. #include <cmsys/auto_ptr.hxx>
  17. //----------------------------------------------------------------------------
  18. cmExportFileGenerator::cmExportFileGenerator()
  19. {
  20. this->AppendMode = false;
  21. }
  22. //----------------------------------------------------------------------------
  23. void cmExportFileGenerator::AddConfiguration(const char* config)
  24. {
  25. this->Configurations.push_back(config);
  26. }
  27. //----------------------------------------------------------------------------
  28. void cmExportFileGenerator::SetExportFile(const char* mainFile)
  29. {
  30. this->MainImportFile = mainFile;
  31. this->FileDir =
  32. cmSystemTools::GetFilenamePath(this->MainImportFile);
  33. this->FileBase =
  34. cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
  35. this->FileExt =
  36. cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
  37. }
  38. //----------------------------------------------------------------------------
  39. bool cmExportFileGenerator::GenerateImportFile()
  40. {
  41. // Open the output file to generate it.
  42. cmsys::auto_ptr<std::ofstream> foutPtr;
  43. if(this->AppendMode)
  44. {
  45. // Open for append.
  46. cmsys::auto_ptr<std::ofstream>
  47. ap(new std::ofstream(this->MainImportFile.c_str(), std::ios::app));
  48. foutPtr = ap;
  49. }
  50. else
  51. {
  52. // Generate atomically and with copy-if-different.
  53. cmsys::auto_ptr<cmGeneratedFileStream>
  54. ap(new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
  55. ap->SetCopyIfDifferent(true);
  56. foutPtr = ap;
  57. }
  58. if(!foutPtr.get() || !*foutPtr)
  59. {
  60. std::string se = cmSystemTools::GetLastSystemError();
  61. cmOStringStream e;
  62. e << "cannot write to file \"" << this->MainImportFile
  63. << "\": " << se;
  64. cmSystemTools::Error(e.str().c_str());
  65. return false;
  66. }
  67. std::ostream& os = *foutPtr;
  68. // Protect that file against use with older CMake versions.
  69. os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
  70. os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
  71. << " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
  72. << "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n";
  73. // Isolate the file policy level.
  74. // We use 2.6 here instead of the current version because newer
  75. // versions of CMake should be able to export files imported by 2.6
  76. // until the import format changes.
  77. os << "CMAKE_POLICY(PUSH)\n"
  78. << "CMAKE_POLICY(VERSION 2.6)\n";
  79. // Start with the import file header.
  80. this->GenerateImportHeaderCode(os);
  81. // Create all the imported targets.
  82. bool result = this->GenerateMainFile(os);
  83. // End with the import file footer.
  84. this->GenerateImportFooterCode(os);
  85. os << "CMAKE_POLICY(POP)\n";
  86. return result;
  87. }
  88. //----------------------------------------------------------------------------
  89. void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
  90. const char* config)
  91. {
  92. // Construct the property configuration suffix.
  93. std::string suffix = "_";
  94. if(config && *config)
  95. {
  96. suffix += cmSystemTools::UpperCase(config);
  97. }
  98. else
  99. {
  100. suffix += "NOCONFIG";
  101. }
  102. // Generate the per-config target information.
  103. this->GenerateImportTargetsConfig(os, config, suffix);
  104. }
  105. //----------------------------------------------------------------------------
  106. void
  107. cmExportFileGenerator
  108. ::SetImportDetailProperties(const char* config, std::string const& suffix,
  109. cmTarget* target, ImportPropertyMap& properties)
  110. {
  111. // Get the makefile in which to lookup target information.
  112. cmMakefile* mf = target->GetMakefile();
  113. // Add the soname for unix shared libraries.
  114. if(target->GetType() == cmTarget::SHARED_LIBRARY ||
  115. target->GetType() == cmTarget::MODULE_LIBRARY)
  116. {
  117. // Check whether this is a DLL platform.
  118. bool dll_platform =
  119. (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
  120. if(!dll_platform)
  121. {
  122. std::string soname = target->GetSOName(config);
  123. std::string prop = "IMPORTED_SONAME";
  124. prop += suffix;
  125. properties[prop] = soname;
  126. }
  127. }
  128. // Add the transitive link dependencies for this configuration.
  129. if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config))
  130. {
  131. this->SetImportLinkProperty(suffix, target,
  132. "IMPORTED_LINK_INTERFACE_LANGUAGES",
  133. iface->Languages, properties);
  134. this->SetImportLinkProperty(suffix, target,
  135. "IMPORTED_LINK_INTERFACE_LIBRARIES",
  136. iface->Libraries, properties);
  137. this->SetImportLinkProperty(suffix, target,
  138. "IMPORTED_LINK_DEPENDENT_LIBRARIES",
  139. iface->SharedDeps, properties);
  140. if(iface->Multiplicity > 0)
  141. {
  142. std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
  143. prop += suffix;
  144. cmOStringStream m;
  145. m << iface->Multiplicity;
  146. properties[prop] = m.str();
  147. }
  148. }
  149. }
  150. //----------------------------------------------------------------------------
  151. void
  152. cmExportFileGenerator
  153. ::SetImportLinkProperty(std::string const& suffix,
  154. cmTarget* target,
  155. const char* propName,
  156. std::vector<std::string> const& libs,
  157. ImportPropertyMap& properties)
  158. {
  159. // Skip the property if there are no libraries.
  160. if(libs.empty())
  161. {
  162. return;
  163. }
  164. // Get the makefile in which to lookup target information.
  165. cmMakefile* mf = target->GetMakefile();
  166. // Construct the property value.
  167. std::string link_libs;
  168. const char* sep = "";
  169. for(std::vector<std::string>::const_iterator li = libs.begin();
  170. li != libs.end(); ++li)
  171. {
  172. // Separate this from the previous entry.
  173. link_libs += sep;
  174. sep = ";";
  175. // Append this entry.
  176. if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
  177. {
  178. // This is a target.
  179. if(tgt->IsImported())
  180. {
  181. // The target is imported (and therefore is not in the
  182. // export). Append the raw name.
  183. link_libs += *li;
  184. }
  185. else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
  186. {
  187. // The target is in the export. Append it with the export
  188. // namespace.
  189. link_libs += this->Namespace;
  190. link_libs += *li;
  191. }
  192. else
  193. {
  194. // The target is not in the export.
  195. if(!this->AppendMode)
  196. {
  197. // We are not appending, so all exported targets should be
  198. // known here. This is probably user-error.
  199. this->ComplainAboutMissingTarget(target, tgt);
  200. }
  201. // Assume the target will be exported by another command.
  202. // Append it with the export namespace.
  203. link_libs += this->Namespace;
  204. link_libs += *li;
  205. }
  206. }
  207. else
  208. {
  209. // Append the raw name.
  210. link_libs += *li;
  211. }
  212. }
  213. // Store the property.
  214. std::string prop = propName;
  215. prop += suffix;
  216. properties[prop] = link_libs;
  217. }
  218. //----------------------------------------------------------------------------
  219. void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
  220. const char* config)
  221. {
  222. os << "#----------------------------------------------------------------\n"
  223. << "# Generated CMake target import file";
  224. if(config)
  225. {
  226. os << " for configuration \"" << config << "\".\n";
  227. }
  228. else
  229. {
  230. os << ".\n";
  231. }
  232. os << "#----------------------------------------------------------------\n"
  233. << "\n";
  234. this->GenerateImportVersionCode(os);
  235. }
  236. //----------------------------------------------------------------------------
  237. void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
  238. {
  239. os << "# Commands beyond this point should not need to know the version.\n"
  240. << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
  241. }
  242. //----------------------------------------------------------------------------
  243. void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
  244. {
  245. // Store an import file format version. This will let us change the
  246. // format later while still allowing old import files to work.
  247. os << "# Commands may need to know the format version.\n"
  248. << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
  249. << "\n";
  250. }
  251. //----------------------------------------------------------------------------
  252. void
  253. cmExportFileGenerator
  254. ::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
  255. {
  256. // Construct the imported target name.
  257. std::string targetName = this->Namespace;
  258. targetName += target->GetName();
  259. // Create the imported target.
  260. os << "# Create imported target " << targetName << "\n";
  261. switch(target->GetType())
  262. {
  263. case cmTarget::EXECUTABLE:
  264. os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
  265. break;
  266. case cmTarget::STATIC_LIBRARY:
  267. os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
  268. break;
  269. case cmTarget::SHARED_LIBRARY:
  270. os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
  271. break;
  272. case cmTarget::MODULE_LIBRARY:
  273. os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
  274. break;
  275. default: // should never happen
  276. break;
  277. }
  278. // Mark the imported executable if it has exports.
  279. if(target->IsExecutableWithExports())
  280. {
  281. os << "SET_PROPERTY(TARGET " << targetName
  282. << " PROPERTY ENABLE_EXPORTS 1)\n";
  283. }
  284. // Mark the imported library if it is a framework.
  285. if(target->IsFrameworkOnApple())
  286. {
  287. os << "SET_PROPERTY(TARGET " << targetName
  288. << " PROPERTY FRAMEWORK 1)\n";
  289. }
  290. // Mark the imported executable if it is an application bundle.
  291. if(target->IsAppBundleOnApple())
  292. {
  293. os << "SET_PROPERTY(TARGET " << targetName
  294. << " PROPERTY MACOSX_BUNDLE 1)\n";
  295. }
  296. if (target->IsCFBundleOnApple())
  297. {
  298. os << "SET_PROPERTY(TARGET " << targetName
  299. << " PROPERTY BUNDLE 1)\n";
  300. }
  301. os << "\n";
  302. }
  303. //----------------------------------------------------------------------------
  304. void
  305. cmExportFileGenerator
  306. ::GenerateImportPropertyCode(std::ostream& os, const char* config,
  307. cmTarget* target,
  308. ImportPropertyMap const& properties)
  309. {
  310. // Construct the imported target name.
  311. std::string targetName = this->Namespace;
  312. targetName += target->GetName();
  313. // Set the import properties.
  314. os << "# Import target \"" << targetName << "\" for configuration \""
  315. << config << "\"\n";
  316. os << "SET_PROPERTY(TARGET " << targetName
  317. << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
  318. if(config && *config)
  319. {
  320. os << cmSystemTools::UpperCase(config);
  321. }
  322. else
  323. {
  324. os << "NOCONFIG";
  325. }
  326. os << ")\n";
  327. os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
  328. for(ImportPropertyMap::const_iterator pi = properties.begin();
  329. pi != properties.end(); ++pi)
  330. {
  331. os << " " << pi->first << " \"" << pi->second << "\"\n";
  332. }
  333. os << " )\n"
  334. << "\n";
  335. }