summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-12-08 19:24:34 +0800
committerGitHub <noreply@github.com>2023-12-08 19:24:34 +0800
commit4321929879c1ed5b87ff95a99ca7da91e28d18fd (patch)
treeae1460dcb652981468e6fa4897e87b697f2bda33 /cmake
parent9903688ccc0793259d43f95cae88bd1a8e178824 (diff)
WIP: CMake (#3326)
* More robust input and output selection in generator tools * Add cmake build system * Get slang-test running with cmake * Bump lz4 and miniz dependencies * Make cmake build more declarative * Correct preprocessor logic in slang.h * Add cuda test to compute/simple * Remove empty cmake files * output placement for cmake, and commenting * Correct include paths in spirv-embed-generator * Format cmake with gersemi * Make cmake build clerer * Neaten header generation Also work around https://gitlab.kitware.com/cmake/cmake/-/issues/18399 by introducing correct_generated_properties to set the GENERATED flag in the correct scope * remove unused files * use 3.20 to set GENERATOR property properly * spelling * more flexible linker arg setting * replace slang-static with obj collection * Set rpath and linker path correctly * neaten generated file generation * tests working with cmake build * fix premake5 build * comment and neaten cmake * remove unnecessary dependency * Build aftermath example only when aftermath is enabled * Add slang-llvm and other dependencies * Put modules alongside binaries * Find slang-glslang correctly * Better option handling * comments * add llvm build test * Better option handling * cmake wobble * use UNICODE and _UNICODE * remove other workflows * use ccache * neaten * limit parallel for llvm build * use ninja for build * Windows and Darwin slang-llvm builds * cache key * verbose llvm build * cl on windows * sccache and cl.exe * use cl.exe * Correct package detection * less verbosity * Simplify miniz inclusion * fix build with sccache * Neaten llvm building * neaten * Neaten slang-llvm fetching * more surgical workarounds * Add ci action * Get version from git * better variable naming * add missing include * clean up after premake in cmake * more docs on cmake build * ci wobble * add imgui target * more selective source * do not download swiftshader * Some missing dependencies * only build llvm on dispatch * Disable /Zi in CI where sccache is present * simplify * set PIC for miniz * set policies before project * reengage workaround * more runs on ci * Add cmake presets * Add cpack * move iterator debug level to preset * Correct lib flag * simplify action * Neaten cmake init * Add todo * Add simple test wrapper * Add tests to workflow presets * rename packing preset * Correctly set definitions * docs * correct preset names * Make slang-test depend on test-server/test-process * neaten * use workflow in actions * install docs * Correct module install dir * debug dist workflow * Install headers * neaten header globbing * Neaten dependency handling * make lib and bin variables * Do not set compiler for vs builds, unnecessary * docs * allow setting explicit source for target * maintain archive subdir * cmake docs * install headers * place targets into folders * cmake docs * nest external projects in folder * remove name clash * Neater external packages * meta targets in folder structure * cleaner slang-glslang dll * Add missing static directive to slang-no-embedded-stdlib * more robust module copying * make slang-test the startup project * folder tweak * Make FETCH_BINARY the default on all platforms * Set DEBUG_DIR * add natvis files to source * skip spirv tests * remove test step from debug dist * Add build to .gitignore * redo warnings to be more like premake * Update imgui * clean more premake files * Disable PCH for glslang, gcc throws a warning * Add /MP for msvc builds * warning wobble * Add script to build llvm * Add slang-llvm and generators components * Build slang-llvm in ci * comments * fetch llvm with git * better abi approximation for cache * better sccache key * formatting * Correct logic around disabling problematic debug info for ccache * exclude gcc and clang from windows ci * Make dist workflows use system llvm * naming * restore normal dist builds * formatting * run tests in ci * Correct slang-llvm url setting * Rely on the system to find the test tool library * actions matrix wiggle * cope with OSX ancient bash * Correct compilers on windows * more ci debugging * Correct rpath handling on OSX * neaten * correct path to slang-llvm * Correct rpath separator on osx * Find slang-llvm correctly * smoke tests only on osx * ci wobble * Give MacOS module a dylib suffix * get swiftshader correctly * cope with bsd cp * remove debug output * full tests on osx * ci wobble * Add some vk tests to expected failures * simplify ci * ci wobble * exclude dx12 tests from github ci * remove cmake code for building llvm * warnings * warnings as errors for cl * spirv-tools in path * add aarch64 ci build * Add SLANG_GENERATORS_PATH option for prebuilt generators * neaten * Correct generator target name * remove yaml anchors because github actions does not support them * Demote CMake in docs Also add info on cross compiling * Restore premake CI * use minimal ci for cmake * Write miniz_export for premake build and .gitignore it * Mention build config tool options in docs * Remove redefined macro for miniz * regenerate vs project
Diffstat (limited to 'cmake')
-rw-r--r--cmake/AutoOption.cmake44
-rw-r--r--cmake/CCacheDebugInfoWorkaround.cmake23
-rw-r--r--cmake/CompilerFlags.cmake217
-rw-r--r--cmake/FindAftermath.cmake26
-rw-r--r--cmake/FindNVAPI.cmake34
-rw-r--r--cmake/FindOptiX.cmake15
-rw-r--r--cmake/GitVersion.cmake50
-rw-r--r--cmake/Glob.cmake51
-rw-r--r--cmake/LLVM.cmake40
-rw-r--r--cmake/SlangTarget.cmake377
10 files changed, 877 insertions, 0 deletions
diff --git a/cmake/AutoOption.cmake b/cmake/AutoOption.cmake
new file mode 100644
index 000000000..3f7cdee0e
--- /dev/null
+++ b/cmake/AutoOption.cmake
@@ -0,0 +1,44 @@
+function(auto_option name package description)
+ set(${name} "AUTO" CACHE STRING ${description})
+ set_property(CACHE ${name} PROPERTY STRINGS AUTO ON OFF)
+
+ if(${${name}} OR ${${name}} STREQUAL "AUTO")
+ if(${${name}} STREQUAL "AUTO")
+ set(req)
+ else()
+ set(req REQUIRED)
+ endif()
+ find_package(${package} ${req})
+
+ if(${${package}_FOUND})
+ set(${name} TRUE CACHE STRING ${description} FORCE)
+ else()
+ set(${name} FALSE CACHE STRING ${description} FORCE)
+ endif()
+ endif()
+endfunction()
+
+function(enum_option name init description)
+ set(enums)
+ set(is_enum TRUE)
+ foreach(enum_or_desc ${ARGN})
+ if(is_enum)
+ list(APPEND enums ${enum_or_desc})
+ string(APPEND description "\n" "${enum_or_desc}" ": ")
+ set(is_enum FALSE)
+ else()
+ string(APPEND description "${enum_or_desc}")
+ set(is_enum TRUE)
+ endif()
+ endforeach()
+
+ set(${name} ${init} CACHE STRING ${description})
+ set_property(CACHE ${name} PROPERTY STRINGS ${enums})
+
+ foreach(enum ${enums})
+ if(${${name}} STREQUAL ${enum})
+ return()
+ endif()
+ endforeach()
+ message(FATAL_ERROR "${name} must be one of ${enums}")
+endfunction()
diff --git a/cmake/CCacheDebugInfoWorkaround.cmake b/cmake/CCacheDebugInfoWorkaround.cmake
new file mode 100644
index 000000000..82fb299e3
--- /dev/null
+++ b/cmake/CCacheDebugInfoWorkaround.cmake
@@ -0,0 +1,23 @@
+# Make sure that shared debug info doesn't intefere with caching
+# See the sccache readme
+if(
+ MSVC
+ AND (NOT DEFINED CMAKE_MSVC_DEBUG_INFORMATION_FORMAT)
+ AND (
+ CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache"
+ OR CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache"
+ )
+)
+ message(
+ NOTICE
+ "Setting embedded debug info for MSVC to work around (s)ccache's inability to cache shared debug info files, Note that this requires CMake 3.25 or greater"
+ )
+ cmake_minimum_required(VERSION 3.25)
+ cmake_policy(GET CMP0141 cmp0141)
+ if(NOT cmp0141 STREQUAL "NEW")
+ message(WARNING "Need CMake policy 0141 enabled")
+ endif()
+ set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
+ "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>"
+ )
+endif()
diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake
new file mode 100644
index 000000000..2a9988d4e
--- /dev/null
+++ b/cmake/CompilerFlags.cmake
@@ -0,0 +1,217 @@
+#
+# Given a list of flags, add those which the C++ compiler supports to the target
+#
+include(CheckCXXCompilerFlag)
+function(add_supported_cxx_flags target)
+ cmake_parse_arguments(ARG "PRIVATE;PUBLIC;INTERFACE" "" "" ${ARGN})
+ set(flags ${ARG_UNPARSED_ARGUMENTS})
+ if(ARG_PRIVATE)
+ set(private PRIVATE)
+ endif()
+ if(ARG_PUBLIC)
+ set(public PUBLIC)
+ endif()
+ if(ARG_INTERFACE)
+ set(interface INTERFACE)
+ endif()
+
+ foreach(flag ${flags})
+ # remove the `no-` prefix from warnings because gcc doesn't treat it as an
+ # error on its own
+ string(REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
+ string(
+ REGEX REPLACE
+ "[^a-zA-Z0-9]+"
+ "_"
+ test_name
+ "CXXFLAG_${flag_to_test}"
+ )
+ check_cxx_compiler_flag("${flag_to_test}" ${test_name})
+ if(${test_name})
+ target_compile_options(
+ ${target}
+ ${private}
+ ${public}
+ ${interface}
+ ${flag}
+ )
+ endif()
+ endforeach()
+endfunction()
+
+#
+# Given a list of linker flags, add those which the compiler supports to the
+# target
+#
+include(CheckLinkerFlag)
+function(add_supported_cxx_linker_flags target)
+ cmake_parse_arguments(ARG "PRIVATE;PUBLIC;INTERFACE;BEFORE" "" "" ${ARGN})
+ set(flags ${ARG_UNPARSED_ARGUMENTS})
+ if(ARG_BEFORE)
+ set(before BEFORE)
+ endif()
+ if(ARG_PRIVATE)
+ set(private PRIVATE)
+ endif()
+ if(ARG_PUBLIC)
+ set(public PUBLIC)
+ endif()
+ if(ARG_INTERFACE)
+ set(interface INTERFACE)
+ endif()
+
+ foreach(flag ${flags})
+ string(
+ REGEX REPLACE
+ "[^a-zA-Z0-9]+"
+ "_"
+ test_name
+ "CXXLINKFLAG_${flag}"
+ )
+ check_linker_flag(CXX "${flag}" ${test_name})
+ if(${test_name})
+ target_link_options(
+ ${target}
+ ${before}
+ ${private}
+ ${public}
+ ${interface}
+ ${flag}
+ )
+ endif()
+ endforeach()
+endfunction()
+
+#
+# Add our default compiler flags to a target
+#
+# Pass USE_EXTRA_WARNINGS to enable -WExtra or /W3
+#
+function(set_default_compile_options target)
+ cmake_parse_arguments(
+ ARG
+ "USE_EXTRA_WARNINGS;USE_FEWER_WARNINGS"
+ ""
+ ""
+ ${ARGN}
+ )
+
+ set(warning_flags)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+ list(
+ APPEND
+ warning_flags
+ -Wall
+ # Disabled warnings:
+ -Wno-switch
+ -Wno-parentheses
+ -Wno-unused-local-typedefs
+ -Wno-class-memaccess
+ -Wno-assume
+ -Wno-reorder
+ -Wno-invalid-offsetof
+ -Wno-newline-eof
+ -Wno-return-std-move
+ # Enabled warnings:
+ # If a function returns an address/reference to a local, we want it to
+ # produce an error, because it probably means something very bad.
+ -Werror=return-local-addr
+ # Some warnings which are on by default in MSVC
+ -Wnarrowing
+ )
+ if(ARG_USE_EXTRA_WARNINGS)
+ list(APPEND warning_flags -Wextra)
+ endif()
+ if(ARG_USE_FEWER_WARNINGS)
+ list(
+ APPEND
+ warning_flags
+ -Wno-class-memaccess
+ -Wno-unused-variable
+ -Wno-unused-parameter
+ -Wno-sign-compare
+ -Wno-unused-function
+ -Wno-unused-value
+ -Wno-unused-but-set-variable
+ -Wno-implicit-fallthrough
+ -Wno-missing-field-initializers
+ -Wno-strict-aliasing
+ -Wno-maybe-uninitialized
+ )
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+ list(APPEND warning_flags)
+ if(ARG_USE_EXTRA_WARNINGS)
+ list(APPEND warning_flags /W4)
+ elseif(ARG_USE_FEWER_WARNINGS)
+ list(APPEND warning_flags /W0)
+ else()
+ list(APPEND warning_flags /W2)
+ endif()
+ endif()
+
+ add_supported_cxx_flags(${target} PRIVATE ${warning_flags})
+
+ # Don't assume that symbols will be resolved at runtime
+ add_supported_cxx_linker_flags(${target} PRIVATE "-Wl,--no-undefined")
+
+ set_target_properties(
+ ${target}
+ PROPERTIES # -fvisibility=hidden
+ CXX_VISIBILITY_PRESET
+ hidden
+ # C++ standard
+ CXX_STANDARD
+ 17
+ # pic
+ POSITION_INDEPENDENT_CODE
+ ON
+ )
+
+ target_compile_definitions(
+ ${target}
+ PRIVATE # Add _DEBUG depending on the build configuration
+ $<$<CONFIG:Debug>:_DEBUG>
+ # For including windows.h in a way that minimized namespace
+ # pollution. Although we define these here, we still set them
+ # manually in any header files which may be included by another
+ # project
+ WIN32_LEAN_AND_MEAN
+ VC_EXTRALEAN
+ NOMINMAX
+ # Use multi-byte character set on Windows
+ UNICODE
+ _UNICODE
+ )
+
+ #
+ # Settings dependent on config options
+ #
+
+ if(SLANG_ENABLE_FULL_DEBUG_VALIDATION)
+ target_compile_definitions(
+ ${target}
+ PRIVATE SLANG_ENABLE_FULL_IR_VALIDATION
+ )
+ endif()
+
+ if(SLANG_ENABLE_DX_ON_VK)
+ target_compile_definitions(${target} PRIVATE SLANG_CONFIG_DX_ON_VK)
+ endif()
+
+ if(SLANG_ENABLE_ASAN)
+ add_supported_cxx_flags(
+ ${target}
+ PRIVATE
+ /fsanitize=address
+ -fsanitize=address
+ )
+ add_supported_cxx_linker_flags(
+ ${target}
+ BEFORE
+ PUBLIC
+ /INCREMENTAL:NO
+ -fsanitize=address
+ )
+ endif()
+endfunction()
diff --git a/cmake/FindAftermath.cmake b/cmake/FindAftermath.cmake
new file mode 100644
index 000000000..fe26c1abd
--- /dev/null
+++ b/cmake/FindAftermath.cmake
@@ -0,0 +1,26 @@
+set(Aftermath_ROOT_DIR "" CACHE PATH "Path to an installed Aftermath SDK")
+
+if(Aftermath_ROOT_DIR)
+ find_path(
+ Aftermath_INCLUDE_DIRS
+ NAMES GFSDK_Aftermath.h
+ PATH_SUFFIXES include
+ PATHS "${Aftermath_ROOT_DIR}"
+ NO_DEFAULT_PATH
+ )
+else()
+ find_path(Aftermath_INCLUDE_DIRS NAMES GFSDK_Aftermath.h)
+endif()
+
+# x86_64 only so far
+find_library(
+ Aftermath_LIBRARIES
+ NAMES GFSDK_Aftermath_Lib.x64
+ PATH_SUFFIXES x64
+ PATHS "${Aftermath_ROOT_DIR}/lib"
+)
+
+find_package_handle_standard_args(
+ Aftermath
+ REQUIRED_VARS Aftermath_INCLUDE_DIRS Aftermath_LIBRARIES
+)
diff --git a/cmake/FindNVAPI.cmake b/cmake/FindNVAPI.cmake
new file mode 100644
index 000000000..bd2a18718
--- /dev/null
+++ b/cmake/FindNVAPI.cmake
@@ -0,0 +1,34 @@
+set(NVAPI_ROOT_DIR "" CACHE PATH "Path to an installed NVAPI SDK")
+
+if(NVAPI_ROOT_DIR)
+ find_path(
+ NVAPI_INCLUDE_DIRS
+ NAMES nvapi.h
+ PATHS "${NVAPI_ROOT_DIR}"
+ NO_DEFAULT_PATH
+ )
+else()
+ find_path(
+ NVAPI_INCLUDE_DIRS
+ NAMES nvapi.h
+ PATHS "${slang-SOURCE_DIR}/external/nvapi"
+ NO_DEFAULT_PATH
+ )
+ find_path(NVAPI_INCLUDE_DIRS NAMES nvapi.h)
+
+ # The nvapi.h header is in the root, so we can populate that easily
+ set(NVAPI_ROOT_DIR ${NVAPI_INCLUDE_DIRS})
+endif()
+
+# x86_64 only so far
+find_library(
+ NVAPI_LIBRARIES
+ NAMES nvapi64
+ PATH_SUFFIXES amd64
+ PATHS ${NVAPI_ROOT_DIR}
+)
+
+find_package_handle_standard_args(
+ NVAPI
+ REQUIRED_VARS NVAPI_INCLUDE_DIRS NVAPI_LIBRARIES
+)
diff --git a/cmake/FindOptiX.cmake b/cmake/FindOptiX.cmake
new file mode 100644
index 000000000..d036c4fef
--- /dev/null
+++ b/cmake/FindOptiX.cmake
@@ -0,0 +1,15 @@
+set(Optix_ROOT_DIR "" CACHE PATH "Path to an installed OptiX SDK")
+
+if(Optix_ROOT_DIR)
+ find_path(
+ OptiX_INCLUDE_DIRS
+ NAMES optix.h
+ PATH_SUFFIXES include
+ PATHS "${Optix_ROOT_DIR}"
+ NO_DEFAULT_PATH
+ )
+else()
+ find_path(OptiX_INCLUDE_DIRS NAMES optix.h)
+endif()
+
+find_package_handle_standard_args(OptiX REQUIRED_VARS OptiX_INCLUDE_DIRS)
diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake
new file mode 100644
index 000000000..7044aaffc
--- /dev/null
+++ b/cmake/GitVersion.cmake
@@ -0,0 +1,50 @@
+find_package(Git)
+
+# Extract a version from the latest tag matching something like v1.2.3.4
+function(get_git_version var dir)
+ if(NOT DEFINED ${var})
+ set(version "0.0")
+ if(GIT_EXECUTABLE)
+ set(command
+ "${GIT_EXECUTABLE}"
+ -C
+ "${dir}"
+ describe
+ --abbrev=0
+ --tags
+ --match
+ v*
+ )
+ execute_process(
+ COMMAND ${command}
+ RESULT_VARIABLE result
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE version
+ )
+ if(NOT result EQUAL 0)
+ message(
+ WARNING
+ "Getting ${var} failed: ${command} returned ${result}"
+ )
+ elseif("${version}" MATCHES "^v([0-9]+(\.[0-9]+)*).*")
+ set(version "${CMAKE_MATCH_1}")
+ else()
+ message(
+ WARNING
+ "Couldn't parse numeric version (like v1.2.3) from ${version}"
+ )
+ endif()
+ else()
+ message(
+ WARNING
+ "Couldn't find git executable to get ${var}, please use -D${var}"
+ )
+ endif()
+ endif()
+
+ set(${var}
+ ${version}
+ CACHE STRING
+ "The project version, detected using git if available"
+ )
+endfunction()
diff --git a/cmake/Glob.cmake b/cmake/Glob.cmake
new file mode 100644
index 000000000..c960e5011
--- /dev/null
+++ b/cmake/Glob.cmake
@@ -0,0 +1,51 @@
+#
+# glob_append(MY_VAR my_glob) will append the results of file(GLOB
+# CONFIGURE_DEPENDS my_glob) to MY_VAR
+#
+# Any number of globs may be specified
+#
+function(glob_append dest)
+ file(GLOB files CONFIGURE_DEPENDS ${ARGN})
+ list(APPEND ${dest} ${files})
+ set(${dest} ${${dest}} PARENT_SCOPE)
+endfunction()
+
+#
+# Perform a recursive glob, and exclude any files appropriately according to
+# the host system and build options
+#
+function(slang_glob_sources var dir)
+ set(patterns
+ "*.cpp"
+ "*.h"
+ "*.natvis"
+ "*.natstepfilter"
+ "*.natjmc"
+ )
+ list(TRANSFORM patterns PREPEND "${dir}/")
+
+ file(GLOB_RECURSE files CONFIGURE_DEPENDS ${patterns})
+
+ if(NOT WIN32)
+ list(FILTER files EXCLUDE REGEX "(^|/)windows/.*")
+ endif()
+
+ if(NOT UNIX)
+ list(FILTER files EXCLUDE REGEX "(^|/)unix/.*")
+ endif()
+
+ if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows" AND NOT SLANG_ENABLE_DX_ON_VK)
+ list(FILTER files EXCLUDE REGEX "(^|/)d3d.*/.*")
+ endif()
+
+ if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows|Linux")
+ list(FILTER files EXCLUDE REGEX "(^|/)vulkan/.*")
+ endif()
+
+ if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
+ list(FILTER files EXCLUDE REGEX "(^|/)open-gl/.*")
+ endif()
+
+ list(APPEND ${var} ${files})
+ set(${var} ${${var}} PARENT_SCOPE)
+endfunction()
diff --git a/cmake/LLVM.cmake b/cmake/LLVM.cmake
new file mode 100644
index 000000000..10a31e2d1
--- /dev/null
+++ b/cmake/LLVM.cmake
@@ -0,0 +1,40 @@
+# A convenience on top of the llvm package's cmake files, this creates a target
+# to pass to target_link_libraries which correctly pulls in the llvm include
+# dir and other compile dependencies
+function(llvm_target_from_components target_name)
+ set(components ${ARGN})
+ llvm_map_components_to_libnames(llvm_libs
+ ${components}
+ )
+ add_library(${target_name} INTERFACE)
+ target_link_libraries(${target_name} INTERFACE ${llvm_libs})
+ target_include_directories(
+ ${target_name}
+ SYSTEM
+ INTERFACE ${LLVM_INCLUDE_DIRS}
+ )
+ target_compile_definitions(${target_name} INTERFACE ${LLVM_DEFINITIONS})
+ if(NOT LLVM_ENABLE_RTTI)
+ # Make sure that we don't disable rtti if this library wasn't compiled with
+ # support
+ add_supported_cxx_flags(${target_name} INTERFACE -fno-rtti /GR-)
+ endif()
+endfunction()
+
+# The same for clang
+function(clang_target_from_libs target_name)
+ set(clang_libs ${ARGN})
+ add_library(${target_name} INTERFACE)
+ target_link_libraries(${target_name} INTERFACE ${clang_libs})
+ target_include_directories(
+ ${target_name}
+ SYSTEM
+ INTERFACE ${CLANG_INCLUDE_DIRS}
+ )
+ target_compile_definitions(${target_name} INTERFACE ${CLANG_DEFINITIONS})
+ if(NOT LLVM_ENABLE_RTTI)
+ # Make sure that we don't disable rtti if this library wasn't compiled with
+ # support
+ add_supported_cxx_flags(${target_name} INTERFACE -fno-rtti /GR-)
+ endif()
+endfunction()
diff --git a/cmake/SlangTarget.cmake b/cmake/SlangTarget.cmake
new file mode 100644
index 000000000..44d6c945c
--- /dev/null
+++ b/cmake/SlangTarget.cmake
@@ -0,0 +1,377 @@
+#
+# A function to make target creation a little more declarative
+#
+# See the comments on the options below for usage
+#
+function(slang_add_target dir type)
+ set(no_value_args
+ # Don't include in the 'all' target
+ EXCLUDE_FROM_ALL
+ # This is loaded at runtime as a shared library
+ SHARED_LIBRARY_TOOL
+ # -Wextra
+ USE_EXTRA_WARNINGS
+ # don't set -Wall
+ USE_FEWER_WARNINGS
+ # Make this a Windows app, rather than a console app, only makes a
+ # difference when compiling for Windows
+ WIN32_EXECUTABLE
+ # Install this target for a non-component install
+ INSTALL
+ )
+ set(single_value_args
+ # Set the target name, useful for multiple targets from the same
+ # directory.
+ # By default this is the name of the last directory component given
+ TARGET_NAME
+ # Set the output name, otherwise defaults to the target name
+ OUTPUT_NAME
+ # Set an explicit output directory relative to the cmake binary
+ # directory. otherwise defaults to the binary directory root.
+ # Outputs are always placed in a further subdirectory according to
+ # build config
+ OUTPUT_DIR
+ # If this is a shared library then the ${EXPORT_MACRO_PREFIX}_DYNAMIC and
+ # ${EXPORT_MACRO_PREFIX}_DYNAMIC_EXPORT macros are set for using and
+ # building respectively
+ EXPORT_MACRO_PREFIX
+ # The folder in which to place this target for IDE-based generators (VS
+ # and XCode)
+ FOLDER
+ # The working directory for debugging
+ DEBUG_DIR
+ # Install this target as part of a component
+ INSTALL_COMPONENT
+ )
+ set(multi_value_args
+ # Use exactly these sources, instead of globbing from the directory
+ # argument
+ EXPLICIT_SOURCE
+ # Additional directories from which to glob source
+ EXTRA_SOURCE_DIRS
+ # Additional compile definitions
+ EXTRA_COMPILE_DEFINITIONS_PRIVATE
+ EXTRA_COMPILE_DEFINITIONS_PUBLIC
+ # Targets with which to link privately
+ LINK_WITH_PRIVATE
+ # Targets whose headers we use, but don't link with
+ INCLUDE_FROM_PRIVATE
+ # Any include directories other targets need to use this target
+ INCLUDE_DIRECTORIES_PUBLIC
+ # Add a dependency on the new target to the specified targets
+ REQUIRED_BY
+ # Add a dependency to the new target on the specified targets
+ REQUIRES
+ # Globs for any headers to install
+ PUBLIC_HEADERS
+ )
+ cmake_parse_arguments(
+ ARG
+ "${no_value_args}"
+ "${single_value_args}"
+ "${multi_value_args}"
+ ${ARGN}
+ )
+
+ if(DEFINED ARG_UNPARSED_ARGUMENTS OR DEFINED ARG_KEYWORDS_MISSING_VALUES)
+ foreach(unparsed_arg ${ARG_UNPARSED_ARGUMENTS})
+ message(
+ SEND_ERROR
+ "Unrecognized argument in slang_add_target: ${unparsed_arg}"
+ )
+ endforeach()
+ foreach(bad_kwarg ${ARG_KEYWORDS_MISSING_VALUES})
+ message(
+ SEND_ERROR
+ "Keyword argument missing values in slang_add_target: ${bad_kwarg}"
+ )
+ endforeach()
+ return()
+ endif()
+
+ #
+ # Set up some variables, including the target name
+ #
+ get_filename_component(dir_absolute ${dir} ABSOLUTE)
+ if(DEFINED ARG_TARGET_NAME)
+ set(target ${ARG_TARGET_NAME})
+ else()
+ get_filename_component(target ${dir_absolute} NAME)
+ endif()
+
+ #
+ # Find the source for this target
+ #
+ if(ARG_EXPLICIT_SOURCE)
+ list(APPEND source ${ARG_EXPLICIT_SOURCE})
+ else()
+ slang_glob_sources(source ${dir})
+ endif()
+ foreach(extra_dir ${ARG_EXTRA_SOURCE_DIRS})
+ slang_glob_sources(source ${extra_dir})
+ endforeach()
+
+ #
+ # Create the target
+ #
+ set(library_types
+ STATIC
+ SHARED
+ OBJECT
+ MODULE
+ ALIAS
+ )
+ if(type STREQUAL "EXECUTABLE")
+ add_executable(${target} ${source})
+ elseif(type STREQUAL "LIBRARY")
+ add_library(${target} ${source})
+ elseif(type IN_LIST library_types)
+ add_library(${target} ${type} ${source})
+ else()
+ message(
+ SEND_ERROR
+ "Unsupported target type ${type} in slang_add_target"
+ )
+ return()
+ endif()
+
+ #
+ # Set the output directory
+ #
+ # We don't want the output directory to be sensitive to where
+ # slang_add_target is called from, so set it explicitly here.
+ #
+ if(DEFINED ARG_OUTPUT_DIR)
+ set(output_dir "${CMAKE_BINARY_DIR}/${ARG_OUTPUT_DIR}/$<CONFIG>")
+ else()
+ # Default to placing things in the cmake binary root.
+ #
+ # While it would be nice to place things according to their
+ # subdirectory, Windows' inflexibility in being able to find DLLs makes
+ # this tricky there.
+ set(output_dir "${CMAKE_BINARY_DIR}/$<CONFIG>")
+ endif()
+ set(archive_subdir ${library_subdir})
+ if(type STREQUAL "MODULE")
+ set(library_subdir ${module_subdir})
+ endif()
+ set_target_properties(
+ ${target}
+ PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY "${output_dir}/${archive_subdir}"
+ LIBRARY_OUTPUT_DIRECTORY "${output_dir}/${library_subdir}"
+ RUNTIME_OUTPUT_DIRECTORY "${output_dir}/${runtime_subdir}"
+ PDB_OUTPUT_DIRECTORY "${output_dir}/${runtime_subdir}"
+ )
+
+ #
+ # Set common compile options and properties
+ #
+ if(ARG_USE_EXTRA_WARNINGS)
+ set_default_compile_options(${target} USE_EXTRA_WARNINGS)
+ elseif(ARG_USE_FEWER_WARNINGS)
+ set_default_compile_options(${target} USE_FEWER_WARNINGS)
+ else()
+ set_default_compile_options(${target})
+ endif()
+
+ set_target_properties(
+ ${target}
+ PROPERTIES EXCLUDE_FROM_ALL ${ARG_EXCLUDE_FROM_ALL}
+ )
+
+ set_target_properties(
+ ${target}
+ PROPERTIES WIN32_EXECUTABLE ${ARG_WIN32_EXECUTABLE}
+ )
+
+ if(DEFINED ARG_OUTPUT_NAME)
+ set_target_properties(
+ ${target}
+ PROPERTIES OUTPUT_NAME ${ARG_OUTPUT_NAME}
+ )
+ endif()
+
+ if(DEFINED ARG_FOLDER)
+ set_target_properties(${target} PROPERTIES FOLDER ${ARG_FOLDER})
+ endif()
+
+ if(DEFINED ARG_DEBUG_DIR)
+ set_target_properties(
+ ${target}
+ PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ARG_DEBUG_DIR}
+ )
+ endif()
+
+ #
+ # Link and include from dependencies
+ #
+ target_link_libraries(${target} PRIVATE ${ARG_LINK_WITH_PRIVATE})
+
+ foreach(include_from ${ARG_INCLUDE_FROM_PRIVATE})
+ target_include_directories(
+ ${target}
+ PRIVATE
+ $<TARGET_PROPERTY:${include_from},INTERFACE_INCLUDE_DIRECTORIES>
+ )
+ endforeach()
+
+ #
+ # Set our exported include directories
+ #
+ foreach(inc ${ARG_INCLUDE_DIRECTORIES_PUBLIC})
+ get_filename_component(inc_abs ${inc} ABSOLUTE)
+ target_include_directories(
+ ${target}
+ PUBLIC "$<BUILD_INTERFACE:${inc_abs}>"
+ )
+ endforeach()
+
+ #
+ # Set up export macros
+ #
+ get_target_property(target_type ${target} TYPE)
+ if(DEFINED ARG_EXPORT_MACRO_PREFIX)
+ if(
+ target_type STREQUAL SHARED_LIBRARY
+ OR target_type STREQUAL MODULE_LIBRARY
+ )
+ target_compile_definitions(
+ ${target}
+ PUBLIC "${ARG_EXPORT_MACRO_PREFIX}_DYNAMIC"
+ PRIVATE "${ARG_EXPORT_MACRO_PREFIX}_DYNAMIC_EXPORT"
+ )
+ endif()
+ endif()
+
+ #
+ # Other dependencies
+ #
+ foreach(requirer ${ARG_REQUIRED_BY})
+ add_dependencies(${requirer} ${target})
+ endforeach()
+
+ if(DEFINED ARG_REQUIRES)
+ add_dependencies(${target} ${ARG_REQUIRES})
+ endif()
+
+ #
+ # Other preprocessor defines
+ #
+ if(ARG_EXTRA_COMPILE_DEFINITIONS_PRIVATE)
+ target_compile_definitions(
+ ${target}
+ PRIVATE ${ARG_EXTRA_COMPILE_DEFINITIONS_PRIVATE}
+ )
+ endif()
+ if(ARG_EXTRA_COMPILE_DEFINITIONS_PUBLIC)
+ target_compile_definitions(
+ ${target}
+ PUBLIC ${ARG_EXTRA_COMPILE_DEFINITIONS_PUBLIC}
+ )
+ endif()
+
+ #
+ # Since we do a lot of dynamic loading, unconditionally set the build rpath
+ # to find our libraries. Ordinarily CMake would sort this out, but we do
+ # have libraries which at build time don't depend on any other shared
+ # libraries of ours but which do load them at runtime, hence the need to do
+ # this explicitly here.
+ #
+ if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ set(ORIGIN "@loader_path")
+ else()
+ set(ORIGIN "$ORIGIN")
+ endif()
+ set_property(
+ TARGET ${target}
+ APPEND
+ PROPERTY BUILD_RPATH "${ORIGIN}/../${library_subdir}"
+ )
+ set_property(
+ TARGET ${target}
+ APPEND
+ PROPERTY INSTALL_RPATH "${ORIGIN}/../${library_subdir}"
+ )
+
+ # On the same topic, give everything a dylib suffix on Mac OS
+ if(CMAKE_SYSTEM_NAME MATCHES "Darwin" AND type STREQUAL "MODULE")
+ set_property(TARGET ${target} PROPERTY SUFFIX ".dylib")
+ endif()
+
+ #
+ # Mark headers for installation
+ #
+ if(ARG_PUBLIC_HEADERS)
+ if(NOT ARG_INSTALL)
+ message(
+ WARNING
+ "${target} was declared with PUBLIC_HEADERS but without INSTALL, the former will do nothing"
+ )
+ endif()
+
+ glob_append(public_headers ${ARG_PUBLIC_HEADERS})
+ if(NOT public_headers)
+ message(WARNING "${target}'s PUBLIC_HEADER globs found no matches")
+ else()
+ set_target_properties(
+ ${target}
+ PROPERTIES PUBLIC_HEADER "${public_headers}"
+ )
+ endif()
+ endif()
+
+ #
+ # Mark for installation
+ #
+ if(ARG_INSTALL OR ARG_INSTALL_COMPONENT)
+ set(component_args)
+ if(ARG_INSTALL_COMPONENT)
+ set(component_args COMPONENT ${ARG_INSTALL_COMPONENT})
+ endif()
+ set(exclude_arg)
+ if(NOT ARG_INSTALL)
+ set(exclude_arg EXCLUDE_FROM_ALL)
+ endif()
+ install(
+ TARGETS ${target}
+ EXPORT SlangTargets
+ ARCHIVE
+ DESTINATION ${archive_subdir}
+ ${component_args}
+ ${exclude_arg}
+ LIBRARY
+ DESTINATION ${library_subdir}
+ ${component_args}
+ ${exclude_arg}
+ RUNTIME
+ DESTINATION ${runtime_subdir}
+ ${component_args}
+ ${exclude_arg}
+ PUBLIC_HEADER
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ ${component_args}
+ ${exclude_arg}
+ )
+ endif()
+endfunction()
+
+# Ideally we'd use CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_RUNTIMEDIR here,
+# however some Slang functionality (specifically generating executables on
+# Linux systems) relies on runtime libraries being at "$ORIGIN/../lib". This
+# could be improved by setting at configure-time that path to be the relative
+# path from CM_I_RD to CM_I_LD.
+set(library_subdir lib)
+set(runtime_subdir bin)
+
+# On Windows, because there's no RPATH, place modules in bin, next to the
+# executables which load them (by deault, CMAKE will place them in lib and
+# expect the application to seek them out there)
+#
+# This variable is used in the above function as and elsewhere for installing
+# an imported module (slang-llvm from binary), hence why it's defined here.
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(module_subdir ${runtime_subdir})
+else()
+ set(module_subdir ${library_subdir})
+endif()