aboutsummaryrefslogtreecommitdiff
path: root/cmake/NativeCompiler.cmake
blob: bd536f44d3bcd30b94f590fc145709e22907228b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

# Native output is independent of the optional -r execution engine.
find_package(Clang REQUIRED CONFIG HINTS "${LLVM_INSTALL_PREFIX}/lib/cmake/clang")
cpsc_find_dependency(PATH LLD_DIR NAMES LLDConfig.cmake PATH_SUFFIXES lib/cmake/lld cmake)
find_package(LLD REQUIRED CONFIG HINTS "${LLVM_INSTALL_PREFIX}/lib/cmake/lld")
find_package(Python3 3.9 REQUIRED COMPONENTS Interpreter)
if(NOT LLVM_ENABLE_ZLIB)
    message(FATAL_ERROR "Native link resources require LLVM built with zlib support")
endif()

if(MINGW)
    set(cpsc_native_platform windows)
    set(cpsc_linker_libraries lldMinGW lldCOFF)
elseif(APPLE)
    set(cpsc_native_platform macos)
    set(cpsc_linker_libraries lldMachO)
else()
    set(cpsc_native_platform linux)
    set(cpsc_linker_libraries lldELF)
endif()

foreach(cpsc_native_library clangDriver ${cpsc_linker_libraries})
    get_target_property(cpsc_native_type ${cpsc_native_library} TYPE)
    if(NOT cpsc_native_type STREQUAL "STATIC_LIBRARY")
        message(FATAL_ERROR "Native output requires static ${cpsc_native_library}; found ${cpsc_native_type}. See doc/build.md for static dependency setup.")
    endif()
endforeach()

set(cpsc_native_flags)
get_filename_component(cpsc_lld_prefix "${LLD_DIR}/../../.." ABSOLUTE)
if(APPLE)
    set(cpsc_linker_names ld64.lld)
else()
    set(cpsc_linker_names ld.lld-23 ld.lld)
endif()
find_program(CPSC_NATIVE_LINKER NAMES ${cpsc_linker_names}
    HINTS "${cpsc_lld_prefix}/bin" ${CPSC_LOCAL_BIN_DIRS})
if(NOT CPSC_NATIVE_LINKER)
    message(FATAL_ERROR "Install the LLD 23 executable to prepare native link resources")
endif()
list(APPEND cpsc_native_flags "--flag=--ld-path=${CPSC_NATIVE_LINKER}")
target_link_options(cpsc PRIVATE -fuse-ld=lld "--ld-path=${CPSC_NATIVE_LINKER}")
if(CMAKE_SYSROOT)
    list(APPEND cpsc_native_flags "--flag=--sysroot=${CMAKE_SYSROOT}")
