mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 19:00:54 -06:00
LLVMFlang: Add support for targeting MSVC ABI on Windows
The compiler does not yet support everything needed to integrate well with the MSVC ABI, in particular for runtime library selection and debug format selection. Document them in FIXME comments and leave this support undocumented by CMake for now. Fixes: #24840 Inspired-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
This commit is contained in:
@@ -174,6 +174,32 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FIXME(LLVMFlang): It does not provide predefines identifying the MSVC ABI or architecture.
|
||||
# It should be taught to define _MSC_VER and its _M_* architecture flags.
|
||||
if("x${lang}" STREQUAL "xFortran" AND "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xLLVMFlang")
|
||||
# Parse the target triple to detect information we should later be able
|
||||
# to get during preprocessing above, once LLVMFlang provides it.
|
||||
if(COMPILER_${lang}_PRODUCED_OUTPUT MATCHES "-triple ([0-9a-z_]*)-.*windows-msvc([0-9]+)\\.([0-9]+)")
|
||||
set(CMAKE_${lang}_SIMULATE_ID "MSVC")
|
||||
set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
||||
set(arch ${CMAKE_MATCH_1})
|
||||
if(arch STREQUAL "x86_64")
|
||||
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "x64")
|
||||
elseif(arch STREQUAL "aarch64")
|
||||
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "ARM64")
|
||||
elseif(arch STREQUAL "arm64ec")
|
||||
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "ARM64EC")
|
||||
elseif(arch MATCHES "^i[3-9]86$")
|
||||
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "X86")
|
||||
else()
|
||||
message(FATAL_ERROR "LLVMFlang target architecture unrecognized: ${arch}")
|
||||
endif()
|
||||
set(MSVC_${lang}_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}")
|
||||
elseif(COMPILER_${lang}_PRODUCED_OUTPUT MATCHES "-triple ([0-9a-z_]*)-.*windows-gnu")
|
||||
set(CMAKE_${lang}_SIMULATE_ID "GNU")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (COMPILER_QNXNTO AND (CMAKE_${lang}_COMPILER_ID STREQUAL "GNU" OR CMAKE_${lang}_COMPILER_ID STREQUAL "LCC"))
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_${lang}_COMPILER}"
|
||||
|
||||
@@ -98,6 +98,9 @@ else()
|
||||
set(CMAKE_Fortran_COMPILER_ID_TEST_FLAGS_FIRST
|
||||
# Get verbose output to help distinguish compilers.
|
||||
"-v"
|
||||
|
||||
# Try compiling to an object file only, with verbose output.
|
||||
"-v -c"
|
||||
)
|
||||
set(CMAKE_Fortran_COMPILER_ID_TEST_FLAGS
|
||||
# Try compiling to an object file only.
|
||||
@@ -108,6 +111,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_Fortran_COMPILER_TARGET)
|
||||
set(CMAKE_Fortran_COMPILER_ID_TEST_FLAGS_FIRST "-v -c --target=${CMAKE_Fortran_COMPILER_TARGET}")
|
||||
endif()
|
||||
|
||||
# Build a small source file to identify the compiler.
|
||||
if(NOT CMAKE_Fortran_COMPILER_ID_RUN)
|
||||
set(CMAKE_Fortran_COMPILER_ID_RUN 1)
|
||||
@@ -227,6 +234,49 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if("${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "LLVMFlang;MSVC")
|
||||
# With LLVMFlang targeting the MSVC ABI we link using lld-link.
|
||||
# Detect the implicit link information from the compiler driver
|
||||
# so we can explicitly pass it to the linker.
|
||||
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
|
||||
set(_LLVMFlang_COMMAND "${CMAKE_Fortran_COMPILER}" "-###" ${CMAKE_CURRENT_LIST_DIR}/CMakeFortranCompilerABI.F)
|
||||
if(CMAKE_Fortran_COMPILER_TARGET)
|
||||
list(APPEND _LLVMFlang_COMMAND --target=${CMAKE_Fortran_COMPILER_TARGET})
|
||||
endif()
|
||||
execute_process(COMMAND ${_LLVMFlang_COMMAND}
|
||||
OUTPUT_VARIABLE _LLVMFlang_OUTPUT
|
||||
ERROR_VARIABLE _LLVMFlang_OUTPUT
|
||||
RESULT_VARIABLE _LLVMFlang_RESULT)
|
||||
string(JOIN "\" \"" _LLVMFlang_COMMAND ${_LLVMFlang_COMMAND})
|
||||
message(CONFIGURE_LOG
|
||||
"Running the Fortran compiler: \"${_LLVMFlang_COMMAND}\"\n"
|
||||
"${_LLVMFlang_OUTPUT}"
|
||||
)
|
||||
if(_LLVMFlang_RESULT EQUAL 0)
|
||||
cmake_parse_implicit_link_info("${_LLVMFlang_OUTPUT}"
|
||||
CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES
|
||||
CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES
|
||||
CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
|
||||
log
|
||||
"${CMAKE_Fortran_IMPLICIT_OBJECT_REGEX}"
|
||||
LANGUAGE Fortran)
|
||||
message(CONFIGURE_LOG
|
||||
"Parsed Fortran implicit link information:\n"
|
||||
"${log}\n"
|
||||
)
|
||||
set(_CMAKE_Fortran_IMPLICIT_LINK_INFORMATION_DETERMINED_EARLY 1)
|
||||
if("x${CMAKE_Fortran_COMPILER_ARCHITECTURE_ID}" STREQUAL "xARM64")
|
||||
# FIXME(LLVMFlang): It does not add `-defaultlib:` fields to object
|
||||
# files to specify link dependencies on its runtime libraries.
|
||||
# For now, we add them ourselves.
|
||||
list(APPEND CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "clang_rt.builtins-aarch64.lib")
|
||||
endif()
|
||||
endif()
|
||||
unset(_LLVMFlang_COMMAND)
|
||||
unset(_LLVMFlang_OUTPUT)
|
||||
unset(_LLVMFlang_RESULT)
|
||||
endif()
|
||||
|
||||
if (NOT _CMAKE_TOOLCHAIN_LOCATION)
|
||||
get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_Fortran_COMPILER}" PATH)
|
||||
endif ()
|
||||
|
||||
@@ -79,7 +79,7 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND
|
||||
set(_CMAKE_MT_NAMES "mt")
|
||||
|
||||
# Prepend toolchain-specific names.
|
||||
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xClang")
|
||||
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^x(Clang|LLVMFlang)$")
|
||||
set(_CMAKE_NM_NAMES "llvm-nm" "nm")
|
||||
list(PREPEND _CMAKE_AR_NAMES "llvm-lib")
|
||||
# llvm-mt is not ready to be used as a replacement for mt.exe
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
set(CMAKE_Fortran_VERBOSE_FLAG "-v")
|
||||
|
||||
set(CMAKE_Fortran_SUBMODULE_SEP "-")
|
||||
set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
|
||||
|
||||
@@ -17,6 +15,10 @@ set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
|
||||
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
|
||||
|
||||
string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
|
||||
if(NOT "x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
set(CMAKE_Fortran_VERBOSE_FLAG "-v")
|
||||
|
||||
string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,58 @@
|
||||
include(Platform/Windows-GNU)
|
||||
__windows_compiler_gnu(Fortran)
|
||||
# TODO: MSVC ABI Support
|
||||
if("x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xGNU")
|
||||
include(Platform/Windows-GNU)
|
||||
__windows_compiler_gnu(Fortran)
|
||||
elseif("x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
include(Platform/Windows-MSVC)
|
||||
__windows_compiler_msvc(Fortran)
|
||||
|
||||
# FIXME(LLVMFlang): It does not provides MSVC runtime library selection flags.
|
||||
# It should be given a flag like classic Flang's `-Xclang --dependent-lib=`, or a
|
||||
# dedicated flag to select among multiple `Fortran*.lib` runtime library variants
|
||||
# that each depend on a different MSVC runtime library. For now, LLVMFlang's
|
||||
# `Fortran*.lib` runtime libraries hard-code use of msvcrt (MultiThreadedDLL),
|
||||
# so we link to it ourselves.
|
||||
set(_LLVMFlang_LINK_RUNTIME "-defaultlib:msvcrt")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
|
||||
|
||||
# FIXME(LLVMFlang): It does not provide all debug information format flags or predefines.
|
||||
# It should be given a flag to enable Embedded debug information like MSVC -Z7.
|
||||
#set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded) # not supported by LLVMFlang
|
||||
#set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # not supported by LLVMFlang
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "-g")
|
||||
|
||||
set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
|
||||
|
||||
if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)
|
||||
set(_g "")
|
||||
else()
|
||||
set(_g " -g")
|
||||
endif()
|
||||
string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT "${_g}")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT "")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT "${_g}")
|
||||
string(APPEND CMAKE_Fortran_FLAGS_MINSIZEREL_INIT "")
|
||||
unset(_g)
|
||||
|
||||
# We link with lld-link.exe instead of the compiler driver, so explicitly
|
||||
# pass implicit link information previously detected from the compiler.
|
||||
set(_LLVMFlang_LINK_DIRS "${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES}")
|
||||
list(TRANSFORM _LLVMFlang_LINK_DIRS PREPEND "-libpath:\"")
|
||||
list(TRANSFORM _LLVMFlang_LINK_DIRS APPEND "\"")
|
||||
string(JOIN " " _LLVMFlang_LINK_DIRS ${_LLVMFlang_LINK_DIRS})
|
||||
string(JOIN " " _LLVMFlang_LINK_LIBS ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES})
|
||||
foreach(v IN ITEMS
|
||||
CMAKE_Fortran_LINK_EXECUTABLE
|
||||
CMAKE_Fortran_CREATE_SHARED_LIBRARY
|
||||
CMAKE_Fortran_CREATE_SHARED_MODULE
|
||||
)
|
||||
string(APPEND "${v}" " ${_LLVMFlang_LINK_DIRS} ${_LLVMFlang_LINK_LIBS} ${_LLVMFlang_LINK_RUNTIME}")
|
||||
endforeach()
|
||||
unset(_LLVMFlang_LINK_DIRS)
|
||||
unset(_LLVMFlang_LINK_LIBS)
|
||||
unset(_LLVMFlang_LINK_RUNTIME)
|
||||
else()
|
||||
message(FATAL_ERROR "LLVMFlang target ABI unrecognized: ${CMAKE_Fortran_SIMULATE_ID}")
|
||||
endif()
|
||||
|
||||
@@ -439,6 +439,10 @@ if(BUILD_TESTING)
|
||||
set(CMAKE_SKIP_VSGNUFortran TRUE)
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID STREQUAL LLVMFlang)
|
||||
# No DLLEXPORT for 'Tests/VSGNUFortran/subdir/fortran/world.f'.
|
||||
set(CMAKE_SKIP_VSGNUFortran TRUE)
|
||||
endif()
|
||||
if(CMAKE_Fortran_COMPILER_ID STREQUAL IntelLLVM)
|
||||
message(STATUS "Skip VSGNUFortran for ifx until DLLEXPORT support is implemented")
|
||||
set(CMAKE_SKIP_VSGNUFortran TRUE)
|
||||
@@ -2150,7 +2154,10 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
set(MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
if(CMAKE_Fortran_COMPILER
|
||||
# FIXME(LLVMFlang): It does not provide debug information format flags or predefines.
|
||||
AND NOT CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang"
|
||||
)
|
||||
list(APPEND MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_Fortran=1)
|
||||
endif()
|
||||
ADD_TEST_MACRO(MSVCDebugInformationFormat)
|
||||
|
||||
@@ -29,7 +29,7 @@ endif()
|
||||
# Pick a module .def file with the properly mangled symbol name.
|
||||
set(world_def "")
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU|LCC")
|
||||
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU|LCC|LLVMFlang")
|
||||
set(world_def world_gnu.def)
|
||||
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel" OR
|
||||
CMAKE_GENERATOR MATCHES "Visual Studio") # Intel plugin
|
||||
|
||||
@@ -21,6 +21,13 @@ foreach(t MultiThreaded SingleThreaded)
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
if(CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
|
||||
# LLVMFlang does not actually define these, so inject them
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "-D_MT")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "-D_MT;-D_DLL")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "-D_MT;-D_DEBUG")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "-D_MT;-D_DEBUG;-D_DLL")
|
||||
endif()
|
||||
string(APPEND CMAKE_Fortran_FLAGS " -w")
|
||||
|
||||
function(verify_combinations threads lang src)
|
||||
|
||||
Reference in New Issue
Block a user