• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ~~~
2# Copyright (c) 2014-2021 The Khronos Group Inc.
3# Copyright (c) 2014-2021 Valve Corporation
4# Copyright (c) 2014-2021 LunarG, Inc.
5# Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#     http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18# ~~~
19
20# Get version of the API the generated code used and put it into a cmake variable LOADER_GENERATED_HEADER_VERSION
21include(generated/loader_generated_header_version.cmake)
22
23add_library(loader_specific_options INTERFACE)
24target_link_libraries(loader_specific_options INTERFACE loader_common_options Vulkan::Headers)
25target_include_directories(loader_specific_options INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/generated ${CMAKE_CURRENT_BINARY_DIR})
26
27if(WIN32)
28    if(MSVC)
29        # Use static MSVCRT libraries
30        foreach(configuration
31                in
32                CMAKE_C_FLAGS_DEBUG
33                CMAKE_C_FLAGS_MINSIZEREL
34                CMAKE_C_FLAGS_RELEASE
35                CMAKE_C_FLAGS_RELWITHDEBINFO
36                CMAKE_CXX_FLAGS_DEBUG
37                CMAKE_CXX_FLAGS_MINSIZEREL
38                CMAKE_CXX_FLAGS_RELEASE
39                CMAKE_CXX_FLAGS_RELWITHDEBINFO)
40            if(${configuration} MATCHES "/MD")
41                string(REGEX
42                    REPLACE "/MD"
43                            "/MT"
44                            ${configuration}
45                            "${${configuration}}")
46            endif()
47        endforeach()
48    endif()
49
50    if(ENABLE_WIN10_ONECORE)
51        # Note: When linking your app or driver to OneCore.lib, be sure to remove any links to non-umbrella libs (such as
52        # kernel32.lib).
53        set(CMAKE_CXX_STANDARD_LIBRARIES " ") # space is intentional
54        set(CMAKE_C_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES})
55    endif()
56
57    target_compile_options(loader_specific_options INTERFACE -D_CRT_SECURE_NO_WARNINGS)
58    # ~~~
59    # Build dev_ext_trampoline.c and unknown_ext_chain.c with /O2 to allow tail-call optimization.
60    # Setup two CMake targets (loader-norm and loader-opt) for the different compilation flags.
61    # ~~~
62    set(MODIFIED_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
63
64    string(REPLACE "/Od" "/O2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG})
65    string(REPLACE "/Ob0" "/Ob2" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG})
66    string(REGEX REPLACE "/RTC." "" MODIFIED_C_FLAGS_DEBUG ${MODIFIED_C_FLAGS_DEBUG})  #remove run-time error checks
67
68    separate_arguments(MODIFIED_C_FLAGS_DEBUG WINDOWS_COMMAND ${MODIFIED_C_FLAGS_DEBUG})
69
70    # ~~~
71    # Setup the loader.rc flie to contain the correct info
72    # Optionally uses the BUILD_DLL_VERSIONINFO build option to allow setting the exact build version
73    # Adds "Dev Build" to any build without the BUILD_DLL_VERSIONINFO option set
74    # ~~~
75    if ("$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "")
76        # default case - use 0 as the BUILDNO
77        set(LOADER_RC_VERSION "1.0.1111.2222")
78        set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}.Dev Build\"")
79        set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader - Dev Build\"")
80    else()
81        set(LOADER_RC_VERSION "$CACHE{BUILD_DLL_VERSIONINFO}")
82        set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}\"")
83        set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader\"")
84    endif()
85
86    # RC file wants the value of FILEVERSION to separated by commas
87    string(REPLACE "." ", " LOADER_VER_FILE_VERSION "${LOADER_RC_VERSION}")
88
89    # Configure the file to include the versioning info
90    # Place it in the current directory for check-in - so the GN build has up to date info
91    configure_file(loader.rc.in ${CMAKE_CURRENT_LIST_DIR}/loader.rc)
92else()
93    # Used to make alloca() and secure_getenv() available
94    target_compile_definitions(loader_specific_options INTERFACE _GNU_SOURCE)
95    if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
96        target_compile_definitions(loader_specific_options INTERFACE __BSD_VISIBLE=1)
97    endif()
98    check_include_file("alloca.h" HAVE_ALLOCA_H)
99    if(HAVE_ALLOCA_H)
100        target_compile_definitions(loader_specific_options INTERFACE HAVE_ALLOCA_H)
101    endif()
102endif()
103
104set(NORMAL_LOADER_SRCS
105    allocation.c
106    cJSON.c
107    debug_utils.c
108    extension_manual.c
109    get_environment.c
110    gpa_helper.c
111    loader.c
112    log.c
113    terminator.c
114    trampoline.c
115    unknown_function_handling.c
116    wsi.c
117    )
118
119if(WIN32)
120    list(APPEND NORMAL_LOADER_SRCS loader_windows.c dirent_on_windows.c)
121elseif(UNIX AND NOT APPLE) # i.e.: Linux
122    list(APPEND NORMAL_LOADER_SRCS loader_linux.c)
123    target_compile_definitions(loader_specific_options INTERFACE LOADER_ENABLE_LINUX_SORT)
124endif()
125
126set(OPT_LOADER_SRCS dev_ext_trampoline.c phys_dev_ext.c)
127
128# Check for assembler support
129set(ASM_FAILURE_MSG "The build will fall back on building with C code\n")
130set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG}Note that this may be unsafe, as the C code requires tail-call optimizations to remove")
131set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} the stack frame for certain calls. If the compiler does not do this, then unknown device")
132set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} extensions will suffer from a corrupted stack.")
133if(WIN32)
134    if(MINGW)
135        find_program(JWASM_FOUND jwasm)
136        if (JWASM_FOUND)
137            set(CMAKE_ASM_MASM_COMPILER ${JWASM_FOUND})
138            execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE COMPILER_VERSION_OUTPUT)
139            if (COMPILER_VERSION_OUTPUT)
140                if (COMPILER_VERSION_OUTPUT MATCHES "x86_64")
141                    set(JWASM_FLAGS -win64)
142                else()
143                    set(JWASM_FLAGS -coff)
144                endif()
145            endif()
146        endif()
147    endif()
148    option(USE_MASM "Use MASM" ON)
149    if (USE_MASM)
150      enable_language(ASM_MASM)
151    endif ()
152    if(CMAKE_ASM_MASM_COMPILER_WORKS OR JWASM_FOUND)
153        if(MINGW)
154            set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} ${JWASM_FLAGS})
155        elseif(NOT CMAKE_CL_64 AND NOT JWASM_FOUND)
156            set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh)
157        endif()
158
159        add_executable(asm_offset asm_offset.c)
160        target_link_libraries(asm_offset loader_specific_options)
161        add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset MASM)
162        add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
163        set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER})
164        add_library(loader-unknown-chain OBJECT unknown_ext_chain_masm.asm)
165        target_link_libraries(loader-unknown-chain Vulkan::Headers)
166        target_include_directories(loader-unknown-chain PUBLIC $<TARGET_PROPERTY:loader_asm_gen_files,BINARY_DIR>)
167        add_dependencies(loader-unknown-chain loader_asm_gen_files)
168    else()
169        message(WARNING "Could not find working MASM assembler\n${ASM_FAILURE_MSG}")
170        add_custom_target(loader_asm_gen_files)
171        add_library(loader-unknown-chain OBJECT unknown_ext_chain.c)
172        target_link_libraries(loader-unknown-chain loader_specific_options)
173        set_target_properties(loader-unknown-chain PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}")
174    endif()
175elseif(APPLE)
176    # For MacOS, use the C code and force the compiler's tail-call optimization instead of using assembly code.
177    set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
178    set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O)
179    add_custom_target(loader_asm_gen_files) # This causes no assembly files to be generated.
180else() # i.e.: Linux
181    option(USE_GAS "Use GAS" ON)
182    if(USE_GAS)
183        enable_language(ASM)
184
185        set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
186        set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
187
188        if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
189            try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S)
190            if(ASSEMBLER_WORKS)
191                set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_aarch64.S)
192            endif()
193        elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^i.86$")
194            check_include_file("cet.h" HAVE_CET_H)
195            if(HAVE_CET_H)
196                target_compile_definitions(loader_specific_options INTERFACE HAVE_CET_H)
197            endif()
198
199            try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_x86.S)
200            if(ASSEMBLER_WORKS)
201                set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_x86.S)
202            endif()
203        endif()
204    endif()
205
206    if(ASSEMBLER_WORKS)
207        add_executable(asm_offset asm_offset.c)
208        target_link_libraries(asm_offset loader_specific_options)
209        add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS)
210        add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
211    else()
212        if(USE_GAS)
213            message(WARNING "Could not find working ${CMAKE_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}")
214        else()
215            message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}")
216        endif()
217        set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
218        add_custom_target(loader_asm_gen_files)
219    endif()
220endif()
221
222if(WIN32)
223    add_library(loader-opt STATIC ${OPT_LOADER_SRCS})
224    target_link_libraries(loader-opt PUBLIC loader_specific_options)
225    add_dependencies(loader-opt loader_asm_gen_files)
226    set_target_properties(loader-opt PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}")
227
228    add_library(vulkan
229                SHARED
230                ${NORMAL_LOADER_SRCS}
231                $<TARGET_OBJECTS:loader-unknown-chain>
232                ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-1.def
233                ${CMAKE_CURRENT_LIST_DIR}/loader.rc)
234
235    target_link_libraries(vulkan PRIVATE loader_specific_options loader-opt)
236
237    if (UPDATE_DEPS)
238        add_dependencies(vulkan vl_update_deps)
239    endif()
240
241    # when adding the suffix the import and runtime library names must be consistent
242    # mingw: libvulkan-1.dll.a / vulkan-1.dll
243    # msvc: vulkan-1.lib / vulkan-1.dll
244    set_target_properties(vulkan
245                          PROPERTIES
246                          OUTPUT_NAME vulkan-1)
247    if(MINGW)
248        # generate the same DLL with mingw
249        set_target_properties(vulkan
250                              PROPERTIES
251                              PREFIX "")
252    endif()
253
254    if(MSVC AND ENABLE_WIN10_ONECORE)
255        target_link_libraries(vulkan PRIVATE OneCoreUAP.lib LIBCMT.LIB LIBCMTD.LIB LIBVCRUNTIME.LIB LIBUCRT.LIB)
256        set_target_properties(vulkan PROPERTIES LINK_FLAGS "/NODEFAULTLIB")
257    else()
258       target_link_libraries(vulkan PRIVATE cfgmgr32)
259    endif()
260
261    add_dependencies(vulkan loader_asm_gen_files)
262
263else()
264    if(APPLE AND BUILD_STATIC_LOADER)
265        add_library(vulkan STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
266        target_compile_definitions(vulkan PRIVATE BUILD_STATIC_LOADER)
267    else()
268        add_library(vulkan SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
269    endif()
270    add_dependencies(vulkan loader_asm_gen_files)
271    # set version based on LOADER_GENERATED_HEADER_VERSION used to generate the code
272    set_target_properties(vulkan
273                          PROPERTIES SOVERSION "1"
274                          VERSION ${LOADER_GENERATED_HEADER_VERSION})
275    target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m)
276    if (NOT ANDROID)
277        target_link_libraries(vulkan PRIVATE Threads::Threads)
278    endif()
279
280    if(APPLE)
281        find_library(COREFOUNDATION_LIBRARY NAMES CoreFoundation)
282        target_link_libraries(vulkan PRIVATE "-framework CoreFoundation")
283
284        # Build vulkan.framework
285        # Use GLOB_RECURSE to find all the header files and populate the vulkan.framework headers with them
286        # Use CONFIGURE_DEPENDS to ensure that if the header files are updated, this list is also updated
287        # Note: CONFIGURE_DEPENDS is a 3.12 feature - gate it for now and remove when CMake minimum version is higher
288        if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0")
289            file(GLOB_RECURSE CONFIGURE_DEPENDS FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS})
290        else()
291            file(GLOB_RECURSE FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS})
292        endif()
293        if(BUILD_STATIC_LOADER)
294            add_library(vulkan-framework STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
295        else()
296            add_library(vulkan-framework SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
297        endif()
298        add_dependencies(vulkan-framework loader_asm_gen_files)
299        target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation")
300        target_link_libraries(vulkan-framework loader_specific_options)
301
302        # The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when a user adds their framework to an Xcode
303        # project and does "Sign on Copy". It would have been nicer to use "1" to denote Vulkan 1. Although Apple docs say that a
304        # framework version does not have to be "A", this part of the Apple toolchain expects it.
305        # https://forums.developer.apple.com/thread/65963
306
307# cmake-format: off
308        set_target_properties(vulkan-framework PROPERTIES
309            OUTPUT_NAME vulkan
310            FRAMEWORK TRUE
311            FRAMEWORK_VERSION A
312            VERSION "${LOADER_GENERATED_HEADER_VERSION}" # "current version"
313            SOVERSION "1.0.0"                        # "compatibility version"
314            MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework
315            PUBLIC_HEADER "${FRAMEWORK_HEADERS}"
316        )
317        install(TARGETS vulkan-framework
318            PUBLIC_HEADER DESTINATION vulkan
319            FRAMEWORK DESTINATION loader
320        )
321# cmake-format: on
322    endif()
323endif()
324
325# common attributes of the vulkan library
326target_link_libraries(vulkan PRIVATE loader_specific_options)
327
328set_target_properties(vulkan ${LOADER_STANDARD_C_PROPERTIES})
329if (TARGET asm_offset)
330    set_target_properties(asm_offset ${LOADER_STANDARD_C_PROPERTIES})
331endif()
332
333# Generate pkg-config file.
334include(FindPkgConfig QUIET)
335if(PKG_CONFIG_FOUND)
336    set(VK_API_VERSION "${LOADER_GENERATED_HEADER_VERSION}")
337    foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
338        set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}")
339    endforeach()
340    if(WIN32)
341        if(MINGW)
342            set(VULKAN_LIB_SUFFIX "-1.dll")
343        else()
344            set(VULKAN_LIB_SUFFIX "-1")
345        endif()
346        # Set libdir path as in cmake's FindVulkan.cmake
347        # https://github.com/KhronosGroup/Vulkan-Loader/issues/668
348        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
349            string(REPLACE "lib" "Lib" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
350        else()
351            string(REPLACE "lib" "Lib32" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
352        endif()
353    else()
354        set(CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
355    endif ()
356    configure_file("vulkan.pc.in" "vulkan.pc" @ONLY)
357    install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
358endif()
359
360target_link_libraries(vulkan PRIVATE Vulkan::Headers)
361add_library(Vulkan::Vulkan ALIAS vulkan)
362
363install(TARGETS vulkan
364        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
365        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
366        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
367