//===-- llvm-config.cpp - LLVM project configuration utility --------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This tool encapsulates information about an LLVM project configuration for // use by other project's build environments (to determine installed path, // available features, required libraries, etc.). // // Note that although this tool *may* be used by some parts of LLVM's build // itself (i.e., the Makefiles use it to compute required libraries when linking // tools), this tool is primarily designed to support external projects. // //===----------------------------------------------------------------------===// #include "llvm/Config/llvm-config.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include using namespace llvm; // Include the build time variables we can report to the user. This is generated // at build time from the BuildVariables.inc.in file by the build system. #include "BuildVariables.inc" // Include the component table. This creates an array of struct // AvailableComponent entries, which record the component name, library name, // and required components for all of the available libraries. // // Not all components define a library, we also use "library groups" as a way to // create entries for pseudo groups like x86 or all-targets. #include "LibraryDependencies.inc" // LinkMode determines what libraries and flags are returned by llvm-config. enum LinkMode { // LinkModeAuto will link with the default link mode for the installation, // which is dependent on the value of LLVM_LINK_LLVM_DYLIB, and fall back // to the alternative if the required libraries are not available. LinkModeAuto = 0, // LinkModeShared will link with the dynamic component libraries if they // exist, and return an error otherwise. LinkModeShared = 1, // LinkModeStatic will link with the static component libraries if they // exist, and return an error otherwise. LinkModeStatic = 2, }; /// Traverse a single component adding to the topological ordering in /// \arg RequiredLibs. /// /// \param Name - The component to traverse. /// \param ComponentMap - A prebuilt map of component names to descriptors. /// \param VisitedComponents [in] [out] - The set of already visited components. /// \param RequiredLibs [out] - The ordered list of required /// libraries. /// \param GetComponentNames - Get the component names instead of the /// library name. static void VisitComponent(const std::string &Name, const StringMap &ComponentMap, std::set &VisitedComponents, std::vector &RequiredLibs, bool IncludeNonInstalled, bool GetComponentNames, const std::function *GetComponentLibraryPath, std::vector *Missing, const std::string &DirSep) { // Lookup the component. AvailableComponent *AC = ComponentMap.lookup(Name); if (!AC) { errs() << "Can't find component: '" << Name << "' in the map. Available components are: "; for (const auto &Component : ComponentMap) { errs() << "'" << Component.first() << "' "; } errs() << "\n"; report_fatal_error("abort"); } assert(AC && "Invalid component name!"); // Add to the visited table. if (!VisitedComponents.insert(AC).second) { // We are done if the component has already been visited. return; } // Only include non-installed components if requested. if (!AC->IsInstalled && !IncludeNonInstalled) return; // Otherwise, visit all the dependencies. for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) { VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents, RequiredLibs, IncludeNonInstalled, GetComponentNames, GetComponentLibraryPath, Missing, DirSep); } if (GetComponentNames) { RequiredLibs.push_back(Name); return; } // Add to the required library list. if (AC->Library) { if (Missing && GetComponentLibraryPath) { std::string path = (*GetComponentLibraryPath)(AC->Library); if (DirSep == "\\") { std::replace(path.begin(), path.end(), '/', '\\'); } if (!sys::fs::exists(path)) Missing->push_back(path); } RequiredLibs.push_back(AC->Library); } } /// Compute the list of required libraries for a given list of /// components, in an order suitable for passing to a linker (that is, libraries /// appear prior to their dependencies). /// /// \param Components - The names of the components to find libraries for. /// \param IncludeNonInstalled - Whether non-installed components should be /// reported. /// \param GetComponentNames - True if one would prefer the component names. static std::vector ComputeLibsForComponents( const std::vector &Components, bool IncludeNonInstalled, bool GetComponentNames, const std::function *GetComponentLibraryPath, std::vector *Missing, const std::string &DirSep) { std::vector RequiredLibs; std::set VisitedComponents; // Build a map of component names to information. StringMap ComponentMap; for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) { AvailableComponent *AC = &AvailableComponents[i]; ComponentMap[AC->Name] = AC; } // Visit the components. for (unsigned i = 0, e = Components.size(); i != e; ++i) { // Users are allowed to provide mixed case component names. std::string ComponentLower = Components[i].lower(); // Validate that the user supplied a valid component name. if (!ComponentMap.count(ComponentLower)) { llvm::errs() << "llvm-config: unknown component name: " << Components[i] << "\n"; exit(1); } VisitComponent(ComponentLower, ComponentMap, VisitedComponents, RequiredLibs, IncludeNonInstalled, GetComponentNames, GetComponentLibraryPath, Missing, DirSep); } // The list is now ordered with leafs first, we want the libraries to printed // in the reverse order of dependency. std::reverse(RequiredLibs.begin(), RequiredLibs.end()); return RequiredLibs; } /* *** */ static void usage() { errs() << "\ usage: llvm-config