[libcxx-commits] [libcxx] e777e44 - [libcxx] Allow linking against the MSVC static CRT

Martin Storsjö via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 28 13:51:42 PDT 2023


Author: Martin Storsjö
Date: 2023-07-28T23:51:28+03:00
New Revision: e777e44546f903146e7cfcd241a9dd9d7f217865

URL: https://github.com/llvm/llvm-project/commit/e777e44546f903146e7cfcd241a9dd9d7f217865
DIFF: https://github.com/llvm/llvm-project/commit/e777e44546f903146e7cfcd241a9dd9d7f217865.diff

LOG: [libcxx] Allow linking against the MSVC static CRT

This respects the CMAKE_MSVC_RUNTIME_LIBRARY option for selecting
the right CRT to use.

Add a CI configuration that tests building this way.

Based on a patch by Andrew Ng.

The test config files end up accumulating and duplicating a fair
bit of cmake-specific logic here; if preferred, we could also add
that in `libcxx/test/CMakeLists.txt` and export a few more variables
to `cmake-bridge.cfg.in` instead.

Differential Revision: https://reviews.llvm.org/D155560

Added: 
    

Modified: 
    libcxx/CMakeLists.txt
    libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in
    libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in
    libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in
    libcxx/utils/ci/buildkite-pipeline.yml
    libcxx/utils/ci/run-buildbot

Removed: 
    


################################################################################
diff  --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 90eb60c8eb6f87..38afb1cb0e7274 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -377,6 +377,11 @@ if (LIBCXX_ABI_FORCE_ITANIUM AND LIBCXX_ABI_FORCE_MICROSOFT)
   message(FATAL_ERROR "Only one of LIBCXX_ABI_FORCE_ITANIUM and LIBCXX_ABI_FORCE_MICROSOFT can be specified.")
 endif ()
 
