From 48aefced4b88fb141bec8d247c7c5dd92a73c6cd Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 9 Feb 2016 19:41:14 +0000 Subject: [PATCH] llvm-config: Add preliminary Windows support Summary: This patch adds Windows support for a few of the llvm-config commands, including cflags, ldflags, libs, and system-libs. Currently llvm-config is untested, so this patch adds tests for the commands that it fixes as well. Reviewers: rnk Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D16762 llvm-svn: 260263 --- lib/Support/CMakeLists.txt | 52 ++++++----- test/tools/llvm-config/cflags.test | 7 ++ test/tools/llvm-config/ldflags.test | 5 ++ test/tools/llvm-config/libs.test | 5 ++ test/tools/llvm-config/system-libs.test | 5 ++ .../llvm-config/system-libs.windows.test | 6 ++ tools/llvm-config/CMakeLists.txt | 6 +- tools/llvm-config/llvm-config.cpp | 87 ++++++++++++------- utils/llvm-build/llvmbuild/main.py | 2 +- 9 files changed, 113 insertions(+), 62 deletions(-) create mode 100644 test/tools/llvm-config/cflags.test create mode 100644 test/tools/llvm-config/ldflags.test create mode 100644 test/tools/llvm-config/libs.test create mode 100644 test/tools/llvm-config/system-libs.test create mode 100644 test/tools/llvm-config/system-libs.windows.test diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 75b3e89f916..0eb4a61fd8f 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -1,32 +1,30 @@ set(system_libs) -if( NOT MSVC ) - if( MINGW ) - # libuuid required for FOLDERID_Profile usage in lib/Support/Windows/Path.inc. - set(system_libs ${system_libs} psapi shell32 ole32 uuid) - elseif( CMAKE_HOST_UNIX ) - if( HAVE_LIBRT ) - set(system_libs ${system_libs} rt) +if( MSVC OR MINGW ) + # libuuid required for FOLDERID_Profile usage in lib/Support/Windows/Path.inc. + set(system_libs ${system_libs} psapi shell32 ole32 uuid) +elseif( CMAKE_HOST_UNIX ) + if( HAVE_LIBRT ) + set(system_libs ${system_libs} rt) + endif() + if( HAVE_LIBDL ) + set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) + endif() + if(LLVM_ENABLE_TERMINFO) + if(HAVE_TERMINFO) + set(system_libs ${system_libs} ${TERMINFO_LIBS}) endif() - if( HAVE_LIBDL ) - set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) - endif() - if(LLVM_ENABLE_TERMINFO) - if(HAVE_TERMINFO) - set(system_libs ${system_libs} ${TERMINFO_LIBS}) - endif() - endif() - if( LLVM_ENABLE_THREADS AND HAVE_LIBATOMIC ) - set(system_libs ${system_libs} atomic) - endif() - if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) - set(system_libs ${system_libs} pthread) - endif() - if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) - set(system_libs ${system_libs} z) - endif() - set(system_libs ${system_libs} m) - endif( MINGW ) -endif( NOT MSVC ) + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBATOMIC ) + set(system_libs ${system_libs} atomic) + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) + set(system_libs ${system_libs} pthread) + endif() + if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) + set(system_libs ${system_libs} z) + endif() + set(system_libs ${system_libs} m) +endif( MSVC OR MINGW ) add_llvm_library(LLVMSupport APFloat.cpp diff --git a/test/tools/llvm-config/cflags.test b/test/tools/llvm-config/cflags.test new file mode 100644 index 00000000000..5e977cb14ed --- /dev/null +++ b/test/tools/llvm-config/cflags.test @@ -0,0 +1,7 @@ +RUN: llvm-config --cflags 2>&1 | FileCheck %s +RUN: llvm-config --cppflags 2>&1 | FileCheck %s +RUN: llvm-config --cxxflags 2>&1 | FileCheck %s +CHECK: -I +CHECK: {{[/\\]}}include +CHECK-NOT: error +CHECK-NOT: warning diff --git a/test/tools/llvm-config/ldflags.test b/test/tools/llvm-config/ldflags.test new file mode 100644 index 00000000000..5bedbde1c67 --- /dev/null +++ b/test/tools/llvm-config/ldflags.test @@ -0,0 +1,5 @@ +RUN: llvm-config --ldflags 2>&1 | FileCheck %s +CHECK: -L +CHECK: {{[/\\]}}lib +CHECK-NOT: error +CHECK-NOT: warning diff --git a/test/tools/llvm-config/libs.test b/test/tools/llvm-config/libs.test new file mode 100644 index 00000000000..fcf9349f1ae --- /dev/null +++ b/test/tools/llvm-config/libs.test @@ -0,0 +1,5 @@ +RUN: llvm-config --libs core 2>&1 | FileCheck %s +CHECK: LLVMCore +CHECK: LLVMSupport +CHECK-NOT: error +CHECK-NOT: warning diff --git a/test/tools/llvm-config/system-libs.test b/test/tools/llvm-config/system-libs.test new file mode 100644 index 00000000000..6a1f3e39fa1 --- /dev/null +++ b/test/tools/llvm-config/system-libs.test @@ -0,0 +1,5 @@ +RUN: llvm-config --system-libs 2>&1 | FileCheck %s +UNSUPPORTED: system-windows +CHECK: -l +CHECK-NOT: error +CHECK-NOT: warning diff --git a/test/tools/llvm-config/system-libs.windows.test b/test/tools/llvm-config/system-libs.windows.test new file mode 100644 index 00000000000..66088424e24 --- /dev/null +++ b/test/tools/llvm-config/system-libs.windows.test @@ -0,0 +1,6 @@ +RUN: llvm-config --system-libs 2>&1 | FileCheck %s +REQUIRED: system-windows +CHECK-NOT: -l +CHECK: psapi.lib shell32.lib ole32.lib uuid.lib +CHECK-NOT: error +CHECK-NOT: warning diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index 46f97e53679..d149b7e65fd 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -11,7 +11,11 @@ add_llvm_tool(llvm-config # Compute the substitution values for various items. get_property(LLVM_SYSTEM_LIBS_LIST TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) foreach(l ${LLVM_SYSTEM_LIBS_LIST}) - set(SYSTEM_LIBS ${SYSTEM_LIBS} "-l${l}") + if(MSVC) + set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") + else() + set(SYSTEM_LIBS ${SYSTEM_LIBS} "-l${l}") + endif() endforeach() string(REPLACE ";" " " SYSTEM_LIBS "${SYSTEM_LIBS}") diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp index b9c22932fe7..a9449c5d817 100644 --- a/tools/llvm-config/llvm-config.cpp +++ b/tools/llvm-config/llvm-config.cpp @@ -79,7 +79,8 @@ static void VisitComponent(const std::string &Name, bool IncludeNonInstalled, bool GetComponentNames, const std::function *GetComponentLibraryPath, - std::vector *Missing) { + std::vector *Missing, + const std::string &DirSep) { // Lookup the component. AvailableComponent *AC = ComponentMap.lookup(Name); assert(AC && "Invalid component name!"); @@ -98,7 +99,7 @@ static void VisitComponent(const std::string &Name, for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) { VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents, RequiredLibs, IncludeNonInstalled, GetComponentNames, - GetComponentLibraryPath, Missing); + GetComponentLibraryPath, Missing, DirSep); } if (GetComponentNames) { @@ -110,6 +111,9 @@ static void VisitComponent(const std::string &Name, 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); } @@ -125,12 +129,11 @@ static void VisitComponent(const std::string &Name, /// \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) { +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; @@ -155,7 +158,7 @@ ComputeLibsForComponents(const std::vector &Components, VisitComponent(ComponentLower, ComponentMap, VisitedComponents, RequiredLibs, IncludeNonInstalled, GetComponentNames, - GetComponentLibraryPath, Missing); + GetComponentLibraryPath, Missing, DirSep); } // The list is now ordered with leafs first, we want the libraries to printed @@ -220,7 +223,8 @@ std::string GetExecutablePath(const char *Argv0) { /// \brief Expand the semi-colon delimited LLVM_DYLIB_COMPONENTS into /// the full list of components. std::vector GetAllDyLibComponents(const bool IsInDevelopmentTree, - const bool GetComponentNames) { + const bool GetComponentNames, + const std::string &DirSep) { std::vector DyLibComponents; StringRef DyLibComponentsStr(LLVM_DYLIB_COMPONENTS); @@ -238,7 +242,7 @@ std::vector GetAllDyLibComponents(const bool IsInDevelopmentTree, return ComputeLibsForComponents(DyLibComponents, /*IncludeNonInstalled=*/IsInDevelopmentTree, - GetComponentNames, nullptr, nullptr); + GetComponentNames, nullptr, nullptr, DirSep); } int main(int argc, char **argv) { @@ -347,15 +351,26 @@ int main(int argc, char **argv) { /// in the first place. This can't be done at configure/build time. StringRef SharedExt, SharedVersionedExt, SharedDir, SharedPrefix, StaticExt, - StaticPrefix, StaticDir = "lib"; + StaticPrefix, StaticDir = "lib", DirSep = "/"; const Triple HostTriple(Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE)); if (HostTriple.isOSWindows()) { SharedExt = "dll"; SharedVersionedExt = LLVM_DYLIB_VERSION ".dll"; - StaticExt = "a"; + if (HostTriple.isOSCygMing()) { + StaticExt = "a"; + StaticPrefix = SharedPrefix = "lib"; + } else { + StaticExt = "lib"; + DirSep = "\\"; + std::replace(ActiveObjRoot.begin(), ActiveObjRoot.end(), '/', '\\'); + std::replace(ActivePrefix.begin(), ActivePrefix.end(), '/', '\\'); + std::replace(ActiveBinDir.begin(), ActiveBinDir.end(), '/', '\\'); + std::replace(ActiveLibDir.begin(), ActiveLibDir.end(), '/', '\\'); + std::replace(ActiveIncludeOption.begin(), ActiveIncludeOption.end(), '/', + '\\'); + } SharedDir = ActiveBinDir; StaticDir = ActiveLibDir; - StaticPrefix = SharedPrefix = "lib"; } else if (HostTriple.isOSDarwin()) { SharedExt = "dylib"; SharedVersionedExt = LLVM_DYLIB_VERSION ".dylib"; @@ -394,7 +409,11 @@ int main(int argc, char **argv) { bool LinkDyLib = (std::strcmp(LLVM_LINK_DYLIB, "ON") == 0); if (BuiltDyLib) { - DyLibExists = sys::fs::exists(SharedDir + "/" + DyLibName); + std::string path((SharedDir + DirSep + DyLibName).str()); + if (DirSep == "\\") { + std::replace(path.begin(), path.end(), '/', '\\'); + } + DyLibExists = sys::fs::exists(path); if (!DyLibExists) { // The shared library does not exist: don't error unless the user // explicitly passes --link-shared. @@ -429,15 +448,12 @@ int main(int argc, char **argv) { /// Maps Unixizms to the host platform. auto GetComponentLibraryFileName = [&](const StringRef &Lib, const bool Shared) { - std::string LibFileName = Lib; - StringRef LibName; - if (GetComponentLibraryNameSlice(Lib, LibName)) { - if (Shared) { - LibFileName = (SharedPrefix + LibName + "." + SharedExt).str(); - } else { - // default to static - LibFileName = (StaticPrefix + LibName + "." + StaticExt).str(); - } + std::string LibFileName; + if (Shared) { + LibFileName = (SharedPrefix + Lib + "." + SharedExt).str(); + } else { + // default to static + LibFileName = (StaticPrefix + Lib + "." + StaticExt).str(); } return LibFileName; @@ -446,9 +462,9 @@ int main(int argc, char **argv) { auto GetComponentLibraryPath = [&](const StringRef &Name, const bool Shared) { auto LibFileName = GetComponentLibraryFileName(Name, Shared); if (Shared) { - return (SharedDir + "/" + LibFileName).str(); + return (SharedDir + DirSep + LibFileName).str(); } else { - return (StaticDir + "/" + LibFileName).str(); + return (StaticDir + DirSep + LibFileName).str(); } }; @@ -475,7 +491,8 @@ int main(int argc, char **argv) { } else if (Arg == "--cxxflags") { OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n'; } else if (Arg == "--ldflags") { - OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n'; + OS << ((HostTriple.isWindowsMSVCEnvironment()) ? "-LIBPATH:" : "-L") + << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n'; } else if (Arg == "--system-libs") { PrintSystemLibs = true; } else if (Arg == "--libs") { @@ -496,10 +513,14 @@ int main(int argc, char **argv) { 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::string path( + GetComponentLibraryPath(AvailableComponents[j].Library, false)); + if (DirSep == "\\") { + std::replace(path.begin(), path.end(), '/', '\\'); + } + if (DyLibExists && !sys::fs::exists(path)) { + Components = + GetAllDyLibComponents(IsInDevelopmentTree, true, DirSep); std::sort(Components.begin(), Components.end()); break; } @@ -577,7 +598,7 @@ int main(int argc, char **argv) { std::vector RequiredLibs = ComputeLibsForComponents( Components, /*IncludeNonInstalled=*/IsInDevelopmentTree, false, - &GetComponentLibraryPathFunction, &MissingLibs); + &GetComponentLibraryPathFunction, &MissingLibs, DirSep); if (!MissingLibs.empty()) { switch (LinkMode) { case LinkModeShared: @@ -607,7 +628,7 @@ int main(int argc, char **argv) { if (PrintSharedMode) { std::unordered_set FullDyLibComponents; std::vector DyLibComponents = - GetAllDyLibComponents(IsInDevelopmentTree, false); + GetAllDyLibComponents(IsInDevelopmentTree, false, DirSep); for (auto &Component : DyLibComponents) { FullDyLibComponents.insert(Component); diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index f2472f698a6..fccfc7e6ece 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -413,7 +413,7 @@ subdirectories = %s if library_name is None: library_name_as_cstr = 'nullptr' else: - library_name_as_cstr = '"lib%s.a"' % library_name + library_name_as_cstr = '"%s"' % library_name if is_installed: is_installed_as_cstr = 'true' else: