summaryrefslogtreecommitdiff
path: root/CMakeLists.txt
diff options
context:
space:
mode:
Diffstat (limited to 'CMakeLists.txt')
-rw-r--r--CMakeLists.txt288
1 files changed, 218 insertions, 70 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c906c5a50..61321bf0a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,8 @@
1cmake_minimum_required(VERSION 3.7) 1cmake_minimum_required(VERSION 3.11)
2 2
3list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") 3list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
4list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") 4list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
5list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/find-modules")
5include(DownloadExternals) 6include(DownloadExternals)
6include(CMakeDependentOption) 7include(CMakeDependentOption)
7 8
@@ -10,10 +11,9 @@ project(yuzu)
10# Set bundled sdl2/qt as dependent options. 11# Set bundled sdl2/qt as dependent options.
11# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON 12# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
12option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
13CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
14 14
15option(ENABLE_QT "Enable the Qt frontend" ON) 15option(ENABLE_QT "Enable the Qt frontend" ON)
16CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) 16CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF "ENABLE_QT;MSVC" OFF)
17 17
18option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) 18option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
19 19
@@ -29,6 +29,13 @@ option(ENABLE_VULKAN "Enables Vulkan backend" ON)
29 29
30option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF) 30option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
31 31
32# Default to a Release build
33get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
34if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
35 set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
36 message(STATUS "Defaulting to a Release build")
37endif()
38
32if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit) 39if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit)
33 message(STATUS "Copying pre-commit hook") 40 message(STATUS "Copying pre-commit hook")
34 file(COPY hooks/pre-commit 41 file(COPY hooks/pre-commit
@@ -53,7 +60,6 @@ endfunction()
53if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules) 60if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules)
54 check_submodules_present() 61 check_submodules_present()
55endif() 62endif()
56
57configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc 63configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc
58 ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc 64 ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
59 COPYONLY) 65 COPYONLY)
@@ -115,63 +121,227 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
115set(CMAKE_CXX_STANDARD 17) 121set(CMAKE_CXX_STANDARD 17)
116set(CMAKE_CXX_STANDARD_REQUIRED ON) 122set(CMAKE_CXX_STANDARD_REQUIRED ON)
117 123
118# System imported libraries 124# Output binaries to bin/
119# ====================== 125set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
120
121find_package(Boost 1.66.0 QUIET)
122if (NOT Boost_FOUND)
123 message(STATUS "Boost 1.66.0 or newer not found, falling back to externals")
124 126
125 set(BOOST_ROOT "${PROJECT_SOURCE_DIR}/externals/boost") 127# System imported libraries
126 set(Boost_NO_SYSTEM_PATHS OFF) 128# If not found, download any missing through Conan
127 find_package(Boost QUIET REQUIRED) 129# =======================================================================
130set(CONAN_CMAKE_SILENT_OUTPUT TRUE)
131set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
132if (YUZU_CONAN_INSTALLED)
133 if (IS_MULTI_CONFIG)
134 include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
135 else()
136 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
137 endif()
138 list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")
139 list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
140 conan_basic_setup()
141 message(STATUS "Adding conan installed libraries to the search path")
128endif() 142endif()
129 143
130# Output binaries to bin/ 144macro(yuzu_find_packages)
131set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) 145 set(options FORCE_REQUIRED)
146 cmake_parse_arguments(FN "${options}" "" "" ${ARGN})
147
148 # Cmake has a *serious* lack of 2D array or associative array...
149 # Capitalization matters here. We need the naming to match the generated paths from Conan
150 set(REQUIRED_LIBS
151 # Cmake Pkg Prefix Version Conan Pkg
152 "Boost 1.71 boost/1.72.0"
153 "Catch2 2.11 catch2/2.11.0"
154 "fmt 6.2 fmt/6.2.0"
155 "OpenSSL 1.1 openssl/1.1.1f"
156 # can't use until https://github.com/bincrafters/community/issues/1173
157 #"libzip 1.5 libzip/1.5.2@bincrafters/stable"
158 "lz4 1.8 lz4/1.9.2"
159 "nlohmann_json 3.7 nlohmann_json/3.7.3"
160 # we need to be careful as the version check might be broken https://github.com/xiph/opus/issues/110
161 "opus 1.3 opus/1.3.1"
162 "ZLIB 1.2 zlib/1.2.11"
163 "zstd 1.4 zstd/1.4.4"
164 )
165
166 foreach(PACKAGE ${REQUIRED_LIBS})
167 string(REGEX REPLACE "[ \t\r\n]+" ";" PACKAGE_SPLIT ${PACKAGE})
168 list(GET PACKAGE_SPLIT 0 PACKAGE_PREFIX)
169 list(GET PACKAGE_SPLIT 1 PACKAGE_VERSION)
170 list(GET PACKAGE_SPLIT 2 PACKAGE_CONAN)
171 # This function is called twice, once to check if the packages exist on the system already
172 # and a second time to check if conan installed them properly. The second check passes in FORCE_REQUIRED
173 if (NOT ${PACKAGE_PREFIX}_FOUND)
174 if (FN_FORCE_REQUIRED)
175 find_package(${PACKAGE_PREFIX} ${PACKAGE_VERSION} REQUIRED)
176 else()
177 find_package(${PACKAGE_PREFIX} ${PACKAGE_VERSION})
178 endif()
179 endif()
180 if (NOT ${PACKAGE_PREFIX}_FOUND)
181 list(APPEND CONAN_REQUIRED_LIBS ${PACKAGE_CONAN})
182 else()
183 # Set a legacy findPackage.cmake style PACKAGE_LIBRARIES variable for subprojects that rely on this
184 set(${PACKAGE_PREFIX}_LIBRARIES "${PACKAGE_PREFIX}::${PACKAGE_PREFIX}")
185 endif()
186 endforeach()
187 unset(FN_FORCE_REQUIRED)
188endmacro()
132 189
133# Prefer the -pthread flag on Linux. 190# Attempt to locate any packages that are required and report the missing ones in CONAN_REQUIRED_LIBS
134set(THREADS_PREFER_PTHREAD_FLAG ON) 191yuzu_find_packages()
135find_package(Threads REQUIRED)
136 192
137if (ENABLE_SDL2) 193# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
138 if (YUZU_USE_BUNDLED_SDL2) 194if(ENABLE_QT)
139 # Detect toolchain and platform 195 # We want to load the generated conan qt config so that we get the QT_ROOT var so that we can use the official
196 # Qt5Config inside the root folder instead of the conan generated one.
197 if(EXISTS ${CMAKE_BINARY_DIR}/qtConfig.cmake)
198 include(${CMAKE_BINARY_DIR}/qtConfig.cmake)
199 list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
200 list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
201 endif()
202 # Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries
203 set(QT_PREFIX_HINT)
204 if(YUZU_USE_BUNDLED_QT)
140 if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) 205 if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
141 set(SDL2_VER "SDL2-2.0.8") 206 set(QT_VER qt-5.12.0-msvc2017_64)
142 else() 207 else()
143 message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.") 208 message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
144 endif() 209 endif()
145 210
146 if (DEFINED SDL2_VER) 211 if (DEFINED QT_VER)
147 download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX) 212 download_bundled_external("qt/" ${QT_VER} QT_PREFIX)
148 endif() 213 endif()
149 214
150 set(SDL2_FOUND YES) 215 set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
151 set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") 216 endif()
152 set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") 217 find_package(Qt5 5.9 COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
153 set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") 218 if (NOT Qt5_FOUND)
219 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable")
220 endif()
221endif()
222# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
223if(ENABLE_SDL2)
224 if(EXISTS ${CMAKE_BINARY_DIR}/sdl2Config.cmake)
225 include(${CMAKE_BINARY_DIR}/sdl2Config.cmake)
226 list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}")
227 list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}")
228 endif()
229 find_package(SDL2)
230 if (NOT SDL2_FOUND)
231 # otherwise add this to the list of libraries to install
232 list(APPEND CONAN_REQUIRED_LIBS "sdl2/2.0.12@bincrafters/stable")
233 endif()
234endif()
154 235
155 add_library(SDL2 INTERFACE) 236# Install any missing dependencies with conan install
156 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") 237if (CONAN_REQUIRED_LIBS)
157 target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") 238 message(STATUS "Packages ${CONAN_REQUIRED_LIBS} not found!")
239 # Use Conan to fetch the libraries that aren't found
240 # Download conan.cmake automatically, you can also just copy the conan.cmake file
241 if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
242 message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
243 file(DOWNLOAD "https://github.com/conan-io/cmake-conan/raw/v0.15/conan.cmake"
244 "${CMAKE_BINARY_DIR}/conan.cmake")
245 endif()
246 include(${CMAKE_BINARY_DIR}/conan.cmake)
247
248 set(CONAN_LIB_OPTIONS
249 libzip:with_openssl=False
250 libzip:enable_windows_crypto=False
251 )
252 conan_check(VERSION 1.24.0 REQUIRED)
253 # Add the bincrafters remote
254 conan_add_remote(NAME bincrafters
255 URL https://api.bintray.com/conan/bincrafters/public-conan)
256
257 # Manually add iconv to fix a dep conflict between qt and sdl2
258 # We don't need to add it through find_package or anything since the other two can find it just fine
259 if ("${CONAN_REQUIRED_LIBS}" MATCHES "qt" AND "${CONAN_REQUIRED_LIBS}" MATCHES "sdl")
260 list(APPEND CONAN_REQUIRED_LIBS "libiconv/1.16")
261 endif()
262 if (IS_MULTI_CONFIG)
263 conan_cmake_run(REQUIRES ${CONAN_REQUIRED_LIBS}
264 OPTIONS ${CONAN_LIB_OPTIONS}
265 BUILD missing
266 CONFIGURATION_TYPES "Release;Debug"
267 GENERATORS cmake_multi cmake_find_package_multi)
268 include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
158 else() 269 else()
270 conan_cmake_run(REQUIRES ${CONAN_REQUIRED_LIBS}
271 OPTIONS ${CONAN_LIB_OPTIONS}
272 BUILD missing
273 GENERATORS cmake cmake_find_package_multi)
274 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
275 endif()
276 list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")
277 list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
278 conan_basic_setup()
279
280 set(YUZU_CONAN_INSTALLED TRUE CACHE BOOL "If true, the following builds will add conan to the lib search path" FORCE)
281
282 # Now that we've installed what we are missing, try to locate them again,
283 # this time with required, so we bail if its not found.
284 yuzu_find_packages(FORCE_REQUIRED)
285
286 # Due to issues with variable scopes in functions, we need to also find_package(qt5) outside of the function
287 if(ENABLE_QT)
288 list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
289 list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
290 find_package(Qt5 5.9 REQUIRED COMPONENTS Widgets OpenGL)
291 if (YUZU_USE_QT_WEB_ENGINE)
292 find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
293 endif()
294 endif()
295 if(ENABLE_SDL2)
296 list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}")
297 list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}")
159 find_package(SDL2 REQUIRED) 298 find_package(SDL2 REQUIRED)
299 endif()
160 300
161 # Some installations don't set SDL2_LIBRARIES 301endif()
162 if("${SDL2_LIBRARIES}" STREQUAL "") 302
163 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2") 303# Reexport some targets that are named differently when using the upstream CmakeConfig vs the generated Conan config
164 set(SDL2_LIBRARIES "SDL2::SDL2") 304# In order to ALIAS targets to a new name, they first need to be IMPORTED_GLOBAL
165 endif() 305# Dynarmic checks for target `boost` and so we want to make sure it can find it through our system instead of using their external
306if (TARGET Boost::Boost)
307 set_target_properties(Boost::Boost PROPERTIES IMPORTED_GLOBAL TRUE)
308 add_library(Boost::boost ALIAS Boost::Boost)
309 add_library(boost ALIAS Boost::Boost)
310elseif (TARGET Boost::boost)
311 set_target_properties(Boost::boost PROPERTIES IMPORTED_GLOBAL TRUE)
312 add_library(boost ALIAS Boost::boost)
313endif()
314
315if (NOT TARGET OpenSSL::SSL)
316 set_target_properties(OpenSSL::OpenSSL PROPERTIES IMPORTED_GLOBAL TRUE)
317 add_library(OpenSSL::SSL ALIAS OpenSSL::OpenSSL)
318endif()
319if (NOT TARGET OpenSSL::Crypto)
320 set_target_properties(OpenSSL::OpenSSL PROPERTIES IMPORTED_GLOBAL TRUE)
321 add_library(OpenSSL::Crypto ALIAS OpenSSL::OpenSSL)
322endif()
166 323
167 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) 324if (TARGET sdl2::sdl2)
168 add_library(SDL2 INTERFACE) 325 # imported from the conan generated sdl2Config.cmake
169 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") 326 set_target_properties(sdl2::sdl2 PROPERTIES IMPORTED_GLOBAL TRUE)
327 add_library(SDL2 ALIAS sdl2::sdl2)
328elseif(SDL2_FOUND)
329 # found through the system package manager
330 # Some installations don't set SDL2_LIBRARIES
331 if("${SDL2_LIBRARIES}" STREQUAL "")
332 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
333 set(SDL2_LIBRARIES "SDL2::SDL2")
170 endif() 334 endif()
171else() 335
172 set(SDL2_FOUND NO) 336 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
337 add_library(SDL2 INTERFACE)
338 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
173endif() 339endif()
174 340
341# Prefer the -pthread flag on Linux.
342set(THREADS_PREFER_PTHREAD_FLAG ON)
343find_package(Threads REQUIRED)
344
175# If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external 345# If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external
176if (YUZU_USE_BUNDLED_UNICORN) 346if (YUZU_USE_BUNDLED_UNICORN)
177 if (MSVC) 347 if (MSVC)
@@ -212,8 +382,12 @@ if (YUZU_USE_BUNDLED_UNICORN)
212 find_package(PythonInterp 2.7 REQUIRED) 382 find_package(PythonInterp 2.7 REQUIRED)
213 383
214 if (MINGW) 384 if (MINGW)
385 # Intentionally call the unicorn makefile directly instead of using make.sh so that we can override the
386 # UNAME_S makefile variable to MINGW. This way we don't have to hack at the uname binary to build
387 # Additionally, overriding DO_WINDOWS_EXPORT prevents unicorn from patching the static unicorn.a by using msvc and cmd,
388 # which are both things we don't have in a mingw cross compiling environment.
215 add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY} 389 add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY}
216 COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" /bin/sh make.sh cross-win64 390 COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc-ar RANLIB=x86_64-w64-mingw32-gcc-ranlib make UNAME_S=MINGW DO_WINDOWS_EXPORT=0
217 WORKING_DIRECTORY ${UNICORN_PREFIX} 391 WORKING_DIRECTORY ${UNICORN_PREFIX}
218 ) 392 )
219 else() 393 else()
@@ -243,32 +417,6 @@ else()
243 message(FATAL_ERROR "Could not find or build unicorn which is required.") 417 message(FATAL_ERROR "Could not find or build unicorn which is required.")
244endif() 418endif()
245 419
246if (ENABLE_QT)
247 if (YUZU_USE_BUNDLED_QT)
248 if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
249 set(QT_VER qt-5.12.0-msvc2017_64)
250 else()
251 message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
252 endif()
253
254 if (DEFINED QT_VER)
255 download_bundled_external("qt/" ${QT_VER} QT_PREFIX)
256 endif()
257
258 set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
259 else()
260 # Passing an empty HINTS seems to cause default system paths to get ignored in CMake 2.8 so
261 # make sure to not pass anything if we don't have one.
262 set(QT_PREFIX_HINT)
263 endif()
264
265 find_package(Qt5 REQUIRED COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
266
267 if (YUZU_USE_QT_WEB_ENGINE)
268 find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets ${QT_PREFIX_HINT})
269 endif ()
270endif()
271
272# Platform-specific library requirements 420# Platform-specific library requirements
273# ====================================== 421# ======================================
274 422
@@ -299,7 +447,7 @@ find_program(CLANG_FORMAT
299 PATHS ${PROJECT_BINARY_DIR}/externals) 447 PATHS ${PROJECT_BINARY_DIR}/externals)
300# if find_program doesn't find it, try to download from externals 448# if find_program doesn't find it, try to download from externals
301if (NOT CLANG_FORMAT) 449if (NOT CLANG_FORMAT)
302 if (WIN32) 450 if (WIN32 AND NOT CMAKE_CROSSCOMPILING)
303 message(STATUS "Clang format not found! Downloading...") 451 message(STATUS "Clang format not found! Downloading...")
304 set(CLANG_FORMAT "${PROJECT_BINARY_DIR}/externals/clang-format${CLANG_FORMAT_POSTFIX}.exe") 452 set(CLANG_FORMAT "${PROJECT_BINARY_DIR}/externals/clang-format${CLANG_FORMAT_POSTFIX}.exe")
305 file(DOWNLOAD 453 file(DOWNLOAD