-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy paththerock_subproject.cmake
1150 lines (1062 loc) · 50.6 KB
/
therock_subproject.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# therock_subproject.cmake
# Facilities for defining build subprojects. This has some similarity to the
# built-in ExternalProject and FetchContent facilities, but it is intended to
# be performant and ergonomic for a super project of our scale where the sources
# of the subprojects are expected to be modified as part of the super-project
# development flow.
include(ExternalProject)
# Global properties.
# THEROCK_DEFAULT_CMAKE_VARS:
# List of CMake variables that will be injected by default into the
# project_init.cmake file of each subproject.
set_property(GLOBAL PROPERTY THEROCK_DEFAULT_CMAKE_VARS
CMAKE_BUILD_TYPE
CMAKE_PROGRAM_PATH
CMAKE_PLATFORM_NO_VERSIONED_SONAME
Python3_EXECUTABLE
Python3_FIND_VIRTUALENV
THEROCK_SOURCE_DIR
THEROCK_BINARY_DIR
THEROCK_BUILD_TESTING
ROCM_SYMLINK_LIBS
# RPATH handling.
THEROCK_NO_INSTALL_RPATH
THEROCK_PRIVATE_INSTALL_RPATH_DIRS
THEROCK_INSTALL_RPATH_EXECUTABLE_DIR
THEROCK_INSTALL_RPATH_LIBRARY_DIR
# Debug info handling.
THEROCK_SPLIT_DEBUG_INFO
)
# Some sub-projects do not react well to not having any GPU targets to build.
# In this case, we build them with a default target. This should only happen
# with target filtering for non-production, single target builds, and we will
# warn about it.
set(THEROCK_SUBPROJECTS_REQUIRING_DEFAULT_GPU_TARGETS hipBLASLt)
set(THEROCK_DEFAULT_GPU_TARGETS "gfx1100")
set_property(GLOBAL PROPERTY THEROCK_SUBPROJECT_COMPILE_COMMANDS_FILES)
if(CMAKE_C_VISIBILITY_PRESET)
list(APPEND THEROCK_DEFAULT_CMAKE_VARS ${CMAKE_C_VISIBILITY_PRESET})
endif()
if(CMAKE_CXX_VISIBILITY_PRESET)
list(APPEND THEROCK_DEFAULT_CMAKE_VARS ${CMAKE_CXX_VISIBILITY_PRESET})
endif()
# CXX flags that we hard-code in the toolchain file when building projects
# that use amd-llvm. In these cases, because it is our built toolchain, we
# don't need to probe warning flag availability and just have a hard-coded
# list. We only squelch warnings here that do not signal code correctness
# issues.
# TODO: Clean up warning flags (https://github.com/ROCm/TheRock/issues/47)
set(THEROCK_AMD_LLVM_DEFAULT_CXX_FLAGS
-Wno-documentation-unknown-command
-Wno-documentation-pedantic
-Wno-unused-command-line-argument
)
# Generates a command prefix that can be prepended to any custom command line
# to perform log/console redirection and pretty printing.
# LOG_FILE: If given, command output will also be sent to this log file. If
# not absolute, it will be made absolute relative to logs/ in the project
# binary directory.
# OUTPUT_ON_FAILURE: Boolean value to indicate whether output should go to the
# console only on failure.
# LABEL: Label to prefix console output with.
#
# This uses the build_tools/teatime.py script for output management. See that
# script for further details. One thing to note: if TEATIME_LABEL_GH_GROUP=1
# in the environment, console output will be formatted with GitHub action
# begin/end group markers vs log line prefixes. Generally, you want to set
# this in CI jobs.
function(therock_subproject_log_command out_var)
cmake_parse_arguments(
PARSE_ARGV 1 ARG
""
"LOG_FILE;LABEL;OUTPUT_ON_FAILURE"
""
)
set(command
"${Python3_EXECUTABLE}"
"${THEROCK_SOURCE_DIR}/build_tools/teatime.py"
"--log-timestamps"
)
if(ARG_LABEL)
list(APPEND command "--label" "${ARG_LABEL}")
endif()
if(ARG_OUTPUT_ON_FAILURE)
list(APPEND command "--no-interactive")
else()
list(APPEND command "--interactive")
endif()
if(ARG_LOG_FILE)
cmake_path(ABSOLUTE_PATH ARG_LOG_FILE BASE_DIRECTORY "${THEROCK_BINARY_DIR}/logs")
list(APPEND command "${ARG_LOG_FILE}")
endif()
list(APPEND command "--")
set("${out_var}" "${command}" PARENT_SCOPE)
endfunction()
# therock_subproject_fetch
# Fetches arbitrary content. This mostly defers to ExternalProject_Add to get
# content but it performs no actual building.
# All unrecognized options are passed to ExternalProject_Add.
# This can interoperate with therock_cmake_subproject_declare by adding the
# CMAKE_PROJECT option, which makes the CMakeLists.txt in the archive visible
# to CMake (which the subproject depends on). Additional touch byproducts
# can be generated with TOUCH.
function(therock_subproject_fetch target_name)
cmake_parse_arguments(
PARSE_ARGV 1 ARG
"CMAKE_PROJECT"
"SOURCE_DIR;PREFIX;EXCLUDE_FROM_ALL"
"TOUCH"
)
if(NOT DEFINED ARG_EXCLUDE_FROM_ALL)
set(ARG_EXCLUDE_FROM_ALL TRUE)
endif()
if(NOT DEFINED ARG_PREFIX)
set(ARG_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_fetch")
endif()
if(NOT DEFINED ARG_SOURCE_DIR)
set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/source")
endif()
set(_extra)
# In order to interop with therock_cmake_subproject_declare, the CMakeLists.txt
# file must exist so we mark this as a by-product. This serves as the dependency
# anchor and causes proper ordering of fetch->configure.
if(ARG_CMAKE_PROJECT)
list(APPEND ARG_TOUCH "${ARG_SOURCE_DIR}/CMakeLists.txt")
endif()
if(ARG_TOUCH)
list(APPEND _extra
BUILD_COMMAND "${CMAKE_COMMAND}" -E touch ${ARG_TOUCH}
BUILD_BYPRODUCTS ${ARG_TOUCH}
)
else()
list(APPEND _extra "BUILD_COMMAND" "")
endif()
ExternalProject_Add(
"${target_name}"
EXCLUDE_FROM_ALL "${ARG_EXCLUDE_FROM_ALL}"
PREFIX "${ARG_PREFIX}"
DOWNLOAD_NO_PROGRESS ON
LOG_DOWNLOAD ON
LOG_MERGED_STDOUTERR ON
LOG_OUTPUT_ON_FAILURE ON
SOURCE_DIR "${ARG_SOURCE_DIR}"
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
${_extra}
${ARG_UNPARSED_ARGUMENTS}
)
endfunction()
# therock_cmake_subproject_declare
# This declares a cmake based subproject by setting a number of key properties
# and setting up boiler-plate targets.
#
# Arguments:
# NAME: Globally unique subproject name. This will become the stem of various
# targets and therefore must be unique (even for nested projects) and a valid
# target identifier.
# ACTIVATE: Option to signify that this call should end by calling
# therock_cmake_subproject_activate. Do not specify this option if wishing to
# further configure the sub-project.
# NO_MERGE_COMPILE_COMMANDS: Option to disable merging of this project's
# compile_commands.json into the overall project. This is useful for
# third-party projects that are excluded from all as it eliminates a
# dependency that forces them to be downloaded/built.
# SOURCE_DIR: Absolute path to the external source directory.
# DIR_PREFIX: By default, directories named "build", "stage", "stamp" are
# created. But if there are multiple sub-projects in a parent dir, then they
# all must have a distinct prefix (not recommended).
# INSTALL_DESTINATION: Sub-directory within the stage/dist directory where this
# sub-project installs. Defaults to empty, meaning that it installs at the top
# of the namespace.
# CMAKE_ARGS: Additional CMake configure arguments.
# BUILD_DEPS: Projects which must build and provide their packages prior to this
# one.
# RUNTIME_DEPS: Projects which must build prior to this one and whose install
# files must be distributed with this project's artifacts in order to
# function.
# INTERFACE_LINK_DIRS: Relative paths within the install tree which dependent
# sub-projects must add to their runtime link library path.
# INTERFACE_PROGRAM_DIRS: Relative paths within the install tree which
# dependent sub-projects must add to their program search path.
# INTERFACE_PKG_CONFIG_DIRS: Relative paths within the install tree which
# dependent sub-projects must add to their PKG_CONFIG_PATH.
# IGNORE_PACKAGES: List of find_package package names to ignore, even if they
# are advertised by the super-project. These packages will always fall-through
# to the system resolver.
# COMPILER_TOOLCHAIN: Uses a built compiler toolchain instead of the
# super-project specified C/C++ compiler. This will add an implicit dep on
# the named compiler sub-project and reconfigure CMAKE_C(XX)_COMPILER options.
# Only a fixed set of supported toolchains are supported (currently
# "amd-llvm").
# BACKGROUND_BUILD: Option to indicate that the subproject does low concurrency,
# high latency build steps. It will be run in the backgroun in a job pool that
# allows some overlapping of work (controlled by
# THEROCK_BACKGROUND_BUILD_JOBS).
# CMAKE_LISTS_RELPATH: Relative path within the source directory to the
# CMakeLists.txt.
# EXTRA_DEPENDS: Extra target dependencies to add to the configure command.
# OUTPUT_ON_FAILURE: If given, build commands will produce no output unless if
# it fails (logs will still be written). While generally not good to squelch a
# "chatty" build, some third party libraries are hopeless and provide little
# signal.
#
# RPATH handling:
# Each subproject has default logic injected which configures the INSTALL_RPATH
# of any defined executable or shared library targets. This default behavior can
# be disabled by setting NO_INSTALL_RPATH.
# *IMPORTANT:* This *overrides* any project local install RPATH configuration.
# While it may seem that this is heavy handed, in practice, almost no library
# on its own does the right thing. If it does, opt it out.
#
# In order to compute a correct RPATH (which we always set as relative to
# the installation prefix), it must be possible to determine each target's
# ORIGIN, as the OS will see it in the install tree. CMake does not have a
# way to determine this, so we use the following heuristic:
# * Use THEROCK_INSTALL_RPATH_ORIGIN target property if defined.
# * For executables, use the project level THEROCK_INSTALL_RPATH_EXECUTABLE_DIR.
# * For shared libraries, use the project level THEROCK_INSTALL_RPATH_LIBRARY_DIR.
#
# We then get the computed private install RPATH dirs (which is the combination
# of any transitive INTERFACE_INSTALL_RPATH_DIRS) and transform them to an
# origin relative path and set them on the INSTALL_RPATH property.
#
# INSTALL_RPATH_DIRS: Install-tree relative paths to runtime shared library
# dependencies to be used for targets defined directly in this project.
# INTERFACE_INSTALL_RPATH_DIRS: Like INSTALL_RPATH_DIRS but advertises these
# directories to dependent projects (but does not use them itself).
# INSTALL_RPATH_EXECUTABLE_DIR: Default install-tree relative path to assume
# that all executables are installed to. Defaults to INSTALL_DESTINATION/bin.
# Can be overriden on a per target basis by setting
# THEROCK_INSTALL_RPATH_EXECUTABLE_DIR.
# INSTALL_RPATH_LIBRARY_DIR: Default install-tree relative path to assume
# that all shared libraries are installed to. Defaults to
# INSTALL_DESTINATION/lib. Can be overriden on a per target basis by setting
# THEROCK_INSTALL_RPATH_LIBRARY_DIR.
function(therock_cmake_subproject_declare target_name)
cmake_parse_arguments(
PARSE_ARGV 1 ARG
"ACTIVATE;EXCLUDE_FROM_ALL;BACKGROUND_BUILD;NO_MERGE_COMPILE_COMMANDS;OUTPUT_ON_FAILURE;NO_INSTALL_RPATH"
"EXTERNAL_SOURCE_DIR;BINARY_DIR;DIR_PREFIX;INSTALL_DESTINATION;COMPILER_TOOLCHAIN;INTERFACE_PROGRAM_DIRS;CMAKE_LISTS_RELPATH;INTERFACE_PKG_CONFIG_DIRS;INSTALL_RPATH_EXECUTABLE_DIR;INSTALL_RPATH_LIBRARY_DIR"
"BUILD_DEPS;RUNTIME_DEPS;CMAKE_ARGS;INTERFACE_LINK_DIRS;IGNORE_PACKAGES;EXTRA_DEPENDS;INSTALL_RPATH_DIRS;INTERFACE_INSTALL_RPATH_DIRS"
)
if(TARGET "${target_name}")
message(FATAL_ERROR "Cannot declare subproject '${target_name}': a target with that name already exists")
endif()
cmake_path(IS_ABSOLUTE ARG_EXTERNAL_SOURCE_DIR _source_is_absolute)
if(_source_is_absolute)
if(NOT ARG_BINARY_DIR)
# TODO: Swap these lines once moved.
set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
# message(FATAL_ERROR "If specifying an absolute SOURCE_DIR, BINARY_DIR must be specified")
endif()
else()
if(NOT ARG_BINARY_DIR)
set(ARG_BINARY_DIR "${ARG_EXTERNAL_SOURCE_DIR}")
endif()
cmake_path(ABSOLUTE_PATH ARG_EXTERNAL_SOURCE_DIR)
cmake_path(ABSOLUTE_PATH ARG_BINARY_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endif()
set(_cmake_source_dir "${ARG_EXTERNAL_SOURCE_DIR}")
if(ARG_CMAKE_LISTS_RELPATH)
cmake_path(APPEND _cmake_source_dir "${ARG_CMAKE_LISTS_RELPATH}")
endif()
message(STATUS "Including subproject ${target_name} (from ${_cmake_source_dir})")
add_custom_target("${target_name}" COMMENT "Top level target to build the ${target_name} sub-project")
# Build directory.
set(_binary_dir "${ARG_BINARY_DIR}/${ARG_DIR_PREFIX}build")
make_directory("${_binary_dir}")
# Stage directory.
set(_stage_dir "${ARG_BINARY_DIR}/${ARG_DIR_PREFIX}stage")
make_directory("${_stage_dir}")
# Dist directory.
set(_dist_dir "${ARG_BINARY_DIR}/${ARG_DIR_PREFIX}dist")
make_directory("${_dist_dir}")
# Stamp directory.
set(_stamp_dir "${ARG_BINARY_DIR}/${ARG_DIR_PREFIX}stamp")
make_directory("${_stamp_dir}")
# Collect LINK_DIRS and PROGRAM_DIRS from explicit args and RUNTIME_DEPS.
_therock_cmake_subproject_collect_runtime_deps(
_private_link_dirs _private_program_dirs _private_pkg_config_dirs _interface_install_rpath_dirs
_transitive_runtime_deps
_transitive_configure_depend_files
${ARG_RUNTIME_DEPS})
# Link dirs
set(_declared_link_dirs "${ARG_INTERFACE_LINK_DIRS}")
_therock_cmake_subproject_absolutize(_declared_link_dirs "${_stage_dir}")
# The link dirs that we advertise combine interface link dirs of runtime deps
# and any that we declared.
set(_interface_link_dirs ${_private_link_dirs} ${_declared_link_dirs})
# Program dirs
# Collect program dirs from explicit args and RUNTIME_DEPS.
set(_declared_program_dirs "${ARG_INTERFACE_PROGRAM_DIRS}")
_therock_cmake_subproject_absolutize(_declared_program_dirs "${_dist_dir}")
# The program dirs that we advertise combine interface program dirs of
# runtime deps and any that we declared.
set(_interface_program_dirs ${_private_program_dirs} ${_declared_program_dirs})
# PkgConfig dirs
set(_declared_pkg_config_dirs "${ARG_INTERFACE_PKG_CONFIG_DIRS}")
_therock_cmake_subproject_absolutize(_declared_pkg_config_dirs "${_stage_dir}")
set(_interface_pkg_config_dirs ${_private_pkg_config_dirs} ${_declared_pkg_config_dirs})
# Install RPATH dirs.
set(_interface_install_rpath_dirs ${_interface_install_rpath_dirs} ${ARG_INTERFACE_INSTALL_RPATH_DIRS})
set(_private_install_rpath_dirs ${ARG_INSTALL_RPATH_DIRS} ${_interface_install_rpath_dirs})
# Dedup transitives.
list(REMOVE_DUPLICATES _private_link_dirs)
list(REMOVE_DUPLICATES _interface_link_dirs)
list(REMOVE_DUPLICATES _private_program_dirs)
list(REMOVE_DUPLICATES _interface_program_dirs)
list(REMOVE_DUPLICATES _transitive_runtime_deps)
list(REMOVE_DUPLICATES _transitive_configure_depend_files)
list(REMOVE_DUPLICATES _private_pkg_config_dirs)
list(REMOVE_DUPLICATES _interface_pkg_config_dirs)
list(REMOVE_DUPLICATES _interface_install_rpath_dirs)
list(REMOVE_DUPLICATES _private_install_rpath_dirs)
# RPATH Executable and Library dir.
if(NOT ARG_INSTALL_RPATH_EXECUTABLE_DIR)
if(ARG_INSTALL_DESTINATION)
set(ARG_INSTALL_RPATH_EXECUTABLE_DIR ARG_INSTALL_DESTINATION)
cmake_path(APPEND ARG_INSTALL_RPATH_EXECUTABLE_DIR "bin")
else()
set(ARG_INSTALL_RPATH_EXECUTABLE_DIR "bin")
endif()
endif()
if(NOT ARG_INSTALL_RPATH_LIBRARY_DIR)
if(ARG_INSTALL_DESTINATION)
set(ARG_INSTALL_RPATH_LIBRARY_DIR ARG_INSTALL_DESTINATION)
cmake_path(APPEND ARG_INSTALL_RPATH_EXECUTABLE_DIR "lib")
else()
set(ARG_INSTALL_RPATH_LIBRARY_DIR "lib")
endif()
endif()
# Build pool determination.
set(_build_pool)
if(ARG_BACKGROUND_BUILD)
set(_build_pool "therock_background")
endif()
set_target_properties("${target_name}" PROPERTIES
THEROCK_SUBPROJECT cmake
THEROCK_BUILD_POOL "${_build_pool}"
THEROCK_EXCLUDE_FROM_ALL "${ARG_EXCLUDE_FROM_ALL}"
THEROCK_NO_MERGE_COMPILE_COMMANDS "${ARG_NO_MERGE_COMPILE_COMMANDS}"
THEROCK_EXTERNAL_SOURCE_DIR "${ARG_EXTERNAL_SOURCE_DIR}"
THEROCK_BINARY_DIR "${_binary_dir}"
THEROCK_DIST_DIR "${_dist_dir}"
THEROCK_STAGE_DIR "${_stage_dir}"
THEROCK_INSTALL_DESTINATION "${ARG_INSTALL_DESTINATION}"
THEROCK_STAMP_DIR "${_stamp_dir}"
THEROCK_CMAKE_SOURCE_DIR "${_cmake_source_dir}"
THEROCK_CMAKE_PROJECT_INIT_FILE "${ARG_BINARY_DIR}/${ARG_BUILD_DIR}_init.cmake"
THEROCK_CMAKE_PROJECT_TOOLCHAIN_FILE "${ARG_BINARY_DIR}/${ARG_BUILD_DIR}_toolchain.cmake"
THEROCK_CMAKE_ARGS "${ARG_CMAKE_ARGS}"
# Non-transitive build deps.
THEROCK_BUILD_DEPS "${ARG_BUILD_DEPS}"
# Transitive runtime deps.
THEROCK_RUNTIME_DEPS "${_transitive_runtime_deps}"
# That this project compiles with.
THEROCK_PRIVATE_LINK_DIRS "${_private_link_dirs}"
# Link dirs that are advertised to dependents
THEROCK_INTERFACE_LINK_DIRS "${_interface_link_dirs}"
# PkgConfig directories that this project must use.
THEROCK_PRIVATE_PKG_CONFIG_DIRS "${_private_pkg_config_dirs}"
# Directories that sub-projects must add to their PKG_CONFIG_PATH.
THEROCK_INTERFACE_PKG_CONFIG_DIRS "${_interface_pkg_config_dirs}"
# Program dirs that this sub-project must configure with.
THEROCK_PRIVATE_PROGRAM_DIRS "${_private_program_dirs}"
# Program dirs that are advertised to dependents.
THEROCK_INTERFACE_PROGRAM_DIRS "${_interface_program_dirs}"
THEROCK_IGNORE_PACKAGES "${ARG_IGNORE_PACKAGES}"
THEROCK_COMPILER_TOOLCHAIN "${ARG_COMPILER_TOOLCHAIN}"
# Any extra depend files that must be added to the configure phase of dependents.
THEROCK_INTERFACE_CONFIGURE_DEPEND_FILES "${_transitive_configure_depend_files}"
THEROCK_EXTRA_DEPENDS "${ARG_EXTRA_DEPENDS}"
THEROCK_OUTPUT_ON_FAILURE "${ARG_OUTPUT_ON_FAILURE}"
# RPATH
THEROCK_NO_INSTALL_RPATH "${ARG_NO_INSTALL_RPATH}"
THEROCK_INTERFACE_INSTALL_RPATH_DIRS "${_interface_install_rpath_dirs}"
THEROCK_PRIVATE_INSTALL_RPATH_DIRS "${_private_install_rpath_dirs}"
THEROCK_INSTALL_RPATH_EXECUTABLE_DIR "${ARG_INSTALL_RPATH_EXECUTABLE_DIR}"
THEROCK_INSTALL_RPATH_LIBRARY_DIR "${ARG_INSTALL_RPATH_LIBRARY_DIR}"
)
if(ARG_ACTIVATE)
therock_cmake_subproject_activate("${target_name}")
endif()
endfunction()
# therock_cmake_subproject_provide_package
# Declares that a subproject provides a given package which should be findable
# with `find_package(package_name)` at the given path relative to its install
# directory.
function(therock_cmake_subproject_provide_package target_name package_name relative_path)
string(APPEND CMAKE_MESSAGE_INDENT " ")
get_target_property(_existing_packages "${target_name}" THEROCK_PROVIDE_PACKAGES)
if(${package_name} IN_LIST _existing_packages)
message(FATAL_ERROR "Package defined multiple times on sub-project ${target_name}: ${package_name}")
endif()
set_property(TARGET "${target_name}" APPEND PROPERTY THEROCK_PROVIDE_PACKAGES "${package_name}")
set(_relpath_name THEROCK_PACKAGE_RELPATH_${package_name})
set_property(TARGET "${target_name}" PROPERTY ${_relpath_name} "${relative_path}")
if(THEROCK_VERBOSE)
message(STATUS "PROVIDE ${package_name} = ${relative_path} (from ${target_name})")
endif()
endfunction()
# therock_cmake_subproject_activate
# If using multi-step setup (i.e. without 'ACTIVATE' on the declare), then this
# must be called once all configuration is complete.
function(therock_cmake_subproject_activate target_name)
_therock_assert_is_cmake_subproject("${target_name}")
# Get properties.
get_target_property(_binary_dir "${target_name}" THEROCK_BINARY_DIR)
get_target_property(_build_deps "${target_name}" THEROCK_BUILD_DEPS)
get_target_property(_build_pool "${target_name}" THEROCK_BUILD_POOL)
get_target_property(_compiler_toolchain "${target_name}" THEROCK_COMPILER_TOOLCHAIN)
get_target_property(_transitive_configure_depend_files "${target_name}" THEROCK_INTERFACE_CONFIGURE_DEPEND_FILES)
get_target_property(_dist_dir "${target_name}" THEROCK_DIST_DIR)
get_target_property(_runtime_deps "${target_name}" THEROCK_RUNTIME_DEPS)
get_target_property(_cmake_args "${target_name}" THEROCK_CMAKE_ARGS)
get_target_property(_cmake_project_init_file "${target_name}" THEROCK_CMAKE_PROJECT_INIT_FILE)
get_target_property(_cmake_project_toolchain_file "${target_name}" THEROCK_CMAKE_PROJECT_TOOLCHAIN_FILE)
get_target_property(_cmake_source_dir "${target_name}" THEROCK_CMAKE_SOURCE_DIR)
get_target_property(_exclude_from_all "${target_name}" THEROCK_EXCLUDE_FROM_ALL)
get_target_property(_external_source_dir "${target_name}" THEROCK_EXTERNAL_SOURCE_DIR)
get_target_property(_extra_depends "${target_name}" THEROCK_EXTRA_DEPENDS)
get_target_property(_ignore_packages "${target_name}" THEROCK_IGNORE_PACKAGES)
get_target_property(_install_destination "${target_name}" THEROCK_INSTALL_DESTINATION)
get_target_property(_no_merge_compile_commands "${target_name}" THEROCK_NO_MERGE_COMPILE_COMMANDS)
get_target_property(_private_link_dirs "${target_name}" THEROCK_PRIVATE_LINK_DIRS)
get_target_property(_private_pkg_config_dirs "${target_name}" THEROCK_PRIVATE_PKG_CONFIG_DIRS)
get_target_property(_private_program_dirs "${target_name}" THEROCK_PRIVATE_PROGRAM_DIRS)
get_target_property(_stage_dir "${target_name}" THEROCK_STAGE_DIR)
get_target_property(_sources "${target_name}" SOURCES)
get_target_property(_stamp_dir "${target_name}" THEROCK_STAMP_DIR)
get_target_property(_output_on_failure "${target_name}" THEROCK_OUTPUT_ON_FAILURE)
# RPATH properties: just mirror these to same named variables because we just
# mirror them syntactically into the subprojet..
get_target_property(THEROCK_NO_INSTALL_RPATH "${target_name}" THEROCK_NO_INSTALL_RPATH)
get_target_property(THEROCK_INTERFACE_INSTALL_RPATH_DIRS "${target_name}" THEROCK_INTERFACE_INSTALL_RPATH_DIRS)
get_target_property(THEROCK_PRIVATE_INSTALL_RPATH_DIRS "${target_name}" THEROCK_PRIVATE_INSTALL_RPATH_DIRS)
get_target_property(THEROCK_INSTALL_RPATH_EXECUTABLE_DIR "${target_name}" THEROCK_INSTALL_RPATH_EXECUTABLE_DIR)
get_target_property(THEROCK_INSTALL_RPATH_LIBRARY_DIR "${target_name}" THEROCK_INSTALL_RPATH_LIBRARY_DIR)
# Handle optional properties.
if(NOT _sources)
set(_sources)
endif()
# Defaults.
set(_configure_comment_suffix)
set(_build_comment_suffix)
# Detect pre/post hooks.
set(_pre_hook_path "${CMAKE_CURRENT_SOURCE_DIR}/pre_hook_${target_name}.cmake")
if(NOT EXISTS "${_pre_hook_path}")
set(_pre_hook_path)
endif()
set(_post_hook_path "${CMAKE_CURRENT_SOURCE_DIR}/post_hook_${target_name}.cmake")
if(NOT EXISTS "${_post_hook_path}")
set(_post_hook_path)
endif()
# Report transitive runtime deps.
if(_runtime_deps AND THEROCK_VERBOSE)
list(JOIN _runtime_deps " " _runtime_deps_pretty)
message(STATUS " RUNTIME_DEPS: ${_runtime_deps_pretty}")
endif()
get_property(_mirror_cmake_vars GLOBAL PROPERTY THEROCK_DEFAULT_CMAKE_VARS)
# Handle compiler toolchain.
set(_compiler_toolchain_addl_depends)
set(_compiler_toolchain_init_contents)
set(_build_env_pairs)
_therock_cmake_subproject_setup_toolchain("${target_name}"
"${_compiler_toolchain}" "${_cmake_project_toolchain_file}")
# Customize any other super-project CMake variables that are captured by
# _init.cmake.
if(_private_program_dirs)
set(CMAKE_PROGRAM_PATH ${_private_program_dirs} ${CMAKE_PROGRAM_PATH})
if(THEROCK_VERBOSE)
foreach(_message_contents ${_private_program_dirs})
message(STATUS " PROGRAM_DIR: ${_message_contents}")
endforeach()
endif()
endif()
# Generate the project_init.cmake
set(_dep_provider_file)
if(_build_deps OR _runtime_deps)
set(_dep_provider_file "${THEROCK_SOURCE_DIR}/cmake/therock_subproject_dep_provider.cmake")
endif()
set(_init_contents)
foreach(_var_name ${_mirror_cmake_vars})
string(APPEND _init_contents "set(${_var_name} \"@${_var_name}@\" CACHE STRING \"\" FORCE)\n")
endforeach()
# Process dependencies. We process runtime deps first so that they take precedence
# over build deps (first wins). Both come from the dist directory because if
# build tools are needed from them, only the dist dir is guaranteed to have
# all runtime deps met.
string(APPEND _init_contents "set(THEROCK_PROVIDED_PACKAGES)\n")
set(_deps_contents)
set(_deps_provided)
_therock_cmake_subproject_setup_deps(_deps_contents _deps_provided THEROCK_DIST_DIR ${_runtime_deps})
_therock_cmake_subproject_setup_deps(_deps_contents _deps_provided THEROCK_DIST_DIR ${_build_deps})
string(APPEND _init_contents "${_deps_contents}")
string(APPEND _init_contents "set(THEROCK_IGNORE_PACKAGES \"@_ignore_packages@\")\n")
string(APPEND _init_contents "list(PREPEND CMAKE_MODULE_PATH \"${THEROCK_SOURCE_DIR}/cmake/finders\")\n")
if(WIN32)
# Windows currently relies on some prebuilt toolchain components from the
# HIP SDK. As part of https://github.com/ROCm/TheRock/issues/36 we should
# be able to satisfy find_package(HIP) via the toolchain.
file(TO_CMAKE_PATH "$ENV{HIP_PATH}" HIP_DIR)
string(APPEND _init_contents "string(APPEND CMAKE_PREFIX_PATH \"${HIP_DIR}\")\n")
endif()
foreach(_private_link_dir ${_private_link_dirs})
if(THEROCK_VERBOSE)
message(STATUS " LINK_DIR: ${_private_link_dir}")
endif()
if(NOT MSVC)
# The normal way.
string(APPEND _init_contents "string(APPEND CMAKE_EXE_LINKER_FLAGS \" -L ${_private_link_dir} -Wl,-rpath-link,${_private_link_dir}\")\n")
string(APPEND _init_contents "string(APPEND CMAKE_SHARED_LINKER_FLAGS \" -L ${_private_link_dir} -Wl,-rpath-link,${_private_link_dir}\")\n")
else()
# The MSVC way.
string(APPEND _init_contents "string(APPEND CMAKE_EXE_LINKER_FLAGS \" /LIBPATH:${_private_link_dir}\")\n")
string(APPEND _init_contents "string(APPEND CMAKE_SHARED_LINKER_FLAGS \" /LIBPATH:${_private_link_dir}\")\n")
endif()
endforeach()
if(THEROCK_VERBOSE AND _private_pkg_config_dirs)
message(STATUS " PKG_CONFIG_DIRS: ${_private_pkg_config_dirs}")
endif()
string(APPEND _init_contents "set(THEROCK_PKG_CONFIG_DIRS \"@_private_pkg_config_dirs@\")\n")
string(APPEND _init_contents "${_compiler_toolchain_init_contents}")
if(_dep_provider_file)
string(APPEND _init_contents "include(${_dep_provider_file})\n")
endif()
if(_pre_hook_path)
string(APPEND _init_contents "include(@_pre_hook_path@)\n")
endif()
string(APPEND _init_contents "set(THEROCK_USER_POST_HOOK)\n")
if(_post_hook_path)
string(APPEND _init_contents "set(THEROCK_USER_POST_HOOK \"@_post_hook_path@\")\n")
endif()
set(_global_post_include "${THEROCK_SOURCE_DIR}/cmake/therock_global_post_subproject.cmake")
string(APPEND _init_contents "cmake_language(DEFER CALL include \"@_global_post_include@\")\n")
file(CONFIGURE OUTPUT "${_cmake_project_init_file}" CONTENT "${_init_contents}" @ONLY ESCAPE_QUOTES)
# Transform build and run deps from target form (i.e. 'ROCR-Runtime' to a dependency
# on the dist.stamp file). These are a dependency for configure. We satisfy both
# build and runtime deps from the dist phase because even build-only deps may
# need to execute tools linked such that they require all transitive libraries
# materialized. We might be able to save some milliseconds by steering
# build-only deps to the stage.stamp file, but the complexity involved is not
# worth it, especially considering that it increases the likelihood of build
# non-determinism.
set(_configure_dep_stamps)
_therock_cmake_subproject_deps_to_stamp(_configure_dep_stamps dist.stamp ${_build_deps})
_therock_cmake_subproject_deps_to_stamp(_configure_dep_stamps dist.stamp ${_runtime_deps})
# Target flags.
set(_all_option)
if(NOT _exclude_from_all)
set(_all_option "ALL")
endif()
# configure target
if(THEROCK_VERBOSE)
message(STATUS " CONFIGURE_DEPENDS: ${_transitive_configure_depend_files} ")
endif()
set(_configure_stamp_file "${_stamp_dir}/configure.stamp")
set(_configure_comment_suffix " (in background)")
set(_terminal_option)
set(_build_terminal_option "USES_TERMINAL")
if("$ENV{THEROCK_INTERACTIVE}")
set(_terminal_option "USES_TERMINAL")
set(_configure_comment_suffix)
elseif(_build_pool)
if(THEROCK_VERBOSE)
message(STATUS " JOB_POOL: ${_build_pool}")
endif()
set(_build_terminal_option JOB_POOL "${_build_pool}")
set(_build_comment_suffix " (in background)")
endif()
set(_stage_destination_dir "${_stage_dir}")
if(_install_destination)
cmake_path(APPEND _stage_destination_dir "${_install_destination}")
endif()
set(_compile_commands_file "${PROJECT_BINARY_DIR}/compile_commands_fragment_${target_name}.json")
therock_subproject_log_command(_configure_log_prefix
LOG_FILE "${target_name}_configure.log"
LABEL "${target_name} configure"
OUTPUT_ON_FAILURE "${_output_on_failure}"
)
add_custom_command(
OUTPUT "${_configure_stamp_file}"
COMMAND
${_configure_log_prefix}
"${CMAKE_COMMAND}"
"-G${CMAKE_GENERATOR}"
"-B${_binary_dir}"
"-S${_cmake_source_dir}"
"-DCMAKE_INSTALL_PREFIX=${_stage_destination_dir}"
"-DTHEROCK_STAGE_INSTALL_ROOT=${_stage_dir}"
"-DCMAKE_TOOLCHAIN_FILE=${_cmake_project_toolchain_file}"
"-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=${_cmake_project_init_file}"
${_cmake_args}
# CMake doesn't always generate a compile_commands.json so touch one to keep
# the build graph sane.
COMMAND "${CMAKE_COMMAND}" -E touch "${_binary_dir}/compile_commands.json"
COMMAND "${CMAKE_COMMAND}" -E touch "${_configure_stamp_file}"
COMMAND "${CMAKE_COMMAND}" -E copy "${_binary_dir}/compile_commands.json" "${_compile_commands_file}"
WORKING_DIRECTORY "${_binary_dir}"
COMMENT "Configure sub-project ${target_name}${_configure_comment_suffix}"
${_terminal_option}
BYPRODUCTS
"${_binary_dir}/CMakeCache.txt"
"${_binary_dir}/cmake_install.cmake"
"${_compile_commands_file}"
DEPENDS
"${_cmake_source_dir}/CMakeLists.txt"
"${_cmake_project_toolchain_file}"
"${_cmake_project_init_file}"
"${_global_post_include}"
${_extra_depends}
${_dep_provider_file}
${_configure_dep_stamps}
${_pre_hook_path}
${_post_hook_path}
${_compiler_toolchain_addl_depends}
${_transitive_configure_depend_files}
# TODO: Have a mechanism for adding more depends for better rebuild ergonomics
)
add_custom_target(
"${target_name}+configure"
${_all_option}
DEPENDS "${_configure_stamp_file}"
)
add_dependencies("${target_name}" "${target_name}+configure")
if(NOT _no_merge_compile_commands)
set_property(GLOBAL APPEND PROPERTY THEROCK_SUBPROJECT_COMPILE_COMMANDS_FILES
"${_compile_commands_file}"
)
endif()
# build target.
therock_subproject_log_command(_build_log_prefix
LOG_FILE "${target_name}_build.log"
LABEL "${target_name}"
OUTPUT_ON_FAILURE "${_output_on_failure}"
)
set(_build_stamp_file "${_stamp_dir}/build.stamp")
add_custom_command(
OUTPUT "${_build_stamp_file}"
COMMAND
${_build_log_prefix}
"${CMAKE_COMMAND}" -E env ${_build_env_pairs} --
"${CMAKE_COMMAND}" "--build" "${_binary_dir}"
COMMAND "${CMAKE_COMMAND}" -E touch "${_build_stamp_file}"
WORKING_DIRECTORY "${_binary_dir}"
COMMENT "Building sub-project ${target_name}${_build_comment_suffix}"
${_build_terminal_option}
DEPENDS
"${_configure_stamp_file}"
${_sources}
)
add_custom_target(
"${target_name}+build"
${_all_option}
DEPENDS
"${_build_stamp_file}"
)
add_dependencies("${target_name}" "${target_name}+build")
# stage install target.
set(_install_strip_option)
if(THEROCK_SPLIT_DEBUG_INFO)
set(_install_strip_option "--strip")
endif()
therock_subproject_log_command(_install_log_prefix
LOG_FILE "${target_name}_install.log"
LABEL "${target_name} install"
# While useful for debugging, stage install logs are almost pure noise
# for interactive use.
OUTPUT_ON_FAILURE ON
)
set(_stage_stamp_file "${_stamp_dir}/stage.stamp")
add_custom_command(
OUTPUT "${_stage_stamp_file}"
COMMAND ${_install_log_prefix} "${CMAKE_COMMAND}" --install "${_binary_dir}" ${_install_strip_option}
COMMAND "${CMAKE_COMMAND}" -E touch "${_stage_stamp_file}"
WORKING_DIRECTORY "${_binary_dir}"
COMMENT "Stage installing sub-project ${target_name}"
${_terminal_option}
DEPENDS
"${_build_stamp_file}"
)
add_custom_target(
"${target_name}+stage"
${_all_option}
DEPENDS
"${_stage_stamp_file}"
)
add_dependencies("${target_name}" "${target_name}+stage")
# dist install target.
set(_dist_stamp_file "${_stamp_dir}/dist.stamp")
set(_fileset_tool "${THEROCK_SOURCE_DIR}/build_tools/fileset_tool.py")
_therock_cmake_subproject_get_stage_dirs(
_dist_source_dirs "${target_name}" ${_runtime_deps})
add_custom_command(
OUTPUT "${_dist_stamp_file}"
COMMAND "${Python3_EXECUTABLE}" "${_fileset_tool}" copy "${_dist_dir}" ${_dist_source_dirs}
COMMAND "${CMAKE_COMMAND}" -E touch "${_dist_stamp_file}"
COMMENT "Merging sub-project dist directory for ${target_name}"
${_terminal_option}
DEPENDS
"${_stage_stamp_file}"
"${_fileset_tool}"
)
add_custom_target(
"${target_name}+dist"
${_all_option}
DEPENDS
"${_dist_stamp_file}"
)
add_dependencies("${target_name}" "${target_name}+dist")
# expunge target
add_custom_target(
"${target_name}+expunge"
COMMAND
${CMAKE_COMMAND} -E rm -rf "${_binary_dir}" "${_stage_dir}" "${_stamp_dir}" "${_dist_dir}"
)
endfunction()
# therock_cmake_subproject_glob_c_sources
# Adds C/C++ sources from given project subdirectories to the list of sources for
# a sub-project. This allows the super-project build system to know when to
# re-trigger the build step of the sub-project. There are many issues with globs
# in CMake, but as an ergonomic win, this is deemed an acceptable compromise
# to a large degree of explicitness.
function(therock_cmake_subproject_glob_c_sources target_name)
cmake_parse_arguments(
PARSE_ARGV 1 ARG
""
""
"SUBDIRS"
)
get_target_property(_project_source_dir "${target_name}" THEROCK_EXTERNAL_SOURCE_DIR)
set(_globs)
foreach(_subdir ${ARG_SUBDIRS})
set(_s "${_project_source_dir}/${_subdir}")
list(APPEND _globs
"${_s}/*.h"
"${_s}/*.hpp"
"${_s}/*.inc"
"${_s}/*.cc"
"${_s}/*.cpp"
"${_s}/*.c"
)
endforeach()
file(GLOB_RECURSE _files LIST_DIRECTORIES FALSE
CONFIGURE_DEPENDS
${_globs}
)
target_sources("${target_name}" PRIVATE ${_files})
endfunction()
# Gets the dist/ directory for a sub-project.
function(therock_cmake_subproject_dist_dir out_var target_name)
_therock_assert_is_cmake_subproject("${target_name}")
get_target_property(_dir "${target_name}" THEROCK_DIST_DIR)
set("${out_var}" "${_dir}" PARENT_SCOPE)
endfunction()
# Merges all compile_commands.json files and exports them.
function(therock_subproject_merge_compile_commands)
if(NOT CMAKE_EXPORT_COMPILE_COMMANDS)
return()
endif()
message(STATUS "Setting up compile_commands.json export")
get_property(_fragment_files GLOBAL PROPERTY THEROCK_SUBPROJECT_COMPILE_COMMANDS_FILES)
if(EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json")
list(APPEND _fragment_files "${CMAKE_BINARY_DIR}/compile_commands.json")
endif()
set(_merged_file "${PROJECT_BINARY_DIR}/compile_commands_merged.json")
set(_merged_file_in_source_dir "${PROJECT_SOURCE_DIR}/compile_commands.json")
set(_merge_script "${THEROCK_SOURCE_DIR}/build_tools/merge_compile_commands.py")
add_custom_command(
OUTPUT "${_merged_file}"
COMMENT "Merging compile_commands.json"
COMMAND "${Python3_EXECUTABLE}"
"${_merge_script}" "${_merged_file}" ${_fragment_files}
COMMAND "${CMAKE_COMMAND}" -E copy "${_merged_file}" "${_merged_file_in_source_dir}"
BYPRODUCTS
"${_merged_file_in_source_dir}"
DEPENDS
"${_merge_script}"
${_fragment_files}
)
add_custom_target(therock_merged_compile_commands ALL
DEPENDS
"${_merged_file}"
"${_merge_script}"
${_fragment_files}
)
endfunction()
function(_therock_assert_is_cmake_subproject target_name)
# Make sure it is a sub-project.
get_target_property(_is_subproject "${target_name}" THEROCK_SUBPROJECT)
if(NOT _is_subproject STREQUAL "cmake")
message(FATAL_ERROR "Target ${target_name} is not a sub-project")
endif()
endfunction()
# Builds a CMake language fragment to set up a dependency provider such that
# it handles super-project provided dependencies locally.
function(_therock_cmake_subproject_setup_deps out_contents out_provided dep_dir_property)
string(APPEND CMAKE_MESSAGE_INDENT " ")
set(_contents "${${out_contents}}")
set(_already_provided ${${out_provided}})
foreach(dep_target ${ARGN})
_therock_assert_is_cmake_subproject("${dep_target}")
get_target_property(_provides "${dep_target}" THEROCK_PROVIDE_PACKAGES)
if(_provides)
foreach(_package_name ${_provides})
if(_package_name IN_LIST _already_provided)
continue()
endif()
list(APPEND _already_provided "${_package_name}")
get_target_property(_dep_dir "${dep_target}" "${dep_dir_property}")
set(_relpath_name THEROCK_PACKAGE_RELPATH_${_package_name})
get_target_property(_relpath "${dep_target}" ${_relpath_name})
if(NOT _dep_dir OR NOT _relpath)
message(FATAL_ERROR "Missing package info props for ${_package_name} on ${dep_target}: '${_dep_dir}' ${_relpath_name}='${_relpath}'")
endif()
set(_find_package_path "${_dep_dir}")
cmake_path(APPEND _find_package_path "${_relpath}")
if(THEROCK_VERBOSE)
message(STATUS "INJECT ${_package_name} = ${_find_package_path} (from ${dep_target})")
endif()
string(APPEND _contents "set(THEROCK_PACKAGE_DIR_${_package_name} \"${_find_package_path}\")\n")
string(APPEND _contents "list(APPEND THEROCK_PROVIDED_PACKAGES ${_package_name})\n")
endforeach()
endif()
endforeach()
set("${out_contents}" "${_contents}" PARENT_SCOPE)
set("${out_provided}" "${_already_provided}" PARENT_SCOPE)
endfunction()
# Gets the staging install directories for a list of subproject deps.
function(_therock_cmake_subproject_get_stage_dirs out_dirs)
set(_dirs)
foreach(target_name ${ARGN})
get_target_property(_stage_dir "${target_name}" THEROCK_STAGE_DIR)
if(NOT _stage_dir)
message(FATAL_ERROR "Sub-project target ${target_name} does not have a stage install dir")
endif()
list(APPEND _dirs "${_stage_dir}")
endforeach()
set(${out_dirs} "${_dirs}" PARENT_SCOPE)
endfunction()
# Transforms a list of sub-project targets to corresponding stamp files of
# `stamp_name`. These are the actual build system deps that are encoded in the
# commands (whereas the target names are just for humans).
function(_therock_cmake_subproject_deps_to_stamp out_stamp_files stamp_name)
set(_stamp_files ${${out_stamp_files}})
foreach(target_name ${ARGN})
_therock_assert_is_cmake_subproject("${target_name}")
get_target_property(_stamp_dir "${target_name}" THEROCK_STAMP_DIR)
if(NOT _stamp_dir)
message(FATAL_ERROR "Sub-project is missing a stamp dir: ${target_name}")
endif()
list(APPEND _stamp_files "${_stamp_dir}/${stamp_name}")
endforeach()
set(${out_stamp_files} "${_stamp_files}" PARENT_SCOPE)
endfunction()
# For a list of targets, gets absolute paths for all interface link directories
# and transitive runtime deps. Both lists may contain duplicates if the DAG
# includes the same dep multiple times.
function(_therock_cmake_subproject_collect_runtime_deps
out_link_dirs out_program_dirs out_pkg_config_dirs out_install_rpath_dirs
out_transitive_deps
out_transitive_configure_depend_files)
set(_install_rpath_dirs)
set(_link_dirs)
set(_program_dirs)
set(_pkg_config_dirs)
set(_transitive_deps)
set(_transitive_configure_depend_files)
foreach(target_name ${ARGN})
_therock_assert_is_cmake_subproject("${target_name}")
get_target_property(_declared_configure_depend_files "${target_name}" THEROCK_INTERFACE_CONFIGURE_DEPEND_FILES)
list(APPEND _transitive_configure_depend_files ${_declared_configure_depend_files})
get_target_property(_stamp_dir "${target_name}" THEROCK_STAMP_DIR)
# Link dirs.
get_target_property(_link_dir "${target_name}" THEROCK_INTERFACE_LINK_DIRS)
list(APPEND _link_dirs ${_link_dir})
# Transitive runtime target deps.
get_target_property(_deps "${target_name}" THEROCK_RUNTIME_DEPS)
list(APPEND _transitive_deps ${_deps} ${target_name})
# If we have program dirs, then this target's 'dist' phase has to become
# a transitive dep for all future configures (by default the build graph
# only depends on the 'stage' phase).
get_target_property(_program_dir "${target_name}" THEROCK_INTERFACE_PROGRAM_DIRS)
if(_program_dir)
list(APPEND _program_dirs ${_program_dir})
list(APPEND _transitive_configure_depend_files "${_stamp_dir}/dist.stamp")
endif()
# PkgConfig dirs.
get_target_property(_pkg_config_dir "${target_name}" THEROCK_INTERFACE_PKG_CONFIG_DIRS)
if(_pkg_config_dir)
list(APPEND _pkg_config_dirs ${_pkg_config_dir})
endif()
# RPATH dirs.
get_target_property(_install_rpath_dir "${target_name}" THEROCK_INTERFACE_INSTALL_RPATH_DIRS)
if(_install_rpath_dir)
list(APPEND _install_rpath_dirs ${_install_rpath_dir})
endif()
endforeach()
set("${out_install_rpath_dirs}" "${_install_rpath_dirs}" PARENT_SCOPE)
set("${out_link_dirs}" "${_link_dirs}" PARENT_SCOPE)
set("${out_program_dirs}" "${_program_dirs}" PARENT_SCOPE)
set("${out_pkg_config_dirs}" "${_pkg_config_dirs}" PARENT_SCOPE)
set("${out_transitive_deps}" "${_transitive_deps}" PARENT_SCOPE)
set("${out_transitive_configure_depend_files}" "${_transitive_configure_depend_files}" PARENT_SCOPE)
endfunction()
# Transforms a list to be absolute paths if not already.
function(_therock_cmake_subproject_absolutize list_var relative_to)
set(_dirs "${${list_var}}")
set(_abs_dirs)
foreach(_dir ${_dirs})
cmake_path(ABSOLUTE_PATH _dir BASE_DIRECTORY "${relative_to}" NORMALIZE)
list(APPEND _abs_dirs "${_dir}")
endforeach()
set("${list_var}" "${_abs_dirs}" PARENT_SCOPE)
endfunction()
# Filters THEROCK_AMDGPU_TARGETS based on global settings for the project.
function(_therock_filter_project_gpu_targets out_var target_name)
get_property(_excludes GLOBAL PROPERTY "THEROCK_AMDGPU_PROJECT_TARGET_EXCLUDES_${target_name}")
set(_filtered ${THEROCK_AMDGPU_TARGETS})
if(_excludes)
foreach(exclude in ${_excludes})
if("${exclude}" IN_LIST _filtered)
message(WARNING