| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmExportLibraryDependenciesCommand.h" |
| |
| #include <map> |
| #include <utility> |
| |
| #include <cm/memory> |
| |
| #include "cmsys/FStream.hxx" |
| |
| #include "cmExecutionStatus.h" |
| #include "cmGeneratedFileStream.h" |
| #include "cmGlobalGenerator.h" |
| #include "cmLocalGenerator.h" |
| #include "cmMakefile.h" |
| #include "cmProperty.h" |
| #include "cmStateTypes.h" |
| #include "cmStringAlgorithms.h" |
| #include "cmSystemTools.h" |
| #include "cmTarget.h" |
| #include "cmTargetLinkLibraryType.h" |
| #include "cmake.h" |
| |
| class cmListFileBacktrace; |
| |
| static void FinalAction(cmMakefile& makefile, std::string const& filename, |
| bool append) |
| { |
| // Use copy-if-different if not appending. |
| std::unique_ptr<cmsys::ofstream> foutPtr; |
| if (append) { |
| const auto openmodeApp = std::ios::app; |
| foutPtr = cm::make_unique<cmsys::ofstream>(filename.c_str(), openmodeApp); |
| } else { |
| std::unique_ptr<cmGeneratedFileStream> ap( |
| new cmGeneratedFileStream(filename, true)); |
| ap->SetCopyIfDifferent(true); |
| foutPtr = std::move(ap); |
| } |
| std::ostream& fout = *foutPtr; |
| |
| if (!fout) { |
| cmSystemTools::Error("Error Writing " + filename); |
| cmSystemTools::ReportLastSystemError(""); |
| return; |
| } |
| |
| // Collect dependency information about all library targets built in |
| // the project. |
| cmake* cm = makefile.GetCMakeInstance(); |
| cmGlobalGenerator* global = cm->GetGlobalGenerator(); |
| const auto& locals = global->GetMakefiles(); |
| std::map<std::string, std::string> libDepsOld; |
| std::map<std::string, std::string> libDepsNew; |
| std::map<std::string, std::string> libTypes; |
| for (const auto& local : locals) { |
| for (auto const& tgt : local->GetTargets()) { |
| // Get the current target. |
| cmTarget const& target = tgt.second; |
| |
| // Skip non-library targets. |
| if (target.GetType() < cmStateEnums::STATIC_LIBRARY || |
| target.GetType() > cmStateEnums::MODULE_LIBRARY) { |
| continue; |
| } |
| |
| // Construct the dependency variable name. |
| std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS"); |
| |
| // Construct the dependency variable value with the direct link |
| // dependencies. |
| std::string valueOld; |
| std::string valueNew; |
| cmTarget::LinkLibraryVectorType const& libs = |
| target.GetOriginalLinkLibraries(); |
| for (cmTarget::LibraryID const& li : libs) { |
| std::string ltVar = cmStrCat(li.first, "_LINK_TYPE"); |
| std::string ltValue; |
| switch (li.second) { |
| case GENERAL_LibraryType: |
| valueNew += "general;"; |
| ltValue = "general"; |
| break; |
| case DEBUG_LibraryType: |
| valueNew += "debug;"; |
| ltValue = "debug"; |
| break; |
| case OPTIMIZED_LibraryType: |
| valueNew += "optimized;"; |
| ltValue = "optimized"; |
| break; |
| } |
| std::string lib = li.first; |
| if (cmTarget* libtgt = global->FindTarget(lib)) { |
| // Handle simple output name changes. This command is |
| // deprecated so we do not support full target name |
| // translation (which requires per-configuration info). |
| if (cmProp outname = libtgt->GetProperty("OUTPUT_NAME")) { |
| lib = *outname; |
| } |
| } |
| valueOld += lib; |
| valueOld += ";"; |
| valueNew += lib; |
| valueNew += ";"; |
| |
| std::string& ltEntry = libTypes[ltVar]; |
| if (ltEntry.empty()) { |
| ltEntry = ltValue; |
| } else if (ltEntry != ltValue) { |
| ltEntry = "general"; |
| } |
| } |
| libDepsNew[targetEntry] = valueNew; |
| libDepsOld[targetEntry] = valueOld; |
| } |
| } |
| |
| // Generate dependency information for both old and new style CMake |
| // versions. |
| const char* vertest = |
| "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4"; |
| fout << "# Generated by CMake\n\n"; |
| fout << "if(" << vertest << ")\n"; |
| fout << " # Information for CMake 2.6 and above.\n"; |
| for (auto const& i : libDepsNew) { |
| if (!i.second.empty()) { |
| fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n"; |
| } |
| } |
| fout << "else()\n"; |
| fout << " # Information for CMake 2.4 and lower.\n"; |
| for (auto const& i : libDepsOld) { |
| if (!i.second.empty()) { |
| fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n"; |
| } |
| } |
| for (auto const& i : libTypes) { |
| if (i.second != "general") { |
| fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n"; |
| } |
| } |
| fout << "endif()\n"; |
| } |
| |
| bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, |
| cmExecutionStatus& status) |
| { |
| if (args.empty()) { |
| status.SetError("called with incorrect number of arguments"); |
| return false; |
| } |
| |
| std::string const& filename = args[0]; |
| bool const append = args.size() > 1 && args[1] == "APPEND"; |
| status.GetMakefile().AddGeneratorAction( |
| [filename, append](cmLocalGenerator& lg, const cmListFileBacktrace&) { |
| FinalAction(*lg.GetMakefile(), filename, append); |
| }); |
| |
| return true; |
| } |