yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Dario MylonopoulosFix CMake error with generator on list in 3.22.1 (#8364)2e0fe3d06

master
22.8 KiB686 linesraw
1#
2# A function to make target specification a little more declarative
3#
4# See the comments on the options below for usage
5#
6function(slang_add_target dir type)
7    set(no_value_args
8        # Don't include in the 'all' target
9        EXCLUDE_FROM_ALL
10        # This is loaded at runtime as a shared library
11        SHARED_LIBRARY_TOOL
12        # -Wextra
13        USE_EXTRA_WARNINGS
14        # don't set -Wall
15        USE_FEWER_WARNINGS
16        # Make this a Windows app, rather than a console app, only makes a
17        # difference when compiling for Windows
18        WIN32_EXECUTABLE
19        # Install this target for a non-component install
20        INSTALL
21        # Don't include any source in this target, this is a complement to
22        # EXPLICIT_SOURCE, and doesn't interact with EXTRA_SOURCE_DIRS
23        NO_SOURCE
24        # Don't generate split debug info for this target
25        NO_SPLIT_DEBUG_INFO
26    )
27    set(single_value_args
28        # Set the target name, useful for multiple targets from the same
29        # directory.
30        # By default this is the name of the last directory component given
31        TARGET_NAME
32        # Set the output name, otherwise defaults to the target name
33        OUTPUT_NAME
34        # Set an explicit output directory relative to the cmake binary
35        # directory. otherwise defaults to the binary directory root.
36        # Outputs are always placed in a further subdirectory according to
37        # build config
38        OUTPUT_DIR
39        # If this is a shared library then the ${EXPORT_MACRO_PREFIX}_DYNAMIC and
40        # ${EXPORT_MACRO_PREFIX}_DYNAMIC_EXPORT macros are set for using and
41        # building respectively
42        EXPORT_MACRO_PREFIX
43        # Ignore target type and use a particular style of export macro
44        # _DYNAMIC or _STATIC, this is useful when the target type is OBJECT
45        # pass in STATIC or SHARED
46        EXPORT_TYPE_AS
47        # The folder in which to place this target for IDE-based generators (VS
48        # and XCode)
49        FOLDER
50        # The working directory for debugging
51        DEBUG_DIR
52        # Install this target as part of a component
53        INSTALL_COMPONENT
54        # Override the debug info component name for installation
55        # explicit name instead, used for externally built things such as
56        # slang-glslang and slang-llvm which have large pdb files
57        DEBUG_INFO_INSTALL_COMPONENT
58        # The name of the Export set to associate with this installed target
59        EXPORT_SET_NAME
60    )
61    set(multi_value_args
62        # Use exactly these sources, instead of globbing from the directory
63        # argument
64        EXPLICIT_SOURCE
65        # Additional directories from which to glob source
66        EXTRA_SOURCE_DIRS
67        # Additional compile definitions and options
68        EXTRA_COMPILE_DEFINITIONS_PRIVATE
69        EXTRA_COMPILE_DEFINITIONS_PUBLIC
70        EXTRA_COMPILE_OPTIONS_PRIVATE
71        # Targets with which to link privately
72        LINK_WITH_PRIVATE
73        # Targets with which to link publicly, for example if their headers
74        # appear in our headers
75        LINK_WITH_PUBLIC
76        # Frameworks with which to link privately
77        LINK_WITH_FRAMEWORK
78        # Targets whose headers we use, but don't link with
79        INCLUDE_FROM_PRIVATE
80        # Targets whose headers we use in our headers, so need to make sure
81        # dependencies of this target also include them
82        INCLUDE_FROM_PUBLIC
83        # Any include directories other targets need to use this target
84        INCLUDE_DIRECTORIES_PUBLIC
85        # Any include directories this target only needs
86        INCLUDE_DIRECTORIES_PRIVATE
87        # Add a dependency on the new target to the specified targets
88        REQUIRED_BY
89        # Add a dependency to the new target on the specified targets
90        REQUIRES
91        # Add a dependency to the new target on the specified targets if they exist
92        OPTIONAL_REQUIRES
93        # Globs for any headers to install
94        PUBLIC_HEADERS
95    )
96    cmake_parse_arguments(
97        ARG
98        "${no_value_args}"
99        "${single_value_args}"
100        "${multi_value_args}"
101        ${ARGN}
102    )
103
104    if(DEFINED ARG_UNPARSED_ARGUMENTS OR DEFINED ARG_KEYWORDS_MISSING_VALUES)
105        foreach(unparsed_arg ${ARG_UNPARSED_ARGUMENTS})
106            message(
107                SEND_ERROR
108                "Unrecognized argument in slang_add_target: ${unparsed_arg}"
109            )
110        endforeach()
111        foreach(bad_kwarg ${ARG_KEYWORDS_MISSING_VALUES})
112            message(
113                SEND_ERROR
114                "Keyword argument missing values in slang_add_target: ${bad_kwarg}"
115            )
116        endforeach()
117        return()
118    endif()
119
120    #
121    # Set up some variables, including the target name
122    #
123    get_filename_component(dir_absolute ${dir} ABSOLUTE)
124    if(DEFINED ARG_TARGET_NAME)
125        set(target ${ARG_TARGET_NAME})
126    else()
127        get_filename_component(target ${dir_absolute} NAME)
128    endif()
129
130    #
131    # Find the source for this target
132    #
133    if(ARG_NO_SOURCE)
134    elseif(ARG_EXPLICIT_SOURCE)
135        list(APPEND source ${ARG_EXPLICIT_SOURCE})
136    else()
137        slang_glob_sources(source ${dir})
138    endif()
139    foreach(extra_dir ${ARG_EXTRA_SOURCE_DIRS})
140        slang_glob_sources(source ${extra_dir})
141    endforeach()
142
143    #
144    # Create the target
145    #
146    set(library_types
147        STATIC
148        SHARED
149        OBJECT
150        MODULE
151        ALIAS
152    )
153    if(type STREQUAL "EXECUTABLE")
154        add_executable(${target} ${source})
155    elseif(type STREQUAL "LIBRARY")
156        add_library(${target} ${source})
157    elseif(type IN_LIST library_types)
158        add_library(${target} ${type} ${source})
159    else()
160        message(
161            SEND_ERROR
162            "Unsupported target type ${type} in slang_add_target"
163        )
164        return()
165    endif()
166
167    # Enable link-time optimization for release builds
168    # See: https://cmake.org/cmake/help/latest/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.html
169    if(SLANG_ENABLE_RELEASE_LTO)
170        set_target_properties(
171            ${target}
172            PROPERTIES
173                INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
174                INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE
175        )
176    endif()
177
178    #
179    # Set the output directory
180    #
181    # We don't want the output directory to be sensitive to where
182    # slang_add_target is called from, so set it explicitly here.
183    #
184    if(DEFINED ARG_OUTPUT_DIR)
185        set(output_dir "${CMAKE_BINARY_DIR}/${ARG_OUTPUT_DIR}/$<CONFIG>")
186    else()
187        # Default to placing things in the cmake binary root.
188        #
189        # While it would be nice to place things according to their
190        # subdirectory, Windows' inflexibility in being able to find DLLs makes
191        # this tricky there.
192        set(output_dir "${CMAKE_BINARY_DIR}/$<CONFIG>")
193    endif()
194    set(archive_subdir ${library_subdir})
195    if(type STREQUAL "MODULE")
196        set(library_subdir ${module_subdir})
197    endif()
198
199    # Respect user-defined CMAKE_*_OUTPUT_DIRECTORY variables if they are set
200    if(DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
201        set(archive_output_dir "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
202    else()
203        set(archive_output_dir "${output_dir}/${archive_subdir}")
204    endif()
205
206    if(DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
207        set(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
208    else()
209        set(library_output_dir "${output_dir}/${library_subdir}")
210    endif()
211
212    if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
213        set(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
214        set(pdb_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
215    else()
216        set(runtime_output_dir "${output_dir}/${runtime_subdir}")
217        set(pdb_output_dir "${output_dir}/${runtime_subdir}")
218    endif()
219
220    set_target_properties(
221        ${target}
222        PROPERTIES
223            ARCHIVE_OUTPUT_DIRECTORY "${archive_output_dir}"
224            LIBRARY_OUTPUT_DIRECTORY "${library_output_dir}"
225            RUNTIME_OUTPUT_DIRECTORY "${runtime_output_dir}"
226            PDB_OUTPUT_DIRECTORY "${pdb_output_dir}"
227    )
228
229    # For Multi-Config generators we also need to set per-config output directories
230    # if user-defined paths are provided
231    if(DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
232        set_target_properties(
233            ${target}
234            PROPERTIES
235                ARCHIVE_OUTPUT_DIRECTORY_DEBUG
236                    "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}"
237                ARCHIVE_OUTPUT_DIRECTORY_RELEASE
238                    "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}"
239                ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO
240                    "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}"
241                ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL
242                    "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}"
243        )
244    endif()
245
246    if(DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
247        set_target_properties(
248            ${target}
249            PROPERTIES
250                LIBRARY_OUTPUT_DIRECTORY_DEBUG
251                    "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
252                LIBRARY_OUTPUT_DIRECTORY_RELEASE
253                    "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
254                LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO
255                    "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
256                LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL
257                    "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
258        )
259    endif()
260
261    if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
262        set_target_properties(
263            ${target}
264            PROPERTIES
265                RUNTIME_OUTPUT_DIRECTORY_DEBUG
266                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
267                RUNTIME_OUTPUT_DIRECTORY_RELEASE
268                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
269                RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO
270                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
271                RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL
272                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
273                PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
274                PDB_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
275                PDB_OUTPUT_DIRECTORY_RELWITHDEBINFO
276                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
277                PDB_OUTPUT_DIRECTORY_MINSIZEREL
278                    "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
279        )
280    endif()
281
282    set(debug_configs "Debug,RelWithDebInfo")
283    if(SLANG_ENABLE_RELEASE_DEBUG_INFO)
284        set(debug_configs "Debug,RelWithDebInfo,Release")
285    endif()
286
287    set_target_properties(
288        ${target}
289        PROPERTIES
290            MSVC_DEBUG_INFORMATION_FORMAT
291                "$<$<CONFIG:${debug_configs}>:Embedded>"
292    )
293    if(MSVC)
294        target_link_options(
295            ${target}
296            PRIVATE "$<$<CONFIG:${debug_configs}>:/DEBUG>"
297        )
298    else()
299        target_compile_options(
300            ${target}
301            PRIVATE "$<$<CONFIG:${debug_configs}>:-g>"
302        )
303    endif()
304
305    #
306    # Set common compile options and properties
307    #
308    if(ARG_USE_EXTRA_WARNINGS)
309        set_default_compile_options(${target} USE_EXTRA_WARNINGS)
310    elseif(ARG_USE_FEWER_WARNINGS)
311        set_default_compile_options(${target} USE_FEWER_WARNINGS)
312    else()
313        set_default_compile_options(${target})
314    endif()
315
316    # Set debug info options if not disabled
317    # Determine if this target produces a binary that can have debug info
318    if(
319        NOT ARG_NO_SPLIT_DEBUG_INFO
320        AND type MATCHES "^(EXECUTABLE|SHARED|MODULE)$"
321        AND SLANG_ENABLE_SPLIT_DEBUG_INFO
322    )
323        set(generate_split_debug_info TRUE)
324    else()
325        set(generate_split_debug_info FALSE)
326    endif()
327
328    if(generate_split_debug_info)
329        if(MSVC)
330            set_target_properties(
331                ${target}
332                PROPERTIES
333                    COMPILE_PDB_NAME "${target}"
334                    COMPILE_PDB_OUTPUT_DIRECTORY "${output_dir}"
335            )
336        else()
337            if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
338                # macOS - use dsymutil with --flat to create separate debug file
339                add_custom_command(
340                    TARGET ${target}
341                    POST_BUILD
342                    COMMAND
343                        dsymutil --flat $<TARGET_FILE:${target}> -o
344                        $<TARGET_FILE:${target}>.dwarf
345                    COMMAND chmod 644 $<TARGET_FILE:${target}>.dwarf
346                    COMMAND ${CMAKE_STRIP} -S $<TARGET_FILE:${target}>
347                    WORKING_DIRECTORY ${output_dir}
348                    VERBATIM
349                )
350            else()
351                add_custom_command(
352                    TARGET ${target}
353                    POST_BUILD
354                    COMMAND
355                        ${CMAKE_OBJCOPY} --only-keep-debug
356                        $<TARGET_FILE:${target}> $<TARGET_FILE:${target}>.dwarf
357                    WORKING_DIRECTORY ${output_dir}
358                    VERBATIM
359                )
360                # We may be building for Android on a Windows host, where chmod isn't available or needed.
361                if(NOT CMAKE_HOST_WIN32)
362                    add_custom_command(
363                        TARGET ${target}
364                        POST_BUILD
365                        COMMAND chmod 644 $<TARGET_FILE:${target}>.dwarf
366                        WORKING_DIRECTORY ${output_dir}
367                        VERBATIM
368                    )
369                endif()
370                add_custom_command(
371                    TARGET ${target}
372                    POST_BUILD
373                    COMMAND
374                        ${CMAKE_STRIP} --strip-debug $<TARGET_FILE:${target}>
375                    COMMAND
376                        ${CMAKE_OBJCOPY}
377                        --add-gnu-debuglink=$<TARGET_FILE:${target}>.dwarf
378                        $<TARGET_FILE:${target}>
379                    WORKING_DIRECTORY ${output_dir}
380                    VERBATIM
381                )
382            endif()
383        endif()
384    endif()
385
386    set_target_properties(
387        ${target}
388        PROPERTIES EXCLUDE_FROM_ALL ${ARG_EXCLUDE_FROM_ALL}
389    )
390
391    set_target_properties(
392        ${target}
393        PROPERTIES WIN32_EXECUTABLE ${ARG_WIN32_EXECUTABLE}
394    )
395
396    if(DEFINED ARG_OUTPUT_NAME)
397        set_target_properties(
398            ${target}
399            PROPERTIES OUTPUT_NAME ${ARG_OUTPUT_NAME}
400        )
401    endif()
402
403    if(DEFINED ARG_FOLDER)
404        set_target_properties(${target} PROPERTIES FOLDER ${ARG_FOLDER})
405    endif()
406
407    if(DEFINED ARG_DEBUG_DIR)
408        set_target_properties(
409            ${target}
410            PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ARG_DEBUG_DIR}
411        )
412    endif()
413
414    #
415    # Link and include from dependencies
416    #
417    if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.26")
418        target_link_libraries(
419            ${target}
420            PRIVATE $<BUILD_LOCAL_INTERFACE:${ARG_LINK_WITH_PRIVATE}>
421        )
422    else()
423        # Expand the list manually to work around a bug in cmake 3.22.1
424        # See: https://github.com/shader-slang/slang/issues/8335
425        foreach(lib IN LISTS ARG_LINK_WITH_PRIVATE)
426            target_link_libraries(${target} PRIVATE $<BUILD_INTERFACE:${lib}>)
427        endforeach()
428    endif()
429
430    target_link_libraries(${target} PUBLIC ${ARG_LINK_WITH_PUBLIC})
431
432    if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
433        foreach(link_framework ${ARG_LINK_WITH_FRAMEWORK})
434            target_link_libraries(
435                ${target}
436                PRIVATE "-framework ${link_framework}"
437            )
438        endforeach()
439    endif()
440
441    foreach(include_from ${ARG_INCLUDE_FROM_PRIVATE})
442        target_include_directories(
443            ${target}
444            PRIVATE
445                $<$<BOOL:${include_from}>:$<TARGET_PROPERTY:${include_from},INTERFACE_INCLUDE_DIRECTORIES>>
446        )
447    endforeach()
448    foreach(include_from ${ARG_INCLUDE_FROM_PUBLIC})
449        target_include_directories(
450            ${target}
451            PUBLIC
452                $<$<BOOL:${include_from}>:$<TARGET_PROPERTY:${include_from},INTERFACE_INCLUDE_DIRECTORIES>>
453        )
454    endforeach()
455
456    #
457    # Set our exported include directories
458    #
459    foreach(inc ${ARG_INCLUDE_DIRECTORIES_PUBLIC})
460        get_filename_component(inc_abs ${inc} ABSOLUTE)
461        target_include_directories(
462            ${target}
463            PUBLIC
464                "$<BUILD_INTERFACE:${inc_abs}>"
465                "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
466        )
467    endforeach()
468    foreach(inc ${ARG_INCLUDE_DIRECTORIES_PRIVATE})
469        get_filename_component(inc_abs ${inc} ABSOLUTE)
470        if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.26")
471            target_include_directories(
472                ${target}
473                PRIVATE "$<BUILD_LOCAL_INTERFACE:${inc_abs}>"
474            )
475        else()
476            target_include_directories(
477                ${target}
478                PRIVATE "$<BUILD_INTERFACE:${inc_abs}>"
479            )
480        endif()
481    endforeach()
482
483    #
484    # Set up export macros
485    #
486    get_target_property(target_type ${target} TYPE)
487    if(DEFINED ARG_EXPORT_MACRO_PREFIX)
488        if(
489            target_type STREQUAL SHARED_LIBRARY
490            OR target_type STREQUAL MODULE_LIBRARY
491            OR ARG_EXPORT_TYPE_AS STREQUAL SHARED
492            OR ARG_EXPORT_TYPE_AS STREQUAL MODULE
493        )
494            target_compile_definitions(
495                ${target}
496                PUBLIC "${ARG_EXPORT_MACRO_PREFIX}_DYNAMIC"
497                PRIVATE "${ARG_EXPORT_MACRO_PREFIX}_DYNAMIC_EXPORT"
498            )
499        elseif(
500            target_type STREQUAL STATIC_LIBRARY
501            OR ARG_EXPORT_TYPE_AS STREQUAL STATIC
502        )
503            target_compile_definitions(
504                ${target}
505                PUBLIC "${ARG_EXPORT_MACRO_PREFIX}_STATIC"
506            )
507        else()
508            message(
509                WARNING
510                "unhandled case in slang_add_target while setting export macro"
511            )
512        endif()
513    endif()
514
515    #
516    # Other dependencies
517    #
518    foreach(requirer ${ARG_REQUIRED_BY})
519        add_dependencies(${requirer} ${target})
520    endforeach()
521
522    if(DEFINED ARG_REQUIRES)
523        add_dependencies(${target} ${ARG_REQUIRES})
524    endif()
525
526    foreach(required ${ARG_OPTIONAL_REQUIRES})
527        if(TARGET ${required})
528            add_dependencies(${target} ${required})
529        endif()
530    endforeach()
531
532    #
533    # Other preprocessor defines and options
534    #
535    if(ARG_EXTRA_COMPILE_DEFINITIONS_PRIVATE)
536        target_compile_definitions(
537            ${target}
538            PRIVATE ${ARG_EXTRA_COMPILE_DEFINITIONS_PRIVATE}
539        )
540    endif()
541    if(ARG_EXTRA_COMPILE_DEFINITIONS_PUBLIC)
542        target_compile_definitions(
543            ${target}
544            PUBLIC ${ARG_EXTRA_COMPILE_DEFINITIONS_PUBLIC}
545        )
546    endif()
547    if(ARG_EXTRA_COMPILE_OPTIONS_PRIVATE)
548        target_compile_options(
549            ${target}
550            PRIVATE ${ARG_EXTRA_COMPILE_OPTIONS_PRIVATE}
551        )
552    endif()
553
554    #
555    # Since we do a lot of dynamic loading, unconditionally set the build rpath
556    # to find our libraries. Ordinarily CMake would sort this out, but we do
557    # have libraries which at build time don't depend on any other shared
558    # libraries of ours but which do load them at runtime, hence the need to do
559    # this explicitly here.
560    #
561    if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
562        set(ORIGIN "@loader_path")
563    else()
564        set(ORIGIN "$ORIGIN")
565    endif()
566    set_property(
567        TARGET ${target}
568        APPEND
569        PROPERTY BUILD_RPATH "${ORIGIN}/../${library_subdir};${ORIGIN}"
570    )
571    set_property(
572        TARGET ${target}
573        APPEND
574        PROPERTY INSTALL_RPATH "${ORIGIN}/../${library_subdir};${ORIGIN}"
575    )
576
577    # On the same topic, give everything a dylib suffix on Mac OS
578    if(CMAKE_SYSTEM_NAME MATCHES "Darwin" AND type STREQUAL "MODULE")
579        set_property(TARGET ${target} PROPERTY SUFFIX ".dylib")
580    endif()
581
582    #
583    # Mark headers for installation
584    #
585    if(ARG_PUBLIC_HEADERS)
586        if(NOT ARG_INSTALL)
587            message(
588                WARNING
589                "${target} was declared with PUBLIC_HEADERS but without INSTALL, the former will do nothing"
590            )
591        endif()
592
593        glob_append(public_headers ${ARG_PUBLIC_HEADERS})
594        if(NOT public_headers)
595            message(WARNING "${target}'s PUBLIC_HEADER globs found no matches")
596        else()
597            set_target_properties(
598                ${target}
599                PROPERTIES PUBLIC_HEADER "${public_headers}"
600            )
601        endif()
602    endif()
603
604    #
605    # Mark for installation
606    #
607    macro(i)
608        if(ARG_EXPORT_SET_NAME)
609            set(export_args EXPORT ${ARG_EXPORT_SET_NAME})
610        else()
611            if(type MATCHES "^(EXECUTABLE|SHARED|MODULE)$")
612                message(
613                    WARNING
614                    "Target ${target} is set to be INSTALLED but EXPORT_SET_NAME wasn't specified"
615                )
616            endif()
617            set(export_args)
618        endif()
619        install(
620            TARGETS ${target} ${export_args}
621            ARCHIVE DESTINATION ${archive_subdir}
622            ${ARGN}
623            LIBRARY DESTINATION ${library_subdir}
624            ${ARGN}
625            RUNTIME DESTINATION ${runtime_subdir}
626            ${ARGN}
627            PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
628            ${ARGN}
629        )
630    endmacro()
631
632    if(ARG_INSTALL_COMPONENT)
633        i(EXCLUDE_FROM_ALL COMPONENT ${ARG_INSTALL_COMPONENT})
634        set(debug_component "${ARG_INSTALL_COMPONENT}-debug-info")
635    elseif(ARG_INSTALL)
636        i()
637        set(debug_component "debug-info")
638    endif()
639
640    if(DEFINED ARG_DEBUG_INFO_INSTALL_COMPONENT)
641        set(debug_component "${ARG_DEBUG_INFO_INSTALL_COMPONENT}")
642    endif()
643
644    # Install debug info only if target is being installed
645    if((ARG_INSTALL OR ARG_INSTALL_COMPONENT) AND generate_split_debug_info)
646        if(type STREQUAL "EXECUTABLE" OR WIN32)
647            set(debug_dest ${runtime_subdir})
648        else()
649            set(debug_dest ${library_subdir})
650        endif()
651
652        if(MSVC)
653            set(debug_file $<TARGET_PDB_FILE:${target}>)
654        else()
655            set(debug_file "$<TARGET_FILE:${target}>.dwarf")
656        endif()
657
658        install(
659            FILES ${debug_file}
660            DESTINATION ${debug_dest}
661            COMPONENT ${debug_component}
662            EXCLUDE_FROM_ALL
663            OPTIONAL
664        )
665    endif()
666endfunction()
667
668# Ideally we'd use CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_RUNTIMEDIR here,
669# however some Slang functionality (specifically generating executables on
670# Linux systems) relies on runtime libraries being at "$ORIGIN/../lib". This
671# could be improved by setting at configure-time that path to be the relative
672# path from CM_I_RD to CM_I_LD.
673set(library_subdir lib)
674set(runtime_subdir bin)
675
676# On Windows, because there's no RPATH, place modules in bin, next to the
677# executables which load them (by deault, CMAKE will place them in lib and
678# expect the application to seek them out there)
679#
680# This variable is used in the above function as and elsewhere for installing
681# an imported module (slang-llvm from binary), hence why it's defined here.
682if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
683    set(module_subdir ${runtime_subdir})
684else()
685    set(module_subdir ${library_subdir})
686endif()