+if (LIBCXX_ENABLE_SHARED AND CMAKE_MSVC_RUNTIME_LIBRARY AND
+    (NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$"))
+  message(WARNING "A static CRT linked into a shared libc++ doesn't work correctly.")
+endif()
+
 #===============================================================================
 # Configure System
 #===============================================================================
@@ -470,11 +475,6 @@ endif()
 
 include(HandleLibCXXABI) # Setup the ABI library flags
 
-# FIXME: Remove all debug flags and flags that change which Windows
-# default libraries are linked. Currently we only support linking the
-# non-debug DLLs
-remove_flags("/D_DEBUG" "/MTd" "/MDd" "/MT" "/Md")
-
 # FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC.
 # Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors
 # so they don't get transformed into -Wno and -errors respectively.
@@ -688,8 +688,16 @@ function(cxx_link_system_libraries target)
       set(LIB_SUFFIX "")
     endif()
 
-    target_link_libraries(${target} PRIVATE msvcrt${LIB_SUFFIX}) # C runtime startup files
-    target_link_libraries(${target} PRIVATE msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
+    if (NOT CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$")
+      set(CRT_LIB "msvcrt")
+      set(CXX_LIB "msvcprt")
+    else()
+      set(CRT_LIB "libcmt")
+      set(CXX_LIB "libcpmt")
+    endif()
+
+    target_link_libraries(${target} PRIVATE ${CRT_LIB}${LIB_SUFFIX}) # C runtime startup files
+    target_link_libraries(${target} PRIVATE ${CXX_LIB}${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
     # Required for standards-complaint wide character formatting functions
     # (e.g. `printfw`/`scanfw`)
     target_link_libraries(${target} PRIVATE iso_stdio_wide_specifiers)

diff  --git a/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in
index 069e33ff2cb0b0..0d46425734ffe8 100644
--- a/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in
@@ -4,18 +4,26 @@
 lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
 
 dbg_include = ''
-lib_suffix = ''
+runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
+
+if runtime_library == '' or runtime_library.endswith('DLL'):
+    crt_lib = 'msvcrt'
+    cxx_lib = 'msvcprt'
+else:
+    crt_lib = 'libcmt'
+    cxx_lib = 'libcpmt'
 
 if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
     dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
-    lib_suffix = 'd'
+    crt_lib += 'd'
+    cxx_lib += 'd'
 
 config.substitutions.append(('%{flags}', '--driver-mode=g++'))
 config.substitutions.append(('%{compile_flags}',
     '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX' + dbg_include
 ))
 config.substitutions.append(('%{link_flags}',
-    '-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
+    '-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
 ))
 config.substitutions.append(('%{exec}',
     '%{executor} --execdir %T --prepend_env PATH=%{lib} -- '

diff  --git a/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in
index 7cff08d3e3bf3b..de0c4ed1b59522 100644
--- a/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in
@@ -5,18 +5,26 @@
 lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
 
 dbg_include = ''
-lib_suffix = ''
+runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
+
+if runtime_library == '' or runtime_library.endswith('DLL'):
+    crt_lib = 'msvcrt'
+    cxx_lib = 'msvcprt'
+else:
+    crt_lib = 'libcmt'
+    cxx_lib = 'libcpmt'
 
 if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
     dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
-    lib_suffix = 'd'
+    crt_lib += 'd'
+    cxx_lib += 'd'
 
 config.substitutions.append(('%{flags}', '--driver-mode=g++'))
 config.substitutions.append(('%{compile_flags}',
     '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -D_HAS_EXCEPTIONS=0' + dbg_include
 ))
 config.substitutions.append(('%{link_flags}',
-    '-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
+    '-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
 ))
 config.substitutions.append(('%{exec}',
     '%{executor} --execdir %T --prepend_env PATH=%{lib} -- '

diff  --git a/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in
index 9edc22611ba167..e8b9c035b306d9 100644
--- a/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in
@@ -4,18 +4,26 @@
 lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
 
 dbg_include = ''
-lib_suffix = ''
+runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
+
+if runtime_library == '' or runtime_library.endswith('DLL'):
+    crt_lib = 'msvcrt'
+    cxx_lib = 'msvcprt'
+else:
+    crt_lib = 'libcmt'
+    cxx_lib = 'libcpmt'
 
 if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
     dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
-    lib_suffix = 'd'
+    crt_lib += 'd'
+    cxx_lib += 'd'
 
 config.substitutions.append(('%{flags}', '--driver-mode=g++'))
 config.substitutions.append(('%{compile_flags}',
     '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX' + dbg_include
 ))
 config.substitutions.append(('%{link_flags}',
-    '-nostdlib -L %%{lib} -llibc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
+    '-nostdlib -L %%{lib} -llibc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
 ))
 config.substitutions.append(('%{exec}',
     '%{executor} --execdir %T -- '

diff  --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index d8a1807ccfdd03..7affef1c60b462 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -777,6 +777,19 @@ steps:
             limit: 2
       timeout_in_minutes: 120
 
+    - label: "Clang-cl (Static CRT)"
+      command: "bash libcxx/utils/ci/run-buildbot clang-cl-static-crt"
+      artifact_paths:
+        - "**/test-results.xml"
+        - "**/*.abilist"
+      agents:
+        queue: "windows"
+      retry:
+        automatic:
+          - exit_status: -1  # Agent was lost
+            limit: 2
+      timeout_in_minutes: 120
+
     - label: "MinGW (DLL, x86_64)"
       command: "bash libcxx/utils/ci/run-buildbot mingw-dll"
       artifact_paths:

diff  --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index d53a3a29ab0c61..1fa7f880b6c915 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -646,6 +646,15 @@ clang-cl-debug)
     echo "+++ Running the libc++ tests"
     ${NINJA} -vC "${BUILD_DIR}" check-cxx
 ;;
+clang-cl-static-crt)
+    clean
+    # Test linking a static libc++ with the static CRT ("MultiThreaded" denotes
+    # the static CRT, as opposed to "MultiThreadedDLL" which is the default).
+    generate-cmake-libcxx-win -DLIBCXX_ENABLE_SHARED=OFF \
+                              -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
+    echo "+++ Running the libc++ tests"
+    ${NINJA} -vC "${BUILD_DIR}" check-cxx
+;;
 mingw-dll)
     clean
     # Explicitly specify the compiler with a triple prefix. The CI


        


More information about the libcxx-commits mailing list