endif()
if(APPLE)
    if(NOT CMAKE_OSX_SYSROOT)
        execute_process(COMMAND xcrun --show-sdk-path
            OUTPUT_VARIABLE CMAKE_OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE
            RESULT_VARIABLE cpsc_sdk_result)
        if(NOT cpsc_sdk_result EQUAL 0)
            message(FATAL_ERROR "Cannot locate the macOS SDK")
        endif()
    endif()
    list(APPEND cpsc_native_flags "--flag=-isysroot" "--flag=${CMAKE_OSX_SYSROOT}")
    if(CMAKE_OSX_DEPLOYMENT_TARGET)
        list(APPEND cpsc_native_flags "--flag=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
    endif()
endif()
set(cpsc_runtime_generator "${CMAKE_SOURCE_DIR}/tools/driver/prepare-native-runtime.py")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${cpsc_runtime_generator}")
execute_process(COMMAND "${Python3_EXECUTABLE}" "${cpsc_runtime_generator}"
    "--compiler=${CMAKE_CXX_COMPILER}"
    "--output=${CMAKE_BINARY_DIR}/native-runtime/NativeRuntime.inc"
    "--platform=${cpsc_native_platform}" ${cpsc_native_flags}
    RESULT_VARIABLE cpsc_runtime_result OUTPUT_VARIABLE cpsc_runtime_output
    ERROR_VARIABLE cpsc_runtime_error)
if(NOT cpsc_runtime_result EQUAL 0)
    message(FATAL_ERROR "Cannot prepare native link resources: ${cpsc_runtime_error}")
endif()
message(STATUS "${cpsc_runtime_output}")
include("${CMAKE_BINARY_DIR}/native-runtime/native-runtime-inputs.cmake")

target_sources(cpsc PRIVATE tools/driver/NativeCompiler.cc)
target_include_directories(cpsc PRIVATE ${CLANG_INCLUDE_DIRS} ${LLD_INCLUDE_DIRS}
    "${CMAKE_BINARY_DIR}/native-runtime")
target_link_libraries(cpsc PRIVATE clangDriver ${cpsc_linker_libraries})
if(MINGW AND TARGET LibXml2::LibXml2)
    # LLD's COFF manifest support reaches libxml2 through LLVMWindowsManifest.
    # An explicit .dll.a in that interface bypasses the driver's -static flag.
    cpsc_find_dependency(LIBRARY CPSC_STATIC_xml2 REQUIRED NAMES libxml2.a)
    cpsc_find_dependency(LIBRARY CPSC_STATIC_iconv REQUIRED NAMES libiconv.a)
    add_library(CPSCStaticXML2 INTERFACE)
    # The prebuilt LLVM archive uses dllimport references. Load XML definitions
    # before LLD resolves those references to local symbols.
    target_link_libraries(CPSCStaticXML2 INTERFACE
        -Wl,--whole-archive "${CPSC_STATIC_xml2}" -Wl,--no-whole-archive
        "${CPSC_STATIC_iconv}" "${CPSC_STATIC_z}" bcrypt)
    get_target_property(cpsc_manifest_libs LLVMWindowsManifest INTERFACE_LINK_LIBRARIES)
    list(TRANSFORM cpsc_manifest_libs REPLACE "^LibXml2::LibXml2$" CPSCStaticXML2)
    set_property(TARGET LLVMWindowsManifest PROPERTY INTERFACE_LINK_LIBRARIES "${cpsc_manifest_libs}")
endif()
# Distribution Clang/LLD archives can still name the shared LLVM umbrella
# library in their imported interfaces. Resolve those edges to static archives.
add_library(CPSCStaticLLVM INTERFACE)
foreach(cpsc_llvm_library IN LISTS LLVM_AVAILABLE_LIBS)
    # Standalone tools and HTTP/debuginfod clients are not driver/linker
    # dependencies. Keep their optional LibEdit/CURL packages optional.
    if(cpsc_llvm_library MATCHES "^LLVM(LineEditor|BOLT.*|Exegesis.*|OptDriver|HTTP|Debuginfod)$")
        continue()
    endif()
    if(TARGET ${cpsc_llvm_library})
        get_target_property(cpsc_llvm_type ${cpsc_llvm_library} TYPE)
        if(cpsc_llvm_type STREQUAL "STATIC_LIBRARY")
            target_link_libraries(CPSCStaticLLVM INTERFACE ${cpsc_llvm_library})
        endif()
    endif()
endforeach()
foreach(cpsc_import IN LISTS CLANG_EXPORTED_TARGETS LLD_EXPORTED_TARGETS LLVM_AVAILABLE_LIBS)
    if(NOT TARGET ${cpsc_import})
        continue()
    endif()
    get_target_property(cpsc_interface ${cpsc_import} INTERFACE_LINK_LIBRARIES)
    if(cpsc_interface)
        list(FIND cpsc_interface LLVM cpsc_shared_llvm_index)
        if(NOT cpsc_shared_llvm_index EQUAL -1)
            list(REMOVE_ITEM cpsc_interface LLVM)
            if(NOT cpsc_import IN_LIST LLVM_AVAILABLE_LIBS)
                list(APPEND cpsc_interface CPSCStaticLLVM)
            endif()
        endif()
        if(CPSC_STATIC_z)
            list(TRANSFORM cpsc_interface REPLACE "^ZLIB::ZLIB$" "${CPSC_STATIC_z}")
        endif()
        if(CPSC_STATIC_zstd)
            list(TRANSFORM cpsc_interface REPLACE "^zstd::libzstd.*$" "${CPSC_STATIC_zstd}")
        endif()
        set_property(TARGET ${cpsc_import} PROPERTY INTERFACE_LINK_LIBRARIES "${cpsc_interface}")
    endif()
endforeach()