mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 04:09:45 +00:00
Fix llvm-config
to adapt to the install environment.
Summary: This patch does a couple of things: - Adds a new argument `--shared-mode` which accepts a list of components and prints whether or not the provided components need to be linked statically or shared. - Fixes `--libnames` when CMake BUILD_SHARED_LIBS is used. - Fixes `--libnames`, `--libs`, and `--libfiles` for dylib when static components aren't installed. - Fixes `--libnames`, `--libs`, `--libfiles`, and `--components` to use LLVM_DYLIB_COMPONENTS as the component manifest for dylib linking. - Uses the host platform's usual convention for filename extensions and such, instead of always defaulting to Unix-izms. Because I don't own a Mac, I am not able to test the Mac platform dependent stuff locally. If someone would be willing to run a build for me on their machine (unless there's a better option), I'd appreciate it. Reviewers: jfb, brad.king, whitequark, beanz Subscribers: beanz, jauhien, llvm-commits Differential Revision: http://reviews.llvm.org/D13198 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252532 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
963c9c6d07
commit
6c6be14bb5
@ -277,6 +277,8 @@ uninstall-local:: uninstall-deplibs
|
||||
|
||||
build-deplibs: $(OutputLibs)
|
||||
|
||||
$(OcamlDir)/%.so: $(LibDir)/%.so
|
||||
$(Verb) ln -sf $< $@
|
||||
$(OcamlDir)/%.a: $(LibDir)/%.a
|
||||
$(Verb) ln -sf $< $@
|
||||
|
||||
|
@ -28,3 +28,6 @@
|
||||
#define LLVM_SYSTEM_LIBS "@LLVM_SYSTEM_LIBS@"
|
||||
#define LLVM_BUILD_SYSTEM "@LLVM_BUILD_SYSTEM@"
|
||||
#define LLVM_HAS_RTTI "@LLVM_HAS_RTTI@"
|
||||
#define LLVM_ENABLE_DYLIB "@LLVM_BUILD_LLVM_DYLIB@"
|
||||
#define LLVM_ENABLE_SHARED "@LLVM_ENABLE_SHARED@"
|
||||
#define LLVM_DYLIB_COMPONENTS "@LLVM_DYLIB_COMPONENTS@"
|
||||
|
@ -31,6 +31,11 @@ set(LLVM_HAS_RTTI ${LLVM_CONFIG_HAS_RTTI})
|
||||
set(LLVM_LDFLAGS "${CMAKE_CXX_LINK_FLAGS}")
|
||||
set(LLVM_BUILDMODE ${CMAKE_BUILD_TYPE})
|
||||
set(LLVM_SYSTEM_LIBS ${SYSTEM_LIBS})
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(LLVM_ENABLE_SHARED ON)
|
||||
else()
|
||||
set(LLVM_ENABLE_SHARED OFF)
|
||||
endif()
|
||||
string(REPLACE ";" " " LLVM_TARGETS_BUILT "${LLVM_TARGETS_TO_BUILD}")
|
||||
configure_file(${BUILDVARIABLES_SRCPATH} ${BUILDVARIABLES_OBJPATH} @ONLY)
|
||||
|
||||
|
@ -71,6 +71,14 @@ $(ObjDir)/BuildVariables.inc: $(BUILDVARIABLES_SRCPATH) Makefile $(ObjDir)/.dir
|
||||
>> temp.sed
|
||||
$(Verb) $(ECHO) 's/@LLVM_TARGETS_BUILT@/$(subst /,\/,$(TARGETS_TO_BUILD))/' \
|
||||
>> temp.sed
|
||||
$(if $(filter-out $(ENABLE_SHARED),0),\
|
||||
$(Verb) $(ECHO) 's/@LLVM_BUILD_LLVM_DYLIB@/ON/',\
|
||||
$(Verb) $(ECHO) 's/@LLVM_BUILD_LLVM_DYLIB@/OFF/') \
|
||||
>> temp.sed
|
||||
$(Verb) $(ECHO) 's/@LLVM_ENABLE_SHARED@/OFF/' \
|
||||
>> temp.sed
|
||||
$(Verb) $(ECHO) 's/@LLVM_DYLIB_COMPONENTS@/all/' \
|
||||
>> temp.sed
|
||||
$(Verb) $(ECHO) 's/@LLVM_BUILD_SYSTEM@/autoconf/' \
|
||||
>> temp.sed
|
||||
$(Verb) $(ECHO) 's/@LLVM_HAS_RTTI@/$(LLVM_HAS_RTTI)/' \
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -51,12 +52,16 @@ using namespace llvm;
|
||||
/// \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 RequiredLibs [out] - The ordered list of required
|
||||
/// libraries.
|
||||
/// \param GetComponentNames - Get the component names instead of the
|
||||
/// library name.
|
||||
static void VisitComponent(StringRef Name,
|
||||
const StringMap<AvailableComponent*> &ComponentMap,
|
||||
std::set<AvailableComponent*> &VisitedComponents,
|
||||
std::vector<StringRef> &RequiredLibs,
|
||||
bool IncludeNonInstalled) {
|
||||
bool IncludeNonInstalled, bool GetComponentNames,
|
||||
const std::string *ActiveLibDir, bool *HasMissing) {
|
||||
// Lookup the component.
|
||||
AvailableComponent *AC = ComponentMap.lookup(Name);
|
||||
assert(AC && "Invalid component name!");
|
||||
@ -74,13 +79,23 @@ static void VisitComponent(StringRef Name,
|
||||
// Otherwise, visit all the dependencies.
|
||||
for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) {
|
||||
VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents,
|
||||
RequiredLibs, IncludeNonInstalled);
|
||||
RequiredLibs, IncludeNonInstalled, GetComponentNames,
|
||||
ActiveLibDir, HasMissing);
|
||||
}
|
||||
|
||||
if (GetComponentNames) {
|
||||
RequiredLibs.push_back(Name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to the required library list.
|
||||
if (AC->Library)
|
||||
if (AC->Library) {
|
||||
if (!IncludeNonInstalled && HasMissing && !*HasMissing && ActiveLibDir) {
|
||||
*HasMissing = !sys::fs::exists(*ActiveLibDir + "/" + AC->Library);
|
||||
}
|
||||
RequiredLibs.push_back(AC->Library);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Compute the list of required libraries for a given list of
|
||||
/// components, in an order suitable for passing to a linker (that is, libraries
|
||||
@ -91,9 +106,12 @@ static void VisitComponent(StringRef Name,
|
||||
/// are required to link the given components.
|
||||
/// \param IncludeNonInstalled - Whether non-installed components should be
|
||||
/// reported.
|
||||
/// \param GetComponentNames - True if one would prefer the component names.
|
||||
static void ComputeLibsForComponents(const std::vector<StringRef> &Components,
|
||||
std::vector<StringRef> &RequiredLibs,
|
||||
bool IncludeNonInstalled) {
|
||||
bool IncludeNonInstalled, bool GetComponentNames,
|
||||
const std::string *ActiveLibDir,
|
||||
bool *HasMissing) {
|
||||
std::set<AvailableComponent*> VisitedComponents;
|
||||
|
||||
// Build a map of component names to information.
|
||||
@ -116,7 +134,8 @@ static void ComputeLibsForComponents(const std::vector<StringRef> &Components,
|
||||
}
|
||||
|
||||
VisitComponent(ComponentLower, ComponentMap, VisitedComponents,
|
||||
RequiredLibs, IncludeNonInstalled);
|
||||
RequiredLibs, IncludeNonInstalled, GetComponentNames,
|
||||
ActiveLibDir, HasMissing);
|
||||
}
|
||||
|
||||
// The list is now ordered with leafs first, we want the libraries to printed
|
||||
@ -159,6 +178,7 @@ Options:\n\
|
||||
--assertion-mode Print assertion mode of LLVM tree (ON or OFF).\n\
|
||||
--build-system Print the build system used to build LLVM (autoconf or cmake).\n\
|
||||
--has-rtti Print whether or not LLVM was built with rtti (YES or NO).\n\
|
||||
--shared-mode Print how the provided components can be collectively linked (`shared` or `static`).\n\
|
||||
Typical components:\n\
|
||||
all All LLVM libraries (default).\n\
|
||||
engine Either a native JIT or a bitcode interpreter.\n";
|
||||
@ -173,10 +193,38 @@ std::string GetExecutablePath(const char *Argv0) {
|
||||
return llvm::sys::fs::getMainExecutable(Argv0, P);
|
||||
}
|
||||
|
||||
/// \brief Expand the semi-colon delimited LLVM_DYLIB_COMPONENTS into
|
||||
/// the full list of components.
|
||||
std::vector<StringRef> GetAllDyLibComponents(const bool IsInDevelopmentTree,
|
||||
const bool GetComponentNames) {
|
||||
std::vector<StringRef> DyLibComponents;
|
||||
{
|
||||
StringRef DyLibComponentsStr(LLVM_DYLIB_COMPONENTS);
|
||||
size_t Offset = 0;
|
||||
while (true) {
|
||||
const size_t NextOffset = DyLibComponentsStr.find(';', Offset);
|
||||
DyLibComponents.push_back(DyLibComponentsStr.substr(Offset, NextOffset));
|
||||
if (NextOffset == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
Offset = NextOffset + 1;
|
||||
}
|
||||
|
||||
assert(DyLibComponents.size() > 0);
|
||||
}
|
||||
|
||||
std::vector<StringRef> Components;
|
||||
ComputeLibsForComponents(DyLibComponents, Components,
|
||||
/*IncludeNonInstalled=*/IsInDevelopmentTree,
|
||||
GetComponentNames, nullptr, nullptr);
|
||||
|
||||
return std::move(Components);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::vector<StringRef> Components;
|
||||
bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
|
||||
bool PrintSystemLibs = false;
|
||||
bool PrintSystemLibs = false, PrintSharedMode = false;
|
||||
bool HasAnyOption = false;
|
||||
|
||||
// llvm-config is designed to support being run both from a development tree
|
||||
@ -271,6 +319,108 @@ int main(int argc, char **argv) {
|
||||
ActiveIncludeOption = "-I" + ActiveIncludeDir;
|
||||
}
|
||||
|
||||
/// We only use `shared library` mode in cases where the static library form
|
||||
/// of the components provided are not available; note however that this is
|
||||
/// skipped if we're run from within the build dir. However, once installed,
|
||||
/// we still need to provide correct output when the static archives are
|
||||
/// removed or, as in the case of CMake's `BUILD_SHARED_LIBS`, never present
|
||||
/// in the first place. This can't be done at configure/build time.
|
||||
|
||||
StringRef SharedExt, SharedVersionedExt, SharedDir, SharedPrefix, StaticExt,
|
||||
StaticPrefix, StaticDir = "lib";
|
||||
const Triple HostTriple(Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE));
|
||||
if (HostTriple.isOSWindows()) {
|
||||
SharedExt = "dll";
|
||||
SharedVersionedExt = PACKAGE_VERSION ".dll";
|
||||
StaticExt = "a";
|
||||
SharedDir = ActiveBinDir;
|
||||
StaticDir = ActiveLibDir;
|
||||
StaticPrefix = SharedPrefix = "";
|
||||
} else if (HostTriple.isOSDarwin()) {
|
||||
SharedExt = "dylib";
|
||||
SharedVersionedExt = PACKAGE_VERSION ".dylib";
|
||||
StaticExt = "a";
|
||||
StaticDir = SharedDir = ActiveLibDir;
|
||||
StaticPrefix = SharedPrefix = "lib";
|
||||
} else {
|
||||
// default to the unix values:
|
||||
SharedExt = "so";
|
||||
SharedVersionedExt = PACKAGE_VERSION ".so";
|
||||
StaticExt = "a";
|
||||
StaticDir = SharedDir = ActiveLibDir;
|
||||
StaticPrefix = SharedPrefix = "lib";
|
||||
}
|
||||
|
||||
const bool BuiltDyLib = (std::strcmp(LLVM_ENABLE_DYLIB, "ON") == 0);
|
||||
|
||||
enum { CMake, AutoConf } ConfigTool;
|
||||
if (std::strcmp(LLVM_BUILD_SYSTEM, "cmake") == 0) {
|
||||
ConfigTool = CMake;
|
||||
} else {
|
||||
ConfigTool = AutoConf;
|
||||
}
|
||||
|
||||
/// CMake style shared libs, ie each component is in a shared library.
|
||||
const bool BuiltSharedLibs =
|
||||
(ConfigTool == CMake && std::strcmp(LLVM_ENABLE_SHARED, "ON") == 0);
|
||||
|
||||
bool DyLibExists = false;
|
||||
const std::string DyLibName =
|
||||
(SharedPrefix + "LLVM-" + SharedVersionedExt).str();
|
||||
|
||||
if (BuiltDyLib) {
|
||||
DyLibExists = sys::fs::exists(SharedDir + "/" + DyLibName);
|
||||
}
|
||||
|
||||
/// Get the component's library name without the lib prefix and the
|
||||
/// extension. Returns true if Lib is in a recognized format.
|
||||
auto GetComponentLibraryNameSlice = [&](const StringRef &Lib,
|
||||
StringRef &Out) {
|
||||
if (Lib.startswith("lib")) {
|
||||
unsigned FromEnd;
|
||||
if (Lib.endswith(StaticExt)) {
|
||||
FromEnd = StaticExt.size() + 1;
|
||||
} else if (Lib.endswith(SharedExt)) {
|
||||
FromEnd = SharedExt.size() + 1;
|
||||
} else {
|
||||
FromEnd = 0;
|
||||
}
|
||||
|
||||
if (FromEnd != 0) {
|
||||
Out = Lib.slice(3, Lib.size() - FromEnd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
/// Maps Unixizms to the host platform.
|
||||
auto GetComponentLibraryFileName = [&](const StringRef &Lib,
|
||||
const bool ForceShared) {
|
||||
std::string LibFileName = Lib;
|
||||
StringRef LibName;
|
||||
if (GetComponentLibraryNameSlice(Lib, LibName)) {
|
||||
if (BuiltSharedLibs || ForceShared) {
|
||||
LibFileName = (SharedPrefix + LibName + "." + SharedExt).str();
|
||||
} else {
|
||||
// default to static
|
||||
LibFileName = (StaticPrefix + LibName + "." + StaticExt).str();
|
||||
}
|
||||
}
|
||||
|
||||
return LibFileName;
|
||||
};
|
||||
/// Get the full path for a possibly shared component library.
|
||||
auto GetComponentLibraryPath = [&](const StringRef &Name,
|
||||
const bool ForceShared) {
|
||||
auto LibFileName = GetComponentLibraryFileName(Name, ForceShared);
|
||||
if (BuiltSharedLibs || ForceShared) {
|
||||
return (SharedDir + "/" + LibFileName).str();
|
||||
} else {
|
||||
return (StaticDir + "/" + LibFileName).str();
|
||||
}
|
||||
};
|
||||
|
||||
raw_ostream &OS = outs();
|
||||
for (int i = 1; i != argc; ++i) {
|
||||
StringRef Arg = argv[i];
|
||||
@ -304,13 +454,33 @@ int main(int argc, char **argv) {
|
||||
} else if (Arg == "--libfiles") {
|
||||
PrintLibFiles = true;
|
||||
} else if (Arg == "--components") {
|
||||
/// If there are missing static archives and a dylib was
|
||||
/// built, print LLVM_DYLIB_COMPONENTS instead of everything
|
||||
/// in the manifest.
|
||||
std::vector<StringRef> Components;
|
||||
for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
|
||||
// Only include non-installed components when in a development tree.
|
||||
if (!AvailableComponents[j].IsInstalled && !IsInDevelopmentTree)
|
||||
continue;
|
||||
|
||||
Components.push_back(AvailableComponents[j].Name);
|
||||
if (AvailableComponents[j].Library && !IsInDevelopmentTree) {
|
||||
if (DyLibExists &&
|
||||
!sys::fs::exists(GetComponentLibraryPath(
|
||||
AvailableComponents[j].Library, false))) {
|
||||
Components = GetAllDyLibComponents(IsInDevelopmentTree, true);
|
||||
std::sort(Components.begin(), Components.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned I = 0; I < Components.size(); ++I) {
|
||||
if (I) {
|
||||
OS << ' ';
|
||||
OS << AvailableComponents[j].Name;
|
||||
}
|
||||
|
||||
OS << Components[I];
|
||||
}
|
||||
OS << '\n';
|
||||
} else if (Arg == "--targets-built") {
|
||||
@ -329,6 +499,8 @@ int main(int argc, char **argv) {
|
||||
OS << LLVM_BUILD_SYSTEM << '\n';
|
||||
} else if (Arg == "--has-rtti") {
|
||||
OS << LLVM_HAS_RTTI << '\n';
|
||||
} else if (Arg == "--shared-mode") {
|
||||
PrintSharedMode = true;
|
||||
} else if (Arg == "--obj-root") {
|
||||
OS << ActivePrefix << '\n';
|
||||
} else if (Arg == "--src-root") {
|
||||
@ -344,35 +516,84 @@ int main(int argc, char **argv) {
|
||||
if (!HasAnyOption)
|
||||
usage();
|
||||
|
||||
if (PrintLibs || PrintLibNames || PrintLibFiles || PrintSystemLibs) {
|
||||
if (PrintLibs || PrintLibNames || PrintLibFiles || PrintSystemLibs ||
|
||||
PrintSharedMode) {
|
||||
|
||||
if (PrintSharedMode && BuiltSharedLibs) {
|
||||
OS << "shared\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If no components were specified, default to "all".
|
||||
if (Components.empty())
|
||||
Components.push_back("all");
|
||||
|
||||
// Construct the list of all the required libraries.
|
||||
std::vector<StringRef> RequiredLibs;
|
||||
bool HasMissing = false;
|
||||
ComputeLibsForComponents(Components, RequiredLibs,
|
||||
/*IncludeNonInstalled=*/IsInDevelopmentTree);
|
||||
/*IncludeNonInstalled=*/IsInDevelopmentTree, false,
|
||||
&ActiveLibDir, &HasMissing);
|
||||
|
||||
if (PrintSharedMode) {
|
||||
std::unordered_set<std::string> FullDyLibComponents;
|
||||
std::vector<StringRef> DyLibComponents =
|
||||
GetAllDyLibComponents(IsInDevelopmentTree, false);
|
||||
|
||||
for (auto &Component : DyLibComponents) {
|
||||
FullDyLibComponents.insert(Component);
|
||||
}
|
||||
DyLibComponents.clear();
|
||||
|
||||
for (auto &Lib : RequiredLibs) {
|
||||
if (!FullDyLibComponents.count(Lib)) {
|
||||
OS << "static\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
FullDyLibComponents.clear();
|
||||
|
||||
if (HasMissing && DyLibExists) {
|
||||
OS << "shared\n";
|
||||
return 0;
|
||||
} else {
|
||||
OS << "static\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (PrintLibs || PrintLibNames || PrintLibFiles) {
|
||||
|
||||
auto PrintForLib = [&](const StringRef &Lib, const bool ForceShared) {
|
||||
if (PrintLibNames) {
|
||||
OS << GetComponentLibraryFileName(Lib, ForceShared);
|
||||
} else if (PrintLibFiles) {
|
||||
OS << GetComponentLibraryPath(Lib, ForceShared);
|
||||
} else if (PrintLibs) {
|
||||
// If this is a typical library name, include it using -l.
|
||||
StringRef LibName;
|
||||
if (Lib.startswith("lib")) {
|
||||
if (GetComponentLibraryNameSlice(Lib, LibName)) {
|
||||
OS << "-l" << LibName;
|
||||
} else {
|
||||
OS << "-l:" << GetComponentLibraryFileName(Lib, ForceShared);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, print the full path.
|
||||
OS << GetComponentLibraryPath(Lib, ForceShared);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (HasMissing && DyLibExists) {
|
||||
PrintForLib(DyLibName, true);
|
||||
} else {
|
||||
for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
|
||||
StringRef Lib = RequiredLibs[i];
|
||||
if (i)
|
||||
OS << ' ';
|
||||
|
||||
if (PrintLibNames) {
|
||||
OS << Lib;
|
||||
} else if (PrintLibFiles) {
|
||||
OS << ActiveLibDir << '/' << Lib;
|
||||
} else if (PrintLibs) {
|
||||
// If this is a typical library name, include it using -l.
|
||||
if (Lib.startswith("lib") && Lib.endswith(".a")) {
|
||||
OS << "-l" << Lib.slice(3, Lib.size()-2);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, print the full path.
|
||||
OS << ActiveLibDir << '/' << Lib;
|
||||
PrintForLib(Lib, false);
|
||||
}
|
||||
}
|
||||
OS << '\n';
|
||||
|
Loading…
Reference in New Issue
Block a user