[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
This commit is contained in:
Martin Storsjö
2023-07-17 12:52:47 +03:00
parent cd1b8be8de
commit e777e44546
6 changed files with 70 additions and 16 deletions

View File

@@ -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)

View File

@@ -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} -- '

View File

@@ -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} -- '

View File

@@ -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 -- '

View File

@@ -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:

View File

@@ -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