Skip to content

Commit e777e44

Browse files
committed
[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
1 parent cd1b8be commit e777e44

File tree

6 files changed

+70
-16
lines changed

6 files changed

+70
-16
lines changed

libcxx/CMakeLists.txt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ if (LIBCXX_ABI_FORCE_ITANIUM AND LIBCXX_ABI_FORCE_MICROSOFT)
377377
message(FATAL_ERROR "Only one of LIBCXX_ABI_FORCE_ITANIUM and LIBCXX_ABI_FORCE_MICROSOFT can be specified.")
378378
endif ()
379379

380+
if (LIBCXX_ENABLE_SHARED AND CMAKE_MSVC_RUNTIME_LIBRARY AND
381+
(NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$"))
382+
message(WARNING "A static CRT linked into a shared libc++ doesn't work correctly.")
383+
endif()
384+
380385
#===============================================================================
381386
# Configure System
382387
#===============================================================================
@@ -470,11 +475,6 @@ endif()
470475

471476
include(HandleLibCXXABI) # Setup the ABI library flags
472477

473-
# FIXME: Remove all debug flags and flags that change which Windows
474-
# default libraries are linked. Currently we only support linking the
475-
# non-debug DLLs
476-
remove_flags("/D_DEBUG" "/MTd" "/MDd" "/MT" "/Md")
477-
478478
# FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC.
479479
# Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors
480480
# so they don't get transformed into -Wno and -errors respectively.
@@ -688,8 +688,16 @@ function(cxx_link_system_libraries target)
688688
set(LIB_SUFFIX "")
689689
endif()
690690

691-
target_link_libraries(${target} PRIVATE msvcrt${LIB_SUFFIX}) # C runtime startup files
692-
target_link_libraries(${target} PRIVATE msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
691+
if (NOT CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$")
692+
set(CRT_LIB "msvcrt")
693+
set(CXX_LIB "msvcprt")
694+
else()
695+
set(CRT_LIB "libcmt")
696+
set(CXX_LIB "libcpmt")
697+
endif()
698+
699+
target_link_libraries(${target} PRIVATE ${CRT_LIB}${LIB_SUFFIX}) # C runtime startup files
700+
target_link_libraries(${target} PRIVATE ${CXX_LIB}${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
693701
# Required for standards-complaint wide character formatting functions
694702
# (e.g. `printfw`/`scanfw`)
695703
target_link_libraries(${target} PRIVATE iso_stdio_wide_specifiers)

libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
55

66
dbg_include = ''
7-
lib_suffix = ''
7+
runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
8+
9+
if runtime_library == '' or runtime_library.endswith('DLL'):
10+
crt_lib = 'msvcrt'
11+
cxx_lib = 'msvcprt'
12+
else:
13+
crt_lib = 'libcmt'
14+
cxx_lib = 'libcpmt'
815

916
if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
1017
dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
11-
lib_suffix = 'd'
18+
crt_lib += 'd'
19+
cxx_lib += 'd'
1220

1321
config.substitutions.append(('%{flags}', '--driver-mode=g++'))
1422
config.substitutions.append(('%{compile_flags}',
1523
'-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
1624
))
1725
config.substitutions.append(('%{link_flags}',
18-
'-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
26+
'-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
1927
))
2028
config.substitutions.append(('%{exec}',
2129
'%{executor} --execdir %T --prepend_env PATH=%{lib} -- '

libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,26 @@
55
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
66

77
dbg_include = ''
8-
lib_suffix = ''
8+
runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
9+
10+
if runtime_library == '' or runtime_library.endswith('DLL'):
11+
crt_lib = 'msvcrt'
12+
cxx_lib = 'msvcprt'
13+
else:
14+
crt_lib = 'libcmt'
15+
cxx_lib = 'libcpmt'
916

1017
if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
1118
dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
12-
lib_suffix = 'd'
19+
crt_lib += 'd'
20+
cxx_lib += 'd'
1321

1422
config.substitutions.append(('%{flags}', '--driver-mode=g++'))
1523
config.substitutions.append(('%{compile_flags}',
1624
'-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
1725
))
1826
config.substitutions.append(('%{link_flags}',
19-
'-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
27+
'-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
2028
))
2129
config.substitutions.append(('%{exec}',
2230
'%{executor} --execdir %T --prepend_env PATH=%{lib} -- '

libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
55

66
dbg_include = ''
7-
lib_suffix = ''
7+
runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@'
8+
9+
if runtime_library == '' or runtime_library.endswith('DLL'):
10+
crt_lib = 'msvcrt'
11+
cxx_lib = 'msvcprt'
12+
else:
13+
crt_lib = 'libcmt'
14+
cxx_lib = 'libcpmt'
815

916
if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG':
1017
dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h'
11-
lib_suffix = 'd'
18+
crt_lib += 'd'
19+
cxx_lib += 'd'
1220

1321
config.substitutions.append(('%{flags}', '--driver-mode=g++'))
1422
config.substitutions.append(('%{compile_flags}',
1523
'-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
1624
))
1725
config.substitutions.append(('%{link_flags}',
18-
'-nostdlib -L %%{lib} -llibc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix)
26+
'-nostdlib -L %%{lib} -llibc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib)
1927
))
2028
config.substitutions.append(('%{exec}',
2129
'%{executor} --execdir %T -- '

libcxx/utils/ci/buildkite-pipeline.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,19 @@ steps:
777777
limit: 2
778778
timeout_in_minutes: 120
779779

780+
- label: "Clang-cl (Static CRT)"
781+
command: "bash libcxx/utils/ci/run-buildbot clang-cl-static-crt"
782+
artifact_paths:
783+
- "**/test-results.xml"
784+
- "**/*.abilist"
785+
agents:
786+
queue: "windows"
787+
retry:
788+
automatic:
789+
- exit_status: -1 # Agent was lost
790+
limit: 2
791+
timeout_in_minutes: 120
792+
780793
- label: "MinGW (DLL, x86_64)"
781794
command: "bash libcxx/utils/ci/run-buildbot mingw-dll"
782795
artifact_paths:

libcxx/utils/ci/run-buildbot

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,15 @@ clang-cl-debug)
646646
echo "+++ Running the libc++ tests"
647647
${NINJA} -vC "${BUILD_DIR}" check-cxx
648648
;;
649+
clang-cl-static-crt)
650+
clean
651+
# Test linking a static libc++ with the static CRT ("MultiThreaded" denotes
652+
# the static CRT, as opposed to "MultiThreadedDLL" which is the default).
653+
generate-cmake-libcxx-win -DLIBCXX_ENABLE_SHARED=OFF \
654+
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
655+
echo "+++ Running the libc++ tests"
656+
${NINJA} -vC "${BUILD_DIR}" check-cxx
657+
;;
649658
mingw-dll)
650659
clean
651660
# Explicitly specify the compiler with a triple prefix. The CI

0 commit comments

Comments
 (0)