summaryrefslogtreecommitdiffstats
path: root/cmake/FindWrapLibClang.cmake
blob: e79b3cf6a8f8a13aa49e1e4de0dc01d9640252ba (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause

if(TARGET WrapLibClang::WrapLibClang)
    set(WrapLibClang_FOUND TRUE)
    return()
endif()

if(DEFINED ENV{LLVM_INSTALL_DIR})
    set(__qt_wrap_clang_backup_prefix "${CMAKE_PREFIX_PATH}")
    list(PREPEND CMAKE_PREFIX_PATH "$ENV{LLVM_INSTALL_DIR}")
elseif(DEFINED CACHE{LLVM_INSTALL_DIR})
    set(__qt_wrap_clang_backup_prefix "${CMAKE_PREFIX_PATH}")
    list(PREPEND CMAKE_PREFIX_PATH "${LLVM_INSTALL_DIR}")
endif()

include(FindPackageHandleStandardArgs)
set(WrapLibClang_FOUND FALSE)

# Find the zstd package before llvm gets a chance to plant its Findzstd.cmake on us. That find
# module is most likely inconsistent with your system-provided llvmConfig.cmake, leading to
# configuration errors. Disable find_package(zstd) within llvm if FindWrapZSTD.cmake was successful.
# Upstream issue: https://github.com/llvm/llvm-project/issues/139666
if(QT_FEATURE_zstd)
    find_package(WrapZSTD QUIET)
    set(__qt_wraplibclang_CMAKE_DISABLE_FIND_PACKAGE_zstd ${CMAKE_DISABLE_FIND_PACKAGE_zstd})
    if(WrapZSTD_FOUND)
        set(CMAKE_DISABLE_FIND_PACKAGE_zstd TRUE)
    endif()
endif()

if(QT_NO_FIND_PACKAGE_CLANG_WORKAROUND)
    set(Clang_FOUND FALSE)
    foreach(VERSION ${QDOC_SUPPORTED_CLANG_VERSIONS})
        if(NOT Clang_FOUND)
            find_package(Clang ${VERSION} CONFIG QUIET)
        endif()
    endforeach()
else()
    set(__qt_wraplibclang_message
        "This probably means that one or more packages necessary for find_package(Clang) are not"
        "installed. See below for more information. You can turn off this pre-check by setting the"
        "CMake variable QT_NO_FIND_PACKAGE_CLANG_WORKAROUND to ON."
    )

    # Try to find the LLVM package. ClangConfig.cmake has a find_package(LLVM REQUIRED) call, which
    # will break if clang is installed but the LLVM CMake files are not installed.
    set(LLVM_FOUND FALSE)
    foreach(VERSION ${QDOC_SUPPORTED_CLANG_VERSIONS})
        if(NOT LLVM_FOUND)
            find_package(LLVM ${VERSION} CONFIG QUIET)
        endif()
    endforeach()
    if(NOT LLVM_FOUND)
        list(PREPEND __qt_wraplibclang_message "The LLVM package could not be found.")
        string(REPLACE ";" " " __qt_wraplibclang_message "${__qt_wraplibclang_message}")
        find_package_handle_standard_args(WrapLibClang
            REQUIRED_VARS WrapLibClang_FOUND
            REASON_FAILURE_MESSAGE "${__qt_wraplibclang_message}")
        unset(__qt_wraplibclang_message)
        return()
    endif()

    # Try to find libClang libraries - either one of the static libs or the whole shared object.
    # ClangTargets.cmake checks for the presence of these libraries.
    find_library(__qt_wraplibclang clangBasic HINTS ${LLVM_LIBRARY_DIRS})
    if(__qt_wraplibclang STREQUAL "__qt_wraplibclang-NOTFOUND")
        unset(__qt_wraplibclang CACHE)
        find_library(__qt_wraplibclang clang HINTS ${LLVM_LIBRARY_DIRS})
    endif()
    if(__qt_wraplibclang STREQUAL "__qt_wraplibclang-NOTFOUND")
        unset(__qt_wraplibclang CACHE)
        list(PREPEND __qt_wraplibclang_message "The clang libraries could not be located.")
        string(REPLACE ";" " " __qt_wraplibclang_message "${__qt_wraplibclang_message}")
        find_package_handle_standard_args(WrapLibClang
            REQUIRED_VARS WrapLibClang_FOUND
            REASON_FAILURE_MESSAGE "${__qt_wraplibclang_message}")
        unset(__qt_wraplibclang_message)
        return()
    endif()
    unset(__qt_wraplibclang CACHE)

    # Now, we're pretty certain that we can find the 'Clang' package without running into errors.
    find_package(Clang ${LLVM_VERSION} EXACT CONFIG)
endif()

if(QT_FEATURE_zstd)
    set(CMAKE_DISABLE_FIND_PACKAGE_zstd ${__qt_wraplibclang_CMAKE_DISABLE_FIND_PACKAGE_zstd})
endif()

# LLVM versions >= 16 come with Findzstd.cmake that creates a target for libzstd.
# Disable its global promotion to prevent interference with FindWrapZSTD.cmake.
if(TARGET zstd::libzstd)
    qt_internal_disable_find_package_global_promotion(zstd::libzstd)
endif()
if(TARGET zstd::libzstd_shared)
    qt_internal_disable_find_package_global_promotion(zstd::libzstd_shared)
endif()
if(TARGET zstd::libzstd_static)
    qt_internal_disable_find_package_global_promotion(zstd::libzstd_static)
endif()

if(__qt_wrap_clang_backup_prefix)
    set(CMAKE_PREFIX_PATH "${__qt_wrap_clang_backup_prefix}")
    unset(__qt_wrap_clang_backup_prefix)
endif()

set(__wrap_lib_clang_requested_version_found FALSE)

# Need to explicitly handle the version check, because the Clang package doesn't.
if(WrapLibClang_FIND_VERSION AND LLVM_PACKAGE_VERSION
        AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL "${WrapLibClang_FIND_VERSION}")
    set(__wrap_lib_clang_requested_version_found TRUE)
endif()

if(TARGET libclang AND ((TARGET clang-cpp AND TARGET LLVM) OR TARGET clangHandleCXX) AND __wrap_lib_clang_requested_version_found)
    set(WrapLibClang_FOUND TRUE)

    get_target_property(type libclang TYPE)
    if (MSVC AND type STREQUAL "STATIC_LIBRARY")
        get_property(__wrap_lib_clang_multi_config
            GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
        if(__wrap_lib_clang_multi_config)
            set(__wrap_lib_clang_configs ${CMAKE_CONFIGURATION_TYPES})
        else()
            set(__wrap_lib_clang_configs ${CMAKE_BUILD_TYPE})
        endif()
        set(__wrap_lib_clang_non_release_configs ${configs})
        list(REMOVE_ITEM __wrap_lib_clang_non_release_configs
            Release MinSizeRel RelWithDebInfo)
        if(__wrap_lib_clang_non_release_configs STREQUAL __wrap_lib_clang_configs)
            message(STATUS "Static linkage against libclang with MSVC was requested, but the build is not a release build, therefore libclang cannot be used.")
            set(WrapLibClang_FOUND FALSE)
        endif()
    endif()

    if(WrapLibClang_FOUND)
        add_library(WrapLibClang::WrapLibClang IMPORTED INTERFACE)

        target_include_directories(WrapLibClang::WrapLibClang INTERFACE ${CLANG_INCLUDE_DIRS})
        if (NOT TARGET Threads::Threads)
            find_package(Threads)
        endif()
        qt_internal_disable_find_package_global_promotion(Threads::Threads)
        # lupdate must also link to LLVM when using clang-cpp
        set(__qt_clang_genex_condition "$<AND:$<TARGET_EXISTS:clang-cpp>,$<TARGET_EXISTS:LLVM>>")
        set(__qt_clang_genex "$<IF:${__qt_clang_genex_condition},clang-cpp;LLVM,clangHandleCXX>")
        target_link_libraries(WrapLibClang::WrapLibClang
            INTERFACE libclang
            "${__qt_clang_genex}"
            Threads::Threads
            )

        foreach(version MAJOR MINOR PATCH)
            set(QT_LIB_CLANG_VERSION_${version} ${LLVM_VERSION_${version}} CACHE STRING "" FORCE)
        endforeach()
        set(QT_LIB_CLANG_VERSION ${LLVM_PACKAGE_VERSION} CACHE STRING "" FORCE)
        set(QT_LIB_CLANG_LIBDIR "${LLVM_LIBRARY_DIRS}" CACHE STRING "" FORCE)
        set(QT_LIBCLANG_RESOURCE_DIR
            "\"${QT_LIB_CLANG_LIBDIR}/clang/${QT_LIB_CLANG_VERSION}/include\"" CACHE STRING "" FORCE)
    endif()
endif()

find_package_handle_standard_args(WrapLibClang
    REQUIRED_VARS WrapLibClang_FOUND
    VERSION_VAR LLVM_PACKAGE_VERSION)