1include_directories(
2    ${CMAKE_CURRENT_SOURCE_DIR}
3    ${CMAKE_CURRENT_BINARY_DIR}
4    ${PROJECT_BINARY_DIR}
5    ${CMAKE_BINARY_DIR}
6)
7
8# Check for the existance of the secure_getenv or __secure_getenv commands
9include(CheckFunctionExists)
10CHECK_FUNCTION_EXISTS(secure_getenv HAVE_SECURE_GETENV)
11CHECK_FUNCTION_EXISTS(__secure_getenv HAVE___SECURE_GETENV)
12CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/loader_cmake_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/loader_cmake_config.h)
13
14# Fetch header version from vulkan.h
15file(STRINGS "../include/vulkan/vulkan.h" lines REGEX "^#define VK_HEADER_VERSION [0-9]+")
16list(LENGTH lines len)
17if(${len} EQUAL 1)
18    string(REGEX MATCHALL "[0-9]+" vk_header_version ${lines})
19else()
20    MESSAGE(FATAL_ERROR "Unable to fetch version from vulkan.h")
21endif()
22
23if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
24    add_definitions(-DVK_USE_PLATFORM_WIN32_KHR -DWIN32_LEAN_AND_MEAN)
25    set(DisplayServer Win32)
26    if (NOT MSVC_VERSION LESS 1900)
27        # Enable control flow guard
28        message(STATUS "Building loader with control flow guard")
29        add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/guard:cf>")
30        set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf")
31        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf")
32    endif()
33elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
34    add_definitions(-DVK_USE_PLATFORM_ANDROID_KHR)
35elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
36    if (BUILD_WSI_XCB_SUPPORT)
37        add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
38    endif()
39
40    if (BUILD_WSI_XLIB_SUPPORT)
41       add_definitions(-DVK_USE_PLATFORM_XLIB_KHR -DVK_USE_PLATFORM_XLIB_XRANDR_EXT)
42    endif()
43
44    if (BUILD_WSI_WAYLAND_SUPPORT)
45       add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
46    endif()
47
48    if (BUILD_WSI_MIR_SUPPORT)
49        add_definitions(-DVK_USE_PLATFORM_MIR_KHR)
50        include_directories(${MIR_INCLUDE_DIR})
51    endif()
52else()
53    message(FATAL_ERROR "Unsupported Platform!")
54endif()
55
56if (WIN32)
57	FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-${MAJOR}.def DEF_FILE)
58	FILE(READ ${DEF_FILE} DEF_TEXT)
59	STRING(REGEX REPLACE "vulkan-${MAJOR}.dll" "${API_LOWERCASE}-${MAJOR}.dll" DEF_EDITED "${DEF_TEXT}" )
60	FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${API_LOWERCASE}-${MAJOR}.def" "${DEF_EDITED}")
61endif()
62
63# DEBUG enables runtime loader ICD verification
64set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
65set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
66
67set(NORMAL_LOADER_SRCS
68    extension_manual.c
69    loader.c
70    loader.h
71    vk_loader_platform.h
72    vk_loader_layer.h
73    trampoline.c
74    wsi.c
75    wsi.h
76    debug_report.c
77    debug_report.h
78    gpa_helper.h
79    ../libs/cjson/includes/cJSON.h
80    ../libs/cjson/cJSON.c
81    murmurhash.c
82    murmurhash.h
83)
84
85set(OPT_LOADER_SRCS
86    dev_ext_trampoline.c
87    phys_dev_ext.c
88)
89
90# Check for assembler support
91set(ASM_FAILURE_MSG "The build will fall back on building with C code\n")
92set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG}Note that this may be unsafe, as the C code requires tail-call optimizations to remove")
93set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} the stack frame for certain calls. If the compiler does not do this, then unknown device")
94set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} extensions will suffer from a corrupted stack.")
95if (WIN32)
96    enable_language(ASM_MASM)
97    if (CMAKE_ASM_MASM_COMPILER_WORKS)
98        if (NOT CMAKE_CL_64)
99            set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh)
100        endif()
101        set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_masm.asm)
102
103        add_executable(asm_offset asm_offset.c)
104        add_dependencies(asm_offset generate_helper_files loader_gen_files)
105        add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset MASM)
106        add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
107        set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LVL_TARGET_FOLDER})
108    else()
109        message(WARNING "Could not find working MASM assebler\n${ASM_FAILURE_MSG}")
110        set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
111        add_custom_target(loader_asm_gen_files)
112    endif()
113else()
114    enable_language(ASM-ATT)
115    set(CMAKE_ASM-ATT_COMPILE_FLAGS "${CMAKE_ASM-ATT_COMPILE_FLAGS} $ENV{ASFLAGS}")
116    set(CMAKE_ASM-ATT_COMPILE_FLAGS "${CMAKE_ASM-ATT_COMPILE_FLAGS} -I\"${CMAKE_CURRENT_BINARY_DIR}\"")
117
118    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/asm_test.asm ".intel_syntax noprefix\n.text\n.global sample\nsample:\nmov ecx, [eax + 16]\n")
119    try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/asm_test.asm)
120    file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/asm_test.asm)
121    if (ASSEMBLER_WORKS)
122        set(CMAKE_ASM-ATT_FLAGS "$ENV{ASFLAGS} -I\"${CMAKE_CURRENT_BINARY_DIR}\"")
123        set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas.asm)
124        add_executable(asm_offset asm_offset.c)
125        add_dependencies(asm_offset generate_helper_files loader_gen_files)
126        add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS)
127        add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
128    else()
129        message(WARNING "Could not find working x86 GAS assembler\n${ASM_FAILURE_MSG}")
130        set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
131        add_custom_target(loader_asm_gen_files)
132    endif()
133endif()
134
135run_vk_xml_generate(loader_extension_generator.py vk_loader_extensions.h)
136run_vk_xml_generate(loader_extension_generator.py vk_loader_extensions.c)
137add_custom_target(loader_gen_files DEPENDS
138        vk_loader_extensions.h
139        vk_loader_extensions.c
140    )
141set_target_properties(loader_gen_files PROPERTIES FOLDER ${LVL_TARGET_FOLDER})
142
143if (WIN32)
144    # Use static MSVCRT libraries
145    foreach(configuration in CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO
146                             CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO)
147        if(${configuration} MATCHES "/MD")
148            string(REGEX REPLACE "/MD" "/MT" ${configuration} "${${configuration}}")
149        endif()
150    endforeach()
151
152    if (ENABLE_WIN10_ONECORE)
153    # Note  When linking your app or driver to OneCore.lib, be sure to remove any links to non-umbrella libs (such as kernel32.lib).
154        set(CMAKE_CXX_STANDARD_LIBRARIES " ") # space is intentional
155        set(CMAKE_C_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES})
156    endif()
157
158    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
159    # Build dev_ext_trampoline.c with -O2 to allow tail-call optimization.
160    # Build other C files with normal options
161    # setup two Cmake targets (loader-norm and loader-opt) for the different compilation flags
162    separate_arguments(LOCAL_C_FLAGS_DBG WINDOWS_COMMAND ${CMAKE_C_FLAGS_DEBUG})
163    set(CMAKE_C_FLAGS_DEBUG " ")
164    separate_arguments(LOCAL_C_FLAGS_REL WINDOWS_COMMAND ${CMAKE_C_FLAGS_RELEASE})
165
166    add_library(loader-norm-dy OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c)
167    add_dependencies(loader-norm-dy generate_helper_files loader_gen_files)
168    target_compile_definitions(loader-norm-dy PUBLIC LOADER_DYNAMIC_LIB)
169    target_compile_options(loader-norm-dy PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>")
170
171    add_library(loader-opt-dy OBJECT ${OPT_LOADER_SRCS})
172    add_dependencies(loader-opt-dy generate_helper_files loader_gen_files loader_asm_gen_files)
173    target_compile_definitions(loader-opt-dy PUBLIC LOADER_DYNAMIC_LIB)
174    target_compile_options(loader-opt-dy PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_REL}>")
175
176    add_library(loader-norm-st OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c)
177    add_dependencies(loader-norm-st generate_helper_files loader_gen_files)
178    target_compile_options(loader-norm-st PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>")
179
180    add_library(loader-opt-st OBJECT ${OPT_LOADER_SRCS})
181    add_dependencies(loader-opt-st generate_helper_files loader_gen_files loader_asm_gen_files)
182    target_compile_options(loader-opt-st PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_REL}>")
183
184    add_library(${API_LOWERCASE}-${MAJOR} SHARED $<TARGET_OBJECTS:loader-opt-dy> $<TARGET_OBJECTS:loader-norm-dy> ${CMAKE_CURRENT_BINARY_DIR}/${API_LOWERCASE}-${MAJOR}.def ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
185    add_library(VKstatic.${MAJOR} STATIC $<TARGET_OBJECTS:loader-opt-st> $<TARGET_OBJECTS:loader-norm-st>)
186    # Suppress conflicting libs warning for debug builds.
187    set_target_properties(${API_LOWERCASE}-${MAJOR} PROPERTIES LINK_FLAGS_DEBUG /ignore:4098)
188    set_target_properties(VKstatic.${MAJOR} PROPERTIES OUTPUT_NAME VKstatic.${MAJOR})
189
190    if (ENABLE_WIN10_ONECORE)
191        target_link_libraries(${API_LOWERCASE}-${MAJOR} OneCoreUAP.lib LIBCMT.LIB LIBCMTD.LIB LIBVCRUNTIME.LIB LIBUCRT.LIB)
192        set_target_properties(${API_LOWERCASE}-${MAJOR} PROPERTIES LINK_FLAGS   "/NODEFAULTLIB")
193    else()
194        target_link_libraries(${API_LOWERCASE}-${MAJOR} Cfgmgr32)
195    endif()
196
197    add_dependencies(${API_LOWERCASE}-${MAJOR} generate_helper_files loader_gen_files loader_asm_gen_files)
198
199    if (CMAKE_GENERATOR MATCHES "^Visual Studio.*")
200        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/${API_LOWERCASE}-${MAJOR}.dll COPY_SRC_PATH)
201        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../demos/$<CONFIGURATION>/ COPY_DST_PATH)
202        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/$<CONFIGURATION>/ COPY_DST_TEST_PATH)
203    else()
204        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${API_LOWERCASE}-${MAJOR}.dll COPY_SRC_PATH)
205        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../demos/ COPY_DST_PATH)
206        file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/ COPY_DST_TEST_PATH)
207    endif()
208    add_custom_command(TARGET ${API_LOWERCASE}-${MAJOR} POST_BUILD
209      COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_PATH})
210    add_custom_command(TARGET ${API_LOWERCASE}-${MAJOR} POST_BUILD
211      COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_TEST_PATH})
212
213else()
214    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
215
216    # Clang (and not gcc) warns about redefining a typedef with the same types, so disable that warning.
217    # Note that it will still throw an error if a typedef is redefined with a different type.
218    if (CMAKE_C_COMPILER_ID MATCHES "Clang")
219        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-typedef-redefinition")
220    endif()
221
222    add_library(${API_LOWERCASE} SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
223    add_dependencies(${API_LOWERCASE} generate_helper_files loader_gen_files loader_asm_gen_files)
224    target_compile_definitions(${API_LOWERCASE} PUBLIC -DLOADER_DYNAMIC_LIB)
225    set_target_properties(${API_LOWERCASE} PROPERTIES SOVERSION "1" VERSION "1.0.${vk_header_version}")
226    target_link_libraries(${API_LOWERCASE} -ldl -lpthread -lm)
227
228    if(INSTALL_LVL_FILES)
229        install(TARGETS ${API_LOWERCASE} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
230    endif()
231
232    # Generate pkg-config file.
233    include(FindPkgConfig QUIET)
234    if(PKG_CONFIG_FOUND)
235        set(VK_API_VERSION "1.0.${vk_header_version}")
236        foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
237            set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}")
238        endforeach()
239        configure_file("vulkan.pc.in" "vulkan.pc" @ONLY)
240        if(INSTALL_LVL_FILES)
241            install(FILES       "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc"
242                    DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
243        endif()
244    endif()
245endif()
246