1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmExportLibraryDependenciesCommand.h"
10 #include "cmsys/FStream.hxx"
12 #include "cmExecutionStatus.h"
13 #include "cmGeneratedFileStream.h"
14 #include "cmGlobalGenerator.h"
15 #include "cmLocalGenerator.h"
16 #include "cmMakefile.h"
17 #include "cmStateTypes.h"
18 #include "cmStringAlgorithms.h"
19 #include "cmSystemTools.h"
21 #include "cmTargetLinkLibraryType.h"
25 class cmListFileBacktrace;
27 static void FinalAction(cmMakefile& makefile, std::string const& filename,
30 // Use copy-if-different if not appending.
31 std::unique_ptr<cmsys::ofstream> foutPtr;
33 const auto openmodeApp = std::ios::app;
34 foutPtr = cm::make_unique<cmsys::ofstream>(filename.c_str(), openmodeApp);
36 std::unique_ptr<cmGeneratedFileStream> ap(
37 new cmGeneratedFileStream(filename, true));
38 ap->SetCopyIfDifferent(true);
39 foutPtr = std::move(ap);
41 std::ostream& fout = *foutPtr;
44 cmSystemTools::Error("Error Writing " + filename);
45 cmSystemTools::ReportLastSystemError("");
49 // Collect dependency information about all library targets built in
51 cmake* cm = makefile.GetCMakeInstance();
52 cmGlobalGenerator* global = cm->GetGlobalGenerator();
53 const auto& locals = global->GetMakefiles();
54 std::map<std::string, std::string> libDepsOld;
55 std::map<std::string, std::string> libDepsNew;
56 std::map<std::string, std::string> libTypes;
57 for (const auto& local : locals) {
58 for (auto const& tgt : local->GetTargets()) {
59 // Get the current target.
60 cmTarget const& target = tgt.second;
62 // Skip non-library targets.
63 if (target.GetType() < cmStateEnums::STATIC_LIBRARY ||
64 target.GetType() > cmStateEnums::MODULE_LIBRARY) {
68 // Construct the dependency variable name.
69 std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS");
71 // Construct the dependency variable value with the direct link
75 cmTarget::LinkLibraryVectorType const& libs =
76 target.GetOriginalLinkLibraries();
77 for (cmTarget::LibraryID const& li : libs) {
78 std::string ltVar = cmStrCat(li.first, "_LINK_TYPE");
81 case GENERAL_LibraryType:
82 valueNew += "general;";
85 case DEBUG_LibraryType:
89 case OPTIMIZED_LibraryType:
90 valueNew += "optimized;";
91 ltValue = "optimized";
94 std::string lib = li.first;
95 if (cmTarget* libtgt = global->FindTarget(lib)) {
96 // Handle simple output name changes. This command is
97 // deprecated so we do not support full target name
98 // translation (which requires per-configuration info).
99 if (cmValue outname = libtgt->GetProperty("OUTPUT_NAME")) {
108 std::string& ltEntry = libTypes[ltVar];
109 if (ltEntry.empty()) {
111 } else if (ltEntry != ltValue) {
115 libDepsNew[targetEntry] = valueNew;
116 libDepsOld[targetEntry] = valueOld;
120 // Generate dependency information for both old and new style CMake
122 const char* vertest =
123 "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
124 fout << "# Generated by CMake\n\n";
125 fout << "if(" << vertest << ")\n";
126 fout << " # Information for CMake 2.6 and above.\n";
127 for (auto const& i : libDepsNew) {
128 if (!i.second.empty()) {
129 fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
133 fout << " # Information for CMake 2.4 and lower.\n";
134 for (auto const& i : libDepsOld) {
135 if (!i.second.empty()) {
136 fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
139 for (auto const& i : libTypes) {
140 if (i.second != "general") {
141 fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
147 bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args,
148 cmExecutionStatus& status)
151 status.SetError("called with incorrect number of arguments");
155 std::string const& filename = args[0];
156 bool const append = args.size() > 1 && args[1] == "APPEND";
157 status.GetMakefile().AddGeneratorAction(
158 [filename, append](cmLocalGenerator& lg, const cmListFileBacktrace&) {
159 FinalAction(*lg.GetMakefile(), filename, append);