• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016-2021 Google Inc.
2# SPDX-License-Identifier: Apache-2.0 OR MIT
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16#
17# At your option, you may choose to accept this material under either:
18#  1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
19#  2. The MIT License, found at <http://opensource.org/licenses/MIT>.
20#
21
22cmake_minimum_required(VERSION 3.0)
23set(CMAKE_CXX_STANDARD 11)
24set(CMAKE_CXX_EXTENSIONS OFF)
25
26# Avoid a warning if parent project sets VERSION in project().
27if (${CMAKE_VERSION} VERSION_GREATER "3.0.1")
28	cmake_policy(SET CMP0048 NEW)
29endif()
30
31project(SPIRV-Cross LANGUAGES CXX C)
32enable_testing()
33
34include(GNUInstallDirs)
35
36option(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS "Instead of throwing exceptions assert" OFF)
37option(SPIRV_CROSS_SHARED "Build the C API as a single shared library." OFF)
38option(SPIRV_CROSS_STATIC "Build the C and C++ API as static libraries." ON)
39option(SPIRV_CROSS_CLI "Build the CLI binary. Requires SPIRV_CROSS_STATIC." ON)
40option(SPIRV_CROSS_ENABLE_TESTS "Enable SPIRV-Cross tests." ON)
41
42option(SPIRV_CROSS_ENABLE_GLSL "Enable GLSL support." ON)
43option(SPIRV_CROSS_ENABLE_HLSL "Enable HLSL target support." ON)
44option(SPIRV_CROSS_ENABLE_MSL "Enable MSL target support." ON)
45option(SPIRV_CROSS_ENABLE_CPP "Enable C++ target support." ON)
46option(SPIRV_CROSS_ENABLE_REFLECT "Enable JSON reflection target support." ON)
47option(SPIRV_CROSS_ENABLE_C_API "Enable C API wrapper support in static library." ON)
48option(SPIRV_CROSS_ENABLE_UTIL "Enable util module support." ON)
49
50option(SPIRV_CROSS_SANITIZE_ADDRESS "Sanitize address" OFF)
51option(SPIRV_CROSS_SANITIZE_MEMORY "Sanitize memory" OFF)
52option(SPIRV_CROSS_SANITIZE_THREADS "Sanitize threads" OFF)
53option(SPIRV_CROSS_SANITIZE_UNDEFINED "Sanitize undefined" OFF)
54
55option(SPIRV_CROSS_NAMESPACE_OVERRIDE "" "Override the namespace used in the C++ API.")
56option(SPIRV_CROSS_FORCE_STL_TYPES "Force use of STL types instead of STL replacements in certain places. Might reduce performance." OFF)
57
58option(SPIRV_CROSS_SKIP_INSTALL "Skips installation targets." OFF)
59
60option(SPIRV_CROSS_WERROR "Fail build on warnings." OFF)
61option(SPIRV_CROSS_MISC_WARNINGS "Misc warnings useful for Travis runs." OFF)
62
63option(SPIRV_CROSS_FORCE_PIC "Force position-independent code for all targets." OFF)
64
65if(${CMAKE_GENERATOR} MATCHES "Makefile")
66	if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
67		message(FATAL_ERROR "Build out of tree to avoid overwriting Makefile")
68	endif()
69endif()
70
71set(spirv-compiler-options "")
72set(spirv-compiler-defines "")
73set(spirv-cross-link-flags "")
74
75message(STATUS "SPIRV-Cross: Finding Git version for SPIRV-Cross.")
76set(spirv-cross-build-version "unknown")
77find_package(Git)
78if (GIT_FOUND)
79	execute_process(
80		COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
81		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
82		OUTPUT_VARIABLE spirv-cross-build-version
83		ERROR_QUIET
84		OUTPUT_STRIP_TRAILING_WHITESPACE
85		)
86	message(STATUS "SPIRV-Cross: Git hash: ${spirv-cross-build-version}")
87else()
88	message(STATUS "SPIRV-Cross: Git not found, using unknown build version.")
89endif()
90
91string(TIMESTAMP spirv-cross-timestamp)
92configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/gitversion.in.h ${CMAKE_CURRENT_BINARY_DIR}/gitversion.h @ONLY)
93
94if (SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
95	set(spirv-compiler-defines ${spirv-compiler-defines} SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
96	if (NOT MSVC)
97		set(spirv-compiler-options ${spirv-compiler-options} -fno-exceptions)
98	endif()
99endif()
100
101if (SPIRV_CROSS_FORCE_STL_TYPES)
102	set(spirv-compiler-defines ${spirv-compiler-defines} SPIRV_CROSS_FORCE_STL_TYPES)
103endif()
104
105if (WIN32)
106	set(CMAKE_DEBUG_POSTFIX "d")
107endif()
108
109if (CMAKE_COMPILER_IS_GNUCXX OR ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") AND NOT MSVC))
110	set(spirv-compiler-options ${spirv-compiler-options} -Wall -Wextra -Wshadow -Wno-deprecated-declarations)
111	if (SPIRV_CROSS_MISC_WARNINGS)
112		if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
113			set(spirv-compiler-options ${spirv-compiler-options} -Wshorten-64-to-32)
114		endif()
115	endif()
116	if (SPIRV_CROSS_WERROR)
117		set(spirv-compiler-options ${spirv-compiler-options} -Werror)
118	endif()
119
120	if (SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
121		set(spirv-compiler-options ${spirv-compiler-options} -fno-exceptions)
122	endif()
123
124	if (SPIRV_CROSS_SANITIZE_ADDRESS)
125		set(spirv-compiler-options ${spirv-compiler-options} -fsanitize=address)
126		set(spirv-cross-link-flags "${spirv-cross-link-flags} -fsanitize=address")
127	endif()
128
129	if (SPIRV_CROSS_SANITIZE_UNDEFINED)
130		set(spirv-compiler-options ${spirv-compiler-options} -fsanitize=undefined)
131		set(spirv-cross-link-flags "${spirv-cross-link-flags} -fsanitize=undefined")
132	endif()
133
134	if (SPIRV_CROSS_SANITIZE_MEMORY)
135		set(spirv-compiler-options ${spirv-compiler-options} -fsanitize=memory)
136		set(spirv-cross-link-flags "${spirv-cross-link-flags} -fsanitize=memory")
137	endif()
138
139	if (SPIRV_CROSS_SANITIZE_THREADS)
140		set(spirv-compiler-options ${spirv-compiler-options} -fsanitize=thread)
141		set(spirv-cross-link-flags "${spirv-cross-link-flags} -fsanitize=thread")
142	endif()
143elseif (MSVC)
144	# AppVeyor spuriously fails in debug build on older MSVC without /bigobj.
145	set(spirv-compiler-options ${spirv-compiler-options} /wd4267 /wd4996 $<$<CONFIG:DEBUG>:/bigobj>)
146endif()
147
148macro(extract_headers out_abs file_list)
149	set(${out_abs}) # absolute paths
150	foreach(_a ${file_list})
151		# get_filename_component only returns the longest extension, so use a regex
152		string(REGEX REPLACE ".*\\.(h|hpp)" "\\1" ext ${_a})
153
154		# For shared library, we are only interested in the C header.
155		if (SPIRV_CROSS_STATIC)
156			if(("${ext}" STREQUAL "h") OR ("${ext}" STREQUAL "hpp"))
157				list(APPEND ${out_abs} "${_a}")
158			endif()
159		else()
160			if("${ext}" STREQUAL "h")
161				list(APPEND ${out_abs} "${_a}")
162			endif()
163		endif()
164	endforeach()
165endmacro()
166
167macro(spirv_cross_add_library name config_name library_type)
168	add_library(${name} ${library_type} ${ARGN})
169	extract_headers(hdrs "${ARGN}")
170	target_include_directories(${name} PUBLIC
171			$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
172			$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/spirv_cross>)
173	set_target_properties(${name} PROPERTIES
174			PUBLIC_HEADERS "${hdrs}")
175	if (SPIRV_CROSS_FORCE_PIC)
176		set_target_properties(${name} PROPERTIES POSITION_INDEPENDENT_CODE ON)
177	endif()
178	target_compile_options(${name} PRIVATE ${spirv-compiler-options})
179	target_compile_definitions(${name} PRIVATE ${spirv-compiler-defines})
180	if (SPIRV_CROSS_NAMESPACE_OVERRIDE)
181		if (${library_type} MATCHES "STATIC")
182			target_compile_definitions(${name} PUBLIC SPIRV_CROSS_NAMESPACE_OVERRIDE=${SPIRV_CROSS_NAMESPACE_OVERRIDE})
183		else()
184			target_compile_definitions(${name} PRIVATE SPIRV_CROSS_NAMESPACE_OVERRIDE=${SPIRV_CROSS_NAMESPACE_OVERRIDE})
185		endif()
186	endif()
187
188	if (NOT SPIRV_CROSS_SKIP_INSTALL)
189		install(TARGETS ${name}
190			EXPORT ${config_name}Config
191			RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
192			LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
193			ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
194			PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/spirv_cross)
195		install(FILES ${hdrs} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/spirv_cross)
196		install(EXPORT ${config_name}Config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${config_name}/cmake)
197		export(TARGETS ${name} FILE ${config_name}Config.cmake)
198	endif()
199endmacro()
200
201set(spirv-cross-core-sources
202		${CMAKE_CURRENT_SOURCE_DIR}/GLSL.std.450.h
203		${CMAKE_CURRENT_SOURCE_DIR}/spirv_common.hpp
204		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_containers.hpp
205		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_error_handling.hpp
206		${CMAKE_CURRENT_SOURCE_DIR}/spirv.hpp
207		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.hpp
208		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross.cpp
209		${CMAKE_CURRENT_SOURCE_DIR}/spirv_parser.hpp
210		${CMAKE_CURRENT_SOURCE_DIR}/spirv_parser.cpp
211		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_parsed_ir.hpp
212		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_parsed_ir.cpp
213		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cfg.hpp
214		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cfg.cpp)
215
216set(spirv-cross-c-sources
217		spirv.h
218		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_c.cpp
219		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_c.h)
220
221set(spirv-cross-glsl-sources
222		${CMAKE_CURRENT_SOURCE_DIR}/spirv_glsl.cpp
223		${CMAKE_CURRENT_SOURCE_DIR}/spirv_glsl.hpp)
224
225set(spirv-cross-cpp-sources
226		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp
227		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp)
228
229set(spirv-cross-msl-sources
230		${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp
231		${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp)
232
233set(spirv-cross-hlsl-sources
234		${CMAKE_CURRENT_SOURCE_DIR}/spirv_hlsl.cpp
235		${CMAKE_CURRENT_SOURCE_DIR}/spirv_hlsl.hpp)
236
237set(spirv-cross-reflect-sources
238		${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.cpp
239		${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.hpp)
240
241set(spirv-cross-util-sources
242		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_util.cpp
243		${CMAKE_CURRENT_SOURCE_DIR}/spirv_cross_util.hpp)
244
245if (SPIRV_CROSS_STATIC)
246	spirv_cross_add_library(spirv-cross-core spirv_cross_core STATIC
247			${spirv-cross-core-sources})
248
249	if (SPIRV_CROSS_ENABLE_GLSL)
250		spirv_cross_add_library(spirv-cross-glsl spirv_cross_glsl STATIC
251				${spirv-cross-glsl-sources})
252		target_link_libraries(spirv-cross-glsl PRIVATE spirv-cross-core)
253	endif()
254
255	if (SPIRV_CROSS_ENABLE_CPP)
256		spirv_cross_add_library(spirv-cross-cpp spirv_cross_cpp STATIC
257				${spirv-cross-cpp-sources})
258
259		if (SPIRV_CROSS_ENABLE_GLSL)
260			target_link_libraries(spirv-cross-cpp PRIVATE spirv-cross-glsl)
261		else()
262			message(FATAL_ERROR "Must enable GLSL support to enable C++ support.")
263		endif()
264	endif()
265
266	if (SPIRV_CROSS_ENABLE_REFLECT)
267		if (SPIRV_CROSS_ENABLE_GLSL)
268			spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC
269					${spirv-cross-reflect-sources})
270		else()
271			message(FATAL_ERROR "Must enable GLSL support to enable JSON reflection support.")
272		endif()
273	endif()
274
275	if (SPIRV_CROSS_ENABLE_MSL)
276		spirv_cross_add_library(spirv-cross-msl spirv_cross_msl STATIC
277				${spirv-cross-msl-sources})
278		if (SPIRV_CROSS_ENABLE_GLSL)
279			target_link_libraries(spirv-cross-msl PRIVATE spirv-cross-glsl)
280		else()
281			message(FATAL_ERROR "Must enable GLSL support to enable MSL support.")
282		endif()
283	endif()
284
285	if (SPIRV_CROSS_ENABLE_HLSL)
286		spirv_cross_add_library(spirv-cross-hlsl spirv_cross_hlsl STATIC
287				${spirv-cross-hlsl-sources})
288		if (SPIRV_CROSS_ENABLE_GLSL)
289			target_link_libraries(spirv-cross-hlsl PRIVATE spirv-cross-glsl)
290		else()
291			message(FATAL_ERROR "Must enable GLSL support to enable HLSL support.")
292		endif()
293	endif()
294
295	if (SPIRV_CROSS_ENABLE_UTIL)
296		spirv_cross_add_library(spirv-cross-util spirv_cross_util STATIC
297				${spirv-cross-util-sources})
298		target_link_libraries(spirv-cross-util PRIVATE spirv-cross-core)
299	endif()
300
301	if (SPIRV_CROSS_ENABLE_C_API)
302		spirv_cross_add_library(spirv-cross-c spirv_cross_c STATIC
303				${spirv-cross-c-sources})
304		target_include_directories(spirv-cross-c PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
305		target_compile_definitions(spirv-cross-c PRIVATE HAVE_SPIRV_CROSS_GIT_VERSION)
306
307		if (SPIRV_CROSS_ENABLE_GLSL)
308			target_link_libraries(spirv-cross-c PRIVATE spirv-cross-glsl)
309			target_compile_definitions(spirv-cross-c PRIVATE SPIRV_CROSS_C_API_GLSL=1)
310		endif()
311
312		if (SPIRV_CROSS_ENABLE_HLSL)
313			target_link_libraries(spirv-cross-c PRIVATE spirv-cross-hlsl)
314			target_compile_definitions(spirv-cross-c PRIVATE SPIRV_CROSS_C_API_HLSL=1)
315		endif()
316
317		if (SPIRV_CROSS_ENABLE_MSL)
318			target_link_libraries(spirv-cross-c PRIVATE spirv-cross-msl)
319			target_compile_definitions(spirv-cross-c PRIVATE SPIRV_CROSS_C_API_MSL=1)
320		endif()
321
322		if (SPIRV_CROSS_ENABLE_CPP)
323			target_link_libraries(spirv-cross-c PRIVATE spirv-cross-cpp)
324			target_compile_definitions(spirv-cross-c PRIVATE SPIRV_CROSS_C_API_CPP=1)
325		endif()
326
327		if (SPIRV_CROSS_ENABLE_REFLECT)
328			target_link_libraries(spirv-cross-c PRIVATE spirv-cross-reflect)
329			target_compile_definitions(spirv-cross-c PRIVATE SPIRV_CROSS_C_API_REFLECT=1)
330		endif()
331	endif()
332endif()
333
334set(spirv-cross-abi-major 0)
335set(spirv-cross-abi-minor 48)
336set(spirv-cross-abi-patch 0)
337
338if (SPIRV_CROSS_SHARED)
339	set(SPIRV_CROSS_VERSION ${spirv-cross-abi-major}.${spirv-cross-abi-minor}.${spirv-cross-abi-patch})
340
341	if (NOT SPIRV_CROSS_SKIP_INSTALL)
342		configure_file(
343			${CMAKE_CURRENT_SOURCE_DIR}/pkg-config/spirv-cross-c-shared.pc.in
344			${CMAKE_CURRENT_BINARY_DIR}/spirv-cross-c-shared.pc @ONLY)
345		install(FILES ${CMAKE_CURRENT_BINARY_DIR}/spirv-cross-c-shared.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
346	endif()
347
348	spirv_cross_add_library(spirv-cross-c-shared spirv_cross_c_shared SHARED
349			${spirv-cross-core-sources}
350			${spirv-cross-c-sources})
351
352	target_include_directories(spirv-cross-c-shared PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
353	target_compile_definitions(spirv-cross-c-shared PRIVATE HAVE_SPIRV_CROSS_GIT_VERSION)
354
355	if (SPIRV_CROSS_ENABLE_GLSL)
356		target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-glsl-sources})
357		target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_GLSL=1)
358	endif()
359
360	if (SPIRV_CROSS_ENABLE_HLSL)
361		if (SPIRV_CROSS_ENABLE_GLSL)
362			target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-hlsl-sources})
363		else()
364			message(FATAL_ERROR "Must enable GLSL support to enable HLSL support.")
365		endif()
366		target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_HLSL=1)
367	endif()
368
369	if (SPIRV_CROSS_ENABLE_MSL)
370		if (SPIRV_CROSS_ENABLE_GLSL)
371			target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-msl-sources})
372		else()
373			message(FATAL_ERROR "Must enable GLSL support to enable MSL support.")
374		endif()
375		target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_MSL=1)
376	endif()
377
378	if (SPIRV_CROSS_ENABLE_CPP)
379		if (SPIRV_CROSS_ENABLE_GLSL)
380			target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-cpp-sources})
381		else()
382			message(FATAL_ERROR "Must enable GLSL support to enable C++ support.")
383		endif()
384		target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_CPP=1)
385	endif()
386
387	if (SPIRV_CROSS_ENABLE_REFLECT)
388		if (SPIRV_CROSS_ENABLE_GLSL)
389			target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-reflect-sources})
390		else()
391			message(FATAL_ERROR "Must enable GLSL support to enable JSON reflection support.")
392		endif()
393		target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_REFLECT=1)
394	endif()
395
396	if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
397		# Only export the C API.
398		target_compile_options(spirv-cross-c-shared PRIVATE -fvisibility=hidden)
399		if (NOT APPLE)
400			set_target_properties(spirv-cross-c-shared PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
401		endif()
402	endif()
403
404	target_compile_definitions(spirv-cross-c-shared PRIVATE SPVC_EXPORT_SYMBOLS)
405
406	set_target_properties(spirv-cross-c-shared PROPERTIES
407			VERSION ${SPIRV_CROSS_VERSION}
408			SOVERSION ${spirv-cross-abi-major})
409endif()
410
411if (SPIRV_CROSS_CLI)
412	if (NOT SPIRV_CROSS_ENABLE_GLSL)
413		message(FATAL_ERROR "Must enable GLSL if building CLI.")
414	endif()
415
416	if (NOT SPIRV_CROSS_ENABLE_HLSL)
417		message(FATAL_ERROR "Must enable HLSL if building CLI.")
418	endif()
419
420	if (NOT SPIRV_CROSS_ENABLE_MSL)
421		message(FATAL_ERROR "Must enable MSL if building CLI.")
422	endif()
423
424	if (NOT SPIRV_CROSS_ENABLE_CPP)
425		message(FATAL_ERROR "Must enable C++ if building CLI.")
426	endif()
427
428	if (NOT SPIRV_CROSS_ENABLE_REFLECT)
429		message(FATAL_ERROR "Must enable reflection if building CLI.")
430	endif()
431
432	if (NOT SPIRV_CROSS_ENABLE_UTIL)
433		message(FATAL_ERROR "Must enable utils if building CLI.")
434	endif()
435
436	if (NOT SPIRV_CROSS_STATIC)
437		message(FATAL_ERROR "Must build static libraries if building CLI.")
438	endif()
439	add_executable(spirv-cross main.cpp)
440	target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options})
441	target_include_directories(spirv-cross PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
442	target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines} HAVE_SPIRV_CROSS_GIT_VERSION)
443	set_target_properties(spirv-cross PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
444	if (NOT SPIRV_CROSS_SKIP_INSTALL)
445		install(TARGETS spirv-cross DESTINATION ${CMAKE_INSTALL_BINDIR})
446	endif()
447	target_link_libraries(spirv-cross PRIVATE
448			spirv-cross-glsl
449			spirv-cross-hlsl
450			spirv-cross-cpp
451			spirv-cross-reflect
452			spirv-cross-msl
453			spirv-cross-util
454			spirv-cross-core)
455
456	if (SPIRV_CROSS_ENABLE_TESTS)
457		# Set up tests, using only the simplest modes of the test_shaders
458		# script.  You have to invoke the script manually to:
459		#  - Update the reference files
460		#  - Get cycle counts from malisc
461		#  - Keep failing outputs
462		find_package(PythonInterp)
463		find_program(spirv-cross-glslang NAMES glslangValidator
464				PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external/glslang-build/output/bin
465				NO_DEFAULT_PATH)
466		find_program(spirv-cross-spirv-as NAMES spirv-as
467				PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external/spirv-tools-build/output/bin
468				NO_DEFAULT_PATH)
469		find_program(spirv-cross-spirv-val NAMES spirv-val
470				PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external/spirv-tools-build/output/bin
471				NO_DEFAULT_PATH)
472		find_program(spirv-cross-spirv-opt NAMES spirv-opt
473				PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external/spirv-tools-build/output/bin
474				NO_DEFAULT_PATH)
475
476		if ((${spirv-cross-glslang} MATCHES "NOTFOUND") OR (${spirv-cross-spirv-as} MATCHES "NOTFOUND") OR (${spirv-cross-spirv-val} MATCHES "NOTFOUND") OR (${spirv-cross-spirv-opt} MATCHES "NOTFOUND"))
477			set(SPIRV_CROSS_ENABLE_TESTS OFF)
478			message("SPIRV-Cross:  Testing will be disabled for SPIRV-Cross. Could not find glslang or SPIRV-Tools build under external/. To enable testing, run ./checkout_glslang_spirv_tools.sh and ./build_glslang_spirv_tools.sh first.")
479		else()
480			set(SPIRV_CROSS_ENABLE_TESTS ON)
481			message("SPIRV-Cross: Found glslang and SPIRV-Tools. Enabling test suite.")
482			message("SPIRV-Cross: Found glslangValidator in: ${spirv-cross-glslang}.")
483			message("SPIRV-Cross: Found spirv-as in: ${spirv-cross-spirv-as}.")
484			message("SPIRV-Cross: Found spirv-val in: ${spirv-cross-spirv-val}.")
485			message("SPIRV-Cross: Found spirv-opt in: ${spirv-cross-spirv-opt}.")
486		endif()
487
488		set(spirv-cross-externals
489				--glslang "${spirv-cross-glslang}"
490				--spirv-as "${spirv-cross-spirv-as}"
491				--spirv-opt "${spirv-cross-spirv-opt}"
492				--spirv-val "${spirv-cross-spirv-val}")
493
494		if (${PYTHONINTERP_FOUND} AND SPIRV_CROSS_ENABLE_TESTS)
495			if (${PYTHON_VERSION_MAJOR} GREATER 2)
496				add_executable(spirv-cross-c-api-test tests-other/c_api_test.c)
497				target_link_libraries(spirv-cross-c-api-test spirv-cross-c)
498				set_target_properties(spirv-cross-c-api-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
499
500				add_executable(spirv-cross-small-vector-test tests-other/small_vector.cpp)
501				target_link_libraries(spirv-cross-small-vector-test spirv-cross-core)
502				set_target_properties(spirv-cross-small-vector-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
503
504				add_executable(spirv-cross-msl-constexpr-test tests-other/msl_constexpr_test.cpp)
505				target_link_libraries(spirv-cross-msl-constexpr-test spirv-cross-c)
506				set_target_properties(spirv-cross-msl-constexpr-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
507
508				add_executable(spirv-cross-msl-resource-binding-test tests-other/msl_resource_bindings.cpp)
509				target_link_libraries(spirv-cross-msl-resource-binding-test spirv-cross-c)
510				set_target_properties(spirv-cross-msl-resource-binding-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
511
512				add_executable(spirv-cross-hlsl-resource-binding-test tests-other/hlsl_resource_bindings.cpp)
513				target_link_libraries(spirv-cross-hlsl-resource-binding-test spirv-cross-c)
514				set_target_properties(spirv-cross-hlsl-resource-binding-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
515
516				add_executable(spirv-cross-msl-ycbcr-conversion-test tests-other/msl_ycbcr_conversion_test.cpp)
517				target_link_libraries(spirv-cross-msl-ycbcr-conversion-test spirv-cross-c)
518				set_target_properties(spirv-cross-msl-ycbcr-conversion-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
519
520				add_executable(spirv-cross-typed-id-test tests-other/typed_id_test.cpp)
521				target_link_libraries(spirv-cross-typed-id-test spirv-cross-core)
522				set_target_properties(spirv-cross-typed-id-test PROPERTIES LINK_FLAGS "${spirv-cross-link-flags}")
523
524				if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
525					target_compile_options(spirv-cross-c-api-test PRIVATE -std=c89 -Wall -Wextra)
526				endif()
527				add_test(NAME spirv-cross-c-api-test
528						COMMAND $<TARGET_FILE:spirv-cross-c-api-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/c_api_test.spv
529						${spirv-cross-abi-major}
530						${spirv-cross-abi-minor}
531						${spirv-cross-abi-patch})
532				add_test(NAME spirv-cross-small-vector-test
533						COMMAND $<TARGET_FILE:spirv-cross-small-vector-test>)
534				add_test(NAME spirv-cross-msl-constexpr-test
535						COMMAND $<TARGET_FILE:spirv-cross-msl-constexpr-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/msl_constexpr_test.spv)
536				add_test(NAME spirv-cross-msl-resource-binding-test
537						COMMAND $<TARGET_FILE:spirv-cross-msl-resource-binding-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/msl_resource_binding.spv)
538				add_test(NAME spirv-cross-hlsl-resource-binding-test
539						COMMAND $<TARGET_FILE:spirv-cross-hlsl-resource-binding-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/hlsl_resource_binding.spv)
540				add_test(NAME spirv-cross-msl-ycbcr-conversion-test
541						COMMAND $<TARGET_FILE:spirv-cross-msl-ycbcr-conversion-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/msl_ycbcr_conversion_test.spv)
542				add_test(NAME spirv-cross-msl-ycbcr-conversion-test-2
543						COMMAND $<TARGET_FILE:spirv-cross-msl-ycbcr-conversion-test> ${CMAKE_CURRENT_SOURCE_DIR}/tests-other/msl_ycbcr_conversion_test_2.spv)
544				add_test(NAME spirv-cross-typed-id-test
545						COMMAND $<TARGET_FILE:spirv-cross-typed-id-test>)
546				add_test(NAME spirv-cross-test
547						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --parallel
548						${spirv-cross-externals}
549						${CMAKE_CURRENT_SOURCE_DIR}/shaders
550						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
551				add_test(NAME spirv-cross-test-no-opt
552						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --parallel
553						${spirv-cross-externals}
554						${CMAKE_CURRENT_SOURCE_DIR}/shaders-no-opt
555						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
556				add_test(NAME spirv-cross-test-metal
557						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal --parallel
558						${spirv-cross-externals}
559						${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl
560						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
561				add_test(NAME spirv-cross-test-metal-no-opt
562						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal --parallel
563						${spirv-cross-externals}
564						${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl-no-opt
565						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
566				add_test(NAME spirv-cross-test-hlsl
567						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --hlsl --parallel
568						${spirv-cross-externals}
569						${CMAKE_CURRENT_SOURCE_DIR}/shaders-hlsl
570						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
571				add_test(NAME spirv-cross-test-hlsl-no-opt
572						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --hlsl --parallel
573						${spirv-cross-externals}
574						${CMAKE_CURRENT_SOURCE_DIR}/shaders-hlsl-no-opt
575						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
576				add_test(NAME spirv-cross-test-opt
577						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --opt --parallel
578						${spirv-cross-externals}
579						${CMAKE_CURRENT_SOURCE_DIR}/shaders
580						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
581				add_test(NAME spirv-cross-test-metal-opt
582						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal --opt --parallel
583						${spirv-cross-externals}
584						${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl
585						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
586				add_test(NAME spirv-cross-test-hlsl-opt
587						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --hlsl --opt --parallel
588						${spirv-cross-externals}
589						${CMAKE_CURRENT_SOURCE_DIR}/shaders-hlsl
590						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
591				add_test(NAME spirv-cross-test-reflection
592						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --reflect --parallel
593						${spirv-cross-externals}
594						${CMAKE_CURRENT_SOURCE_DIR}/shaders-reflection
595						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
596				add_test(NAME spirv-cross-test-ue4
597						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --msl --parallel
598						${spirv-cross-externals}
599						${CMAKE_CURRENT_SOURCE_DIR}/shaders-ue4
600						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
601				add_test(NAME spirv-cross-test-ue4-opt
602						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --msl --opt --parallel
603						${spirv-cross-externals}
604						${CMAKE_CURRENT_SOURCE_DIR}/shaders-ue4
605						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
606				add_test(NAME spirv-cross-test-ue4-no-opt
607						COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --msl --parallel
608						${spirv-cross-externals}
609						${CMAKE_CURRENT_SOURCE_DIR}/shaders-ue4-no-opt
610						WORKING_DIRECTORY $<TARGET_FILE_DIR:spirv-cross>)
611			endif()
612		elseif(NOT ${PYTHONINTERP_FOUND})
613			message(WARNING "SPIRV-Cross: Testing disabled. Could not find python3. If you have python3 installed try running "
614					"cmake with -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python3 to help it find the executable")
615		endif()
616	endif()
617endif()
618