-
Notifications
You must be signed in to change notification settings - Fork 16
/
ProjectTools.cmake
2172 lines (2025 loc) · 89.3 KB
/
ProjectTools.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
# ============================================================================
# Copyright (c) 2011-2012 University of Pennsylvania
# Copyright (c) 2013-2014 Carnegie Mellon University
# Copyright (c) 2013-2014 Andreas Schuh
# All rights reserved.
#
# See COPYING file for license information or visit
# http://opensource.andreasschuh.com/cmake-basis/download.html#license
# ============================================================================
##############################################################################
# @file ProjectTools.cmake
# @brief Definition of main project tools.
##############################################################################
# ----------------------------------------------------------------------------
# include guard
if (__BASIS_PROJECTTOOLS_INCLUDED)
return ()
else ()
set (__BASIS_PROJECTTOOLS_INCLUDED TRUE)
endif ()
# ============================================================================
# basis_name_check
# ============================================================================
# ----------------------------------------------------------------------------
## @brief Check if a project name fits the BASIS standards.
#
macro (basis_name_check INPUT_PROJECT_NAME)
if (NOT ${INPUT_PROJECT_NAME} MATCHES "^[a-zA-Z][-+_a-zA-Z0-9]*$")
message (FATAL_ERROR "Invalid name: ${${INPUT_PROJECT_NAME}}\n"
"We suggest that you use upper CamelCase notation. "
"(see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms). "
"Please choose a name with either only captial letters "
"in the case of an acronym or a name with mixed case, "
"but starting with a (captial) letter.\n"
"Note that numbers, `-`, `+`, and `_` are allowed, "
"but not as first character.")
endif()
endmacro()
# ============================================================================
# meta-data
# ============================================================================
## @brief Auxiliary macro used by basis_project_check_metadata.
#
# Used by basis_project_check_metadata to check the existence of each project
# source directory specified in the given list variable and to report an error
# otherwise. As a side effect, this macro makes all relative paths absolute
# with respect to PROJECT_SOURCE_DIR or sets the directory variable to the
# default value (ARGN).
macro (basis_check_or_set_source_paths _VAR)
if (${_VAR})
set (_PATHS)
foreach (_PATH IN LISTS ${_VAR})
if (NOT IS_ABSOLUTE "${_PATH}")
set (_PATH "${PROJECT_SOURCE_DIR}/${_PATH}")
endif ()
if (NOT IS_DIRECTORY "${_PATH}")
message (FATAL_ERROR "The ${_VAR} is set to the non-existing path\n\t${_PATH}\n"
"Check the basis_project() arguments and keep in mind that"
" relative paths have to be relative to the top-level directory"
" of the project or module, respectively, i.e.\n\t${PROJECT_SOURCE_DIR}\n")
endif ()
list (APPEND _PATHS "${_PATH}")
endforeach ()
set (${_VAR} "${_PATHS}")
unset (_PATHS)
unset (_PATH)
else ()
set (${_VAR} ${ARGN})
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## @brief Check meta-data and set defaults.
#
# @sa basis_project()
# @sa basis_slicer_module()
macro (basis_project_check_metadata)
# PROJECT_AUTHOR
if (PROJECT_AUTHORS AND PROJECT_AUTHOR)
message (FATAL_ERROR "Options AUTHOR and AUTHORS are mutually exclusive!")
endif ()
if (PROJECT_AUTHOR)
set (PROJECT_AUTHORS "${PROJECT_AUTHOR}")
endif ()
if (NOT PROJECT_AUTHORS AND PROJECT_IS_MODULE)
set (PROJECT_AUTHORS "${TOPLEVEL_PROJECT_AUTHORS}")
endif ()
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_AUTHORS "${PROJECT_AUTHORS}")
endif ()
# PROJECT_NAME or PROJECT_SUBPROJECT
if (PROJECT_SUBPROJECT AND PROJECT_NAME)
message (FATAL_ERROR "Options SUBPROJECT and NAME are mutually exclusive!")
elseif (PROJECT_SUBPROJECT)
set (PROJECT_NAME "${PROJECT_SUBPROJECT}")
set (PROJECT_IS_SUBPROJECT TRUE)
else ()
set (PROJECT_IS_SUBPROJECT FALSE)
endif ()
unset (PROJECT_SUBPROJECT)
if (NOT PROJECT_NAME)
message (FATAL_ERROR "CMake BASIS variable PROJECT_NAME not specified!")
endif ()
basis_name_check(PROJECT_NAME)
string (TOLOWER "${PROJECT_NAME}" PROJECT_NAME_L)
string (TOUPPER "${PROJECT_NAME}" PROJECT_NAME_U)
basis_sanitize_for_regex(PROJECT_NAME_RE "${PROJECT_NAME}")
string (TOLOWER "${PROJECT_NAME_RE}" PROJECT_NAME_RE_L)
string (TOUPPER "${PROJECT_NAME_RE}" PROJECT_NAME_RE_U)
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_NAME "${PROJECT_NAME}")
set (TOPLEVEL_PROJECT_NAME_L "${PROJECT_NAME_L}")
set (TOPLEVEL_PROJECT_NAME_U "${PROJECT_NAME_U}")
set (TOPLEVEL_PROJECT_NAME_RE "${PROJECT_NAME_RE}")
set (TOPLEVEL_PROJECT_NAME_RE_L "${PROJECT_NAME_RE_L}")
set (TOPLEVEL_PROJECT_NAME_RE_U "${PROJECT_NAME_RE_U}")
endif ()
# PROJECT_PACKAGE_NAME
if (PROJECT_PACKAGE AND PROJECT_PACKAGE_NAME)
message (FATAL_ERROR "Options PACKAGE_NAME and PACKAGE are mutually exclusive!")
endif ()
if (PROJECT_PACKAGE)
set (PROJECT_PACKAGE_NAME "${PROJECT_PACKAGE}")
endif ()
if (NOT PROJECT_PACKAGE_NAME)
if (PROJECT_IS_MODULE)
set (PROJECT_PACKAGE_NAME "${TOPLEVEL_PROJECT_PACKAGE_NAME}")
else ()
if (PROJECT_IS_SUBPROJECT)
message (FATAL_ERROR "Missing PACKAGE_NAME option for SUBPROJECT ${PROJECT_NAME}!"
" Note that the PACKAGE_NAME option is required for subprojects"
" in order to enable the independent build. It should be"
" set to the name of the top-level project this subproject"
" belongs to. Otherwise, the subproject can only be build"
" as part of the package it belongs to.")
endif ()
set (PROJECT_PACKAGE_NAME "${PROJECT_NAME}")
endif ()
endif ()
basis_name_check(PROJECT_PACKAGE_NAME)
string (TOLOWER "${PROJECT_PACKAGE_NAME}" PROJECT_PACKAGE_NAME_L)
string (TOUPPER "${PROJECT_PACKAGE_NAME}" PROJECT_PACKAGE_NAME_U)
basis_sanitize_for_regex(PROJECT_PACKAGE_NAME_RE "${PROJECT_PACKAGE_NAME}")
string (TOLOWER "${PROJECT_PACKAGE_NAME_RE}" PROJECT_PACKAGE_NAME_RE_L)
string (TOUPPER "${PROJECT_PACKAGE_NAME_RE}" PROJECT_PACKAGE_NAME_RE_U)
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_PACKAGE_NAME "${PROJECT_PACKAGE_NAME}")
set (TOPLEVEL_PROJECT_PACKAGE_NAME_L "${PROJECT_PACKAGE_NAME_L}")
set (TOPLEVEL_PROJECT_PACKAGE_NAME_U "${PROJECT_PACKAGE_NAME_U}")
set (TOPLEVEL_PROJECT_PACKAGE_NAME_RE "${PROJECT_PACKAGE_NAME_RE}")
set (TOPLEVEL_PROJECT_PACKAGE_NAME_RE_L "${PROJECT_PACKAGE_NAME_RE_L}")
set (TOPLEVEL_PROJECT_PACKAGE_NAME_RE_U "${PROJECT_PACKAGE_NAME_RE_U}")
endif ()
# PROJECT_PACKAGE_VENDOR
if (PROJECT_PROVIDER AND PROJECT_VENDOR AND PROJECT_PACKAGE_VENDOR)
message (FATAL_ERROR "Options PACKAGE_VENDOR, VENDOR, and PROVIDER (deprecated) are mutually exclusive!")
endif ()
if (PROJECT_PROVIDER)
message (WARNING "Option PROVIDER is deprecated and should be replaced by VENDOR!"
" Consider additionally the new options PROVIDER_NAME and DIVISION_NAME")
set (PROJECT_PACKAGE_VENDOR "${PROJECT_PROVIDER}")
endif ()
if (PROJECT_VENDOR)
set (PROJECT_PACKAGE_VENDOR "${PROJECT_VENDOR}")
endif ()
if (NOT PROJECT_PACKAGE_VENDOR AND PROJECT_IS_MODULE)
set (PROJECT_PACKAGE_VENDOR "${TOPLEVEL_PROJECT_PACKAGE_VENDOR}")
endif ()
string (TOLOWER "${PROJECT_PACKAGE_VENDOR}" PROJECT_PACKAGE_VENDOR_L)
string (TOUPPER "${PROJECT_PACKAGE_VENDOR}" PROJECT_PACKAGE_VENDOR_U)
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_PACKAGE_VENDOR "${PROJECT_PACKAGE_VENDOR}")
set (TOPLEVEL_PROJECT_PACKAGE_VENDOR_L "${PROJECT_PACKAGE_VENDOR_L}")
set (TOPLEVEL_PROJECT_PACKAGE_VENDOR_U "${PROJECT_PACKAGE_VENDOR_U}")
endif ()
# PROJECT_PACKAGE_WEBSITE
if (PROJECT_WEBSITE AND PROJECT_PACKAGE_WEBSITE)
message (FATAL_ERROR "Options PACKAGE_WEBSITE and WEBSITE are mutually exclusive!")
endif ()
if (PROJECT_WEBSITE)
set (PROJECT_PACKAGE_WEBSITE "${PROJECT_WEBSITE}")
endif ()
if (PROJECT_IS_MODULE)
if (NOT PROJECT_PACKAGE_WEBSITE)
set (PROJECT_PACKAGE_WEBSITE "${TOPLEVEL_PROJECT_PACKAGE_WEBSITE}")
endif ()
else ()
set (TOPLEVEL_PROJECT_PACKAGE_WEBSITE "${PROJECT_PACKAGE_WEBSITE}")
endif ()
# PROJECT_PACKAGE_LOGO - see also basis_initialize_settings
if (PROJECT_IS_MODULE)
if (NOT PROJECT_PACKAGE_LOGO)
set (PROJECT_PACKAGE_LOGO "${TOPLEVEL_PROJECT_PACKAGE_LOGO}")
endif ()
else ()
set (TOPLEVEL_PROJECT_PACKAGE_LOGO "${PROJECT_PACKAGE_LOGO}")
endif ()
# PROJECT_PROVIDER_NAME
if (NOT PROJECT_PROVIDER_NAME AND PROJECT_IS_MODULE)
set (PROJECT_PROVIDER_NAME "${TOPLEVEL_PROJECT_PROVIDER_NAME}")
endif ()
string (TOLOWER "${PROJECT_PROVIDER_NAME}" PROJECT_PROVIDER_NAME_L)
string (TOUPPER "${PROJECT_PROVIDER_NAME}" PROJECT_PROVIDER_NAME_U)
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_PROVIDER_NAME "${PROJECT_PROVIDER_NAME}")
set (TOPLEVEL_PROJECT_PROVIDER_NAME_L "${PROJECT_PROVIDER_NAME_L}")
set (TOPLEVEL_PROJECT_PROVIDER_NAME_U "${PROJECT_PROVIDER_NAME_U}")
endif ()
# PROJECT_PROVIDER_WEBSITE
if (PROJECT_IS_MODULE)
if (NOT PROJECT_PROVIDER_WEBSITE)
set (PROJECT_PROVIDER_WEBSITE "${TOPLEVEL_PROJECT_PROVIDER_WEBSITE}")
endif ()
else ()
set (TOPLEVEL_PROJECT_PROVIDER_WEBSITE "${PROJECT_PROVIDER_WEBSITE}")
endif ()
# PROJECT_PROVIDER_LOGO - see also basis_initialize_settings
if (PROJECT_IS_MODULE)
if (NOT PROJECT_PROVIDER_LOGO)
set (PROJECT_PROVIDER_LOGO "${TOPLEVEL_PROJECT_PROVIDER_LOGO}")
endif ()
else ()
set (TOPLEVEL_PROJECT_PROVIDER_LOGO "${PROJECT_PROVIDER_LOGO}")
endif ()
# PROJECT_DIVISION_NAME
if (NOT PROJECT_DIVISION_NAME AND PROJECT_IS_MODULE)
set (PROJECT_DIVISION_NAME "${TOPLEVEL_PROJECT_DIVISION_NAME}")
endif ()
string (TOLOWER "${PROJECT_DIVISION_NAME}" PROJECT_DIVISION_NAME_L)
string (TOUPPER "${PROJECT_DIVISION_NAME}" PROJECT_DIVISION_NAME_U)
if (NOT PROJECT_IS_MODULE)
set (TOPLEVEL_PROJECT_DIVISION_NAME "${PROJECT_DIVISION_NAME}")
set (TOPLEVEL_PROJECT_DIVISION_NAME_L "${PROJECT_DIVISION_NAME_L}")
set (TOPLEVEL_PROJECT_DIVISION_NAME_U "${PROJECT_DIVISION_NAME_U}")
endif ()
# PROJECT_DIVISION_WEBSITE
if (PROJECT_IS_MODULE)
if (NOT PROJECT_DIVISION_WEBSITE)
set (PROJECT_DIVISION_WEBSITE "${TOPLEVEL_PROJECT_DIVISION_WEBSITE}")
endif ()
else ()
set (TOPLEVEL_PROJECT_DIVISION_WEBSITE "${PROJECT_DIVISION_WEBSITE}")
endif ()
# PROJECT_DIVISION_LOGO - see also basis_initialize_settings
if (PROJECT_IS_MODULE)
if (NOT PROJECT_DIVISION_LOGO)
set (PROJECT_DIVISION_LOGO "${TOPLEVEL_PROJECT_DIVISION_LOGO}")
endif ()
else ()
set (TOPLEVEL_PROJECT_DIVISION_LOGO "${PROJECT_DIVISION_LOGO}")
endif ()
# PROJECT_VERSION
if (PROJECT_VERSION)
if (NOT PROJECT_VERSION MATCHES "^[0-9]+(\\.[0-9]+)?(\\.[0-9]+)?(rc[0-9]+|[a-z])?$")
message (FATAL_ERROR "Project ${PROJECT_NAME} has invalid version: ${PROJECT_VERSION}!")
endif ()
if (PROJECT_IS_MODULE)
if (PROJECT_VERSION MATCHES "^0+(\\.0+)?(\\.0+)?$")
set (PROJECT_VERSION "${TOPLEVEL_PROJECT_VERSION}")
endif ()
else ()
set (TOPLEVEL_PROJECT_VERSION "${PROJECT_VERSION}")
endif ()
else ()
if (PROJECT_IS_MODULE)
set (PROJECT_VERSION "${TOPLEVEL_PROJECT_VERSION}")
else ()
message (FATAL_ERROR "Project version not specified!")
endif ()
endif ()
# PROJECT_DESCRIPTION
if (PROJECT_DESCRIPTION)
basis_list_to_string (PROJECT_DESCRIPTION ${PROJECT_DESCRIPTION})
else ()
set (PROJECT_DESCRIPTION "")
endif ()
# PROJECT_COPYRIGHT
if (PROJECT_IS_MODULE)
if (NOT PROJECT_COPYRIGHT)
set (PROJECT_COPYRIGHT "${TOPLEVEL_PROJECT_COPYRIGHT}")
endif ()
else ()
set (TOPLEVEL_PROJECT_COPYRIGHT "${PROJECT_COPYRIGHT}")
endif ()
# PROJECT_LICENSE
if (PROJECT_IS_MODULE)
if (NOT PROJECT_LICENSE)
set (PROJECT_LICENSE "${TOPLEVEL_PROJECT_LICENSE}")
endif ()
else ()
set (TOPLEVEL_PROJECT_LICENSE "${PROJECT_LICENSE}")
endif ()
# PROJECT_CONTACT
if (PROJECT_IS_MODULE)
if (NOT PROJECT_CONTACT)
set (PROJECT_CONTACT "${TOPLEVEL_PROJECT_CONTACT}")
endif ()
else ()
set (TOPLEVEL_PROJECT_CONTACT "${PROJECT_CONTACT}")
endif ()
# source tree directories
basis_set_if_empty (PROJECT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
basis_check_or_set_source_paths (PROJECT_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
basis_check_or_set_source_paths (PROJECT_CODE_DIRS "${PROJECT_SOURCE_DIR}/src")
basis_check_or_set_source_paths (PROJECT_MODULES_DIR "${PROJECT_SOURCE_DIR}/modules")
basis_check_or_set_source_paths (PROJECT_CONFIG_DIR "${PROJECT_SOURCE_DIR}/config")
basis_check_or_set_source_paths (PROJECT_DATA_DIR "${PROJECT_SOURCE_DIR}/data")
basis_check_or_set_source_paths (PROJECT_DOC_DIR "${PROJECT_SOURCE_DIR}/doc")
basis_check_or_set_source_paths (PROJECT_DOCRES_DIR "${PROJECT_DOC_DIR}/static")
basis_check_or_set_source_paths (PROJECT_EXAMPLE_DIR "${PROJECT_SOURCE_DIR}/example")
basis_check_or_set_source_paths (PROJECT_LIBRARY_DIR "${PROJECT_SOURCE_DIR}/lib")
basis_check_or_set_source_paths (PROJECT_TESTING_DIR "${PROJECT_SOURCE_DIR}/test")
# extract main source code directories from lists
list (GET PROJECT_INCLUDE_DIRS 0 PROJECT_INCLUDE_DIR)
list (GET PROJECT_CODE_DIRS 0 PROJECT_CODE_DIR)
# let basis_project_begin() know that basis_project() was called
set (BASIS_basis_project_CALLED TRUE)
endmacro ()
# ----------------------------------------------------------------------------
## @brief Sets basic project information including the name, version, and dependencies.
#
# Any BASIS project has to call this macro in the file BasisProject.cmake
# located in the top level directory of the source tree in order to define
# the project attributes required by BASIS to setup the build system.
# Moreover, if the BASIS project is a module of another BASIS project, this
# file and the variables set by this macro are used by the top-level project to
# identify its modules and the dependencies among them.
#
# @param [in] ARGN This list is parsed for the following arguments:
#
# @par General project meta-data:
# @par
# <table border="0">
# <tr>
# @tp @b VERSION major[.minor[.patch]] @endtp
# <td>Project version string. (default: 1.0.0)
# @n
# The version number consists of three components: the major version number,
# the minor version number, and the patch number. The format of the version
# string is "<major>.<minor>.<patch>", where the minor version number and patch
# number default to "0" if not given. Only digits are allowed except of the two
# separating dots.
# @n
# - A change of the major version number indicates changes of the softwares
# @api (and @abi) and/or its behavior and/or the change or addition of major
# features.
# - A change of the minor version number indicates changes that are not only
# bug fixes and no major changes. Hence, changes of the @api but not the @abi.
# - A change of the patch number indicates changes only related to bug fixes
# which did not change the softwares @api. It is the least important component
# of the version number.
# </td>
# </tr>
# <tr>
# @tp @b DESCRIPTION description @endtp
# <td>Package description, used for packing. If multiple arguments are given,
# they are concatenated using one space character as delimiter.</td>
# </tr>
# <tr>
# @tp @b NAME name @endtp
# <td>The name of the project.</td>
# </tr>
# <tr>
# @tp @b SUBPROJECT name @endtp
# <td>Use this option instead of @c NAME to indicate that this project is a subproject
# of the package named by @c PACKAGE_NAME. This results, for example, in target
# UIDs such as "<package>.<name>.<target>" instead of "<package>.<target>".
# Moreover, the libraries and shared files of a subproject are installed
# in subdirectores whose name equals the name of the subproject. This option
# should only be used for projects which are modules of another BASIS project,
# where these modules should reside in their own sub-namespace rather than
# on the same level as the top-level project.</td>
# </tr>
# <tr>
# @tp @b PACKAGE_NAME name @endtp
# <td>Name of the package this project (module) belongs to. Defaults to the
# name of the (top-level) project. This option can further be used in case
# of a top-level project to specify a different package name for the installation.
# In case of a subproject which is a module of another BASIS project, setting
# the package name explicitly using this option enables the build of the
# subproject as separate project while preserving the directory structure
# and other namespace settings. Therefore, this option is required if the
# @c SUBPROJECT option is given and the project shall be build independently
# as stand-alone package. (default: name of top-level package)</td>
# </tr>
# <tr>
# @tp @b PACKAGE name @endtp
# <td>Short alternative for @c PACKAGE_NAME.</td>
# </tr>
# <tr>
# @tp @b PACKAGE_VENDOR name @endtp
# <td>Short ID of package vendor (i.e, provider and/or division acronym) this variable is used
# for package identification and is the name given to the folder that will be used as the default
# installation path location subdirectory.</td>
# </tr>
# <tr>
# @tp @b VENDOR name @endtp
# <td>Short alternative for @c PACKAGE_VENDOR.</td>
# </tr>
# <tr>
# @tp @b PACKAGE_WEBSITE url @endtp
# <td>URL of project website used for documentation and packaging.
# (default: project website of top-level project or empty string)</td>
# </tr>
# <tr>
# @tp @b PACKAGE_LOGO path @endtp
# <td>Path to package logo file for this installable package. Used in documentation and packaging.
# Relative paths must be relative to @c PROJECT_SOURCE_DIR.
# (default: empty string)</td>
# </tr>
# <tr>
# @tp @b WEBSITE url @endtp
# <td>Short alternative for @c PACKAGE_WEBSITE.</td>
# </tr>
# <tr>
# @tp @b PROVIDER_NAME name @endtp
# <td>The provider/vendor/creator of this package, used for packaging and installation.
# (default: provider of top-level project or empty string)</td>
# </tr>
# <tr>
# @tp @b PROVIDER_WEBSITE url @endtp
# <td>URL of provider website used for documentation and packaging.
# (default: provider website of top-level project or empty string)</td>
# </tr>
# <tr>
# @tp @b PROVIDER_LOGO path @endtp
# <td>Path to provider logo file used for documentation and packaging.
# Relative paths must be relative to @c PROJECT_SOURCE_DIR.
# (default: empty string)</td>
# </tr>
# <tr>
# @tp @b DIVISION_NAME name @endtp
# <td>The provider division of this package, used for packaging and installation.
# (default: provider division of top-level project or empty string)</td>
# </tr>
# <tr>
# @tp @b DIVISION_WEBSITE url @endtp
# <td>URL of provider division website used for documentation and packaging.
# (default: provider website of top-level project or empty string)</td>
# </tr>
# <tr>
# @tp @b DIVISION_LOGO path @endtp
# <td>Path to provider division logo file used for documentation and packaging.
# Relative paths must be relative to @c PROJECT_SOURCE_DIR.
# (default: empty string)</td>
# </tr>
# <tr>
# @tp @b TEMPLATE path @endtp
# <td> The TEMPLATE variable stores the directory of the chosen project template along
# with the template version so that the correct template is used by basisproject when a project is updated.
# Note that this variable is used in BASIS itself to specify the default template to use for the BASIS
# installation, i.e., the default used by basisproject if no --template argument is provided.
# If the template is part of the BASIS installation, only the template name and version part of the
# full path are needed. Otherwise, the full absolute path is used. For example,
# @code
# basis_project (
# # ...
# TEMPLATE "sbia/1.8"
# # ...
# )
# # or
# basis_project (
# # ...
# TEMPLATE "/opt/local/share/custom-basis-template/1.0"
# # ...
# )
# @endcode
# The installed templates can be found in the share/templates folder of installed BASIS software,
# as well as the data/templates foler of the BASIS source tree.</td>
# </tr>
# </table>
#
# @par Project dependencies:
# Dependencies on other BASIS projects, which can be subprojects of the same
# BASIS top-level project, as well as dependencies on external packages such as ITK
# have to be defined here using the @p DEPENDS argument option. This will be used
# by a top-level project to ensure that the dependencies among its subprojects are
# resolved properly. For each external dependency, the BASIS functions
# basis_find_package() and basis_use_package() are invoked by
# basis_project_initialize(). If an external package is not CMake aware and
# additional CMake code shall be executed to include the settings of the external
# package (which is usually done in a so-called <tt>Use<Pkg>.cmake</tt> file
# if the package would be CMake aware), such code should be added to the
# <tt>Settings.cmake</tt> file of the project.
# @par
# <table border="0">
# <tr>
# @tp @b DEPENDS dep1 [dep2...] @endtp
# <td>List of dependencies, i.e., either names of other BASIS (sub)projects
# or names of external packages.</td>
# </tr>
# <tr>
# @tp @b OPTIONAL_DEPENDS dep1 [dep2...] @endtp
# <td>List of dependencies, i.e., either names of other BASIS (sub)projects
# or names of external packages which are used only if available.</td>
# </tr>
# <tr>
# @tp @b TEST_DEPENDS dep1 [dep2...] @endtp
# <td>List of dependencies, i.e., either names of other BASIS (sub)projects
# or names of external packages which are only required by the tests.</td>
# </tr>
# <tr>
# @tp @b OPTIONAL_TEST_DEPENDS dep1 [dep2...] @endtp
# <td>List of dependencies, i.e., either names of other BASIS (sub)projects
# or names of external packages which are used only by the tests if available.</td>
# </tr>
# </table>
#
# @par Source tree layout:
# Relative directory paths have to be relative to the @c PROJECT_SOURCE_DIR, i.e.,
# the diretory containing the @c BasisProject.cmake file which calls this command.
# If any of the following arguments refer to non-existing directory paths,
# the respective paths are simply ignored during the project build configuration.
# In case of the paths passed to @p MODULE_DIRS, an error is raised if the directory
# does not exist or is missing a BasisProject.cmake file.
# @par
# <table border="0">
# <tr>
# @tp @b INCLUDE_DIRS path1 [path2...] @endtp
# <td>A list of directories containing the header files of the public interface.
# (default: include)</td>
# </tr>
# <tr>
# @tp @b INCLUDE_DIR path @endtp
# <td>Alternative option for @p INCLUDE_DIRS which only accepts a single path as argument.</td>
# </tr>
# <tr>
# @tp @b CODE_DIRS path1 [path2...] @endtp
# <td>A list of directories containing the source code files. The first diretory path
# is used as main source directory from which the subdirectory name of the
# corresponding build tree directory is derived. Any configured or generated
# source files are written to this build tree source directory.
# (default: src)</td>
# </tr>
# <tr>
# @tp @b CODE_DIR path @endtp
# <td>Alternative option for @p CODE_DIRS which only accepts a single path as argument.</td>
# </tr>
# <tr>
# @tp @b LIBRARY_DIR path @endtp
# <td>Directory of public modules written in a scripting language such as Python or Perl. (default: lib)</td>
# </tr>
# <tr>
# @tp @b MODULES_DIR path @endtp
# <td>Path to directory containing multiple module subdirectories, each containing
# their own BasisProject.cmake file that will each be picked up automatically.
# (default: modules)</td>
# </tr>
# <tr>
# @tp @b MODULE_DIRS path1 [path2...] @endtp
# <td>A list of individual module directories, each containing a BasisProject.cmake file.
# This list differs from @c MODULES_DIR in that each listed directory is the
# root directory of a single module, whereas @c MODULES_DIR is the comman
# directory of multiple modules contained in their own respective subdirectory.
# (default: "")</td>
# </tr>
# <tr>
# @tp @b CONFIG_DIR path @endtp
# <td>Directory in which BASIS looks for custom CMake/BASIS configuration files. (default: config)</td>
# </tr>
# <tr>
# @tp @b DATA_DIR path @endtp
# <td>Directory which contains auxiliary data required by the software programs. (default: data)</td>
# </tr>
# <tr>
# @tp @b DOC_DIR path @endtp
# <td>Directory containing the software documentation (source) files. (default: doc)</td>
# </tr>
# <tr>
# @tp @b DOCRES_DIR path @endtp
# <td>Directory where the documentation ressource files such as the project logo are located. (default: @p DOC_DIR/config)</td>
# </tr>
# <tr>
# @tp @b EXAMPLE_DIR path @endtp
# <td>Directory with some example files demonstrating the usage of the software. (default: example)</td>
# </tr>
# <tr>
# @tp @b TESTING_DIR path @endtp
# <td>The root diretory of the testing source tree containing test data and implementations. (default: test)</td>
# </tr>
# </table>
#
# @returns Sets the following non-cached CMake variables.
# See documentation of the corresponding parameters above for details.
# @retval PROJECT_NAME See @c NAME and @p SUBPROJECT.
# @retval PROJECT_PACKAGE_NAME See @c PACKAGE_NAME.
# @retval PROJECT_PACKAGE_VENDOR See @c PACKAGE_VENDOR.
# @retval PROJECT_PACKAGE_WEBSITE See @c PACKAGE_WEBSITE.
# @retval PROJECT_PACKAGE_LOGO See @c PACKAGE_LOGO. Value is an absolute path.
# @retval PROJECT_PROVIDER_NAME See @c PROVIDER_NAME.
# @retval PROJECT_PROVIDER_WEBSITE See @c PROVIDER_WEBSITE.
# @retval PROJECT_PROVIDER_LOGO See @c PROVIDER_LOGO. Value is an absolute path.
# @retval PROJECT_DIVISION_NAME See @c DIVISION_NAME.
# @retval PROJECT_DIVISION_WEBSITE See @c DIVISION_WEBSITE.
# @retval PROJECT_DIVISION_LOGO See @c DIVISION_LOGO. Value is an absolute path.
# @retval PROJECT_VERSION See @c VERSION.
# @retval PROJECT_DESCRIPTION See @c DESCRIPTION.
# @retval PROJECT_DEPENDS See @c DEPENDS.
# @retval PROJECT_OPTIONAL_DEPENDS See @c OPTIONAL_DEPENDS.
# @retval PROJECT_TEST_DEPENDS See @c TEST_DEPENDS.
# @retval PROJECT_OPTIONAL_TEST_DEPENDS See @c OPTIONAL_TEST_DEPENDS.
# @retval PROJECT_IS_SUBPROJECT See @c TRUE if @c IS_SUBPROJECT option given or @c FALSE otherwise.
#
# @retval PROJECT_CODE_DIRS See @c CODE_DIRS.
# @retval PROJECT_CODE_DIR First element of @c PROJECT_CODE_DIRS list.
# @retval PROJECT_CONFIG_DIR See @c CONFIG_DIR.
# @retval PROJECT_DATA_DIR See @c DATA_DIR.
# @retval PROJECT_DOC_DIR See @c DOC_DIR.
# @retval PROJECT_DOCRES_DIR See @c DOCRES_DIR.
# @retval PROJECT_EXAMPLE_DIR See @c EXAMPLE_DIR.
# @retval PROJECT_INCLUDE_DIRS See @c INCLUDE_DIRS.
# @retval PROJECT_INCLUDE_DIR First element of @c PROJECT_INCLUDE_DIRS list.
# @retval PROJECT_LIBRARY_DIR See @c LIBRARY_DIR.
# @retval PROJECT_MODULE_DIRS See @c MODULE_DIRS.
# @retval PROJECT_MODULES_DIR See @c MODULES_DIR.
# @retval PROJECT_TESTING_DIR See @c TESTING_DIR.
#
# @ingroup CMakeAPI
#
# @see BasisSettings.cmake
macro (basis_project)
# @see BasisSettings.cmake for parameter lists.
# @see basis_project_check_metadata() above for implementation details
CMAKE_PARSE_ARGUMENTS (
PROJECT
"${BASIS_METADATA_LIST_SWITCH}"
"${BASIS_METADATA_LIST_SINGLE}"
"${BASIS_METADATA_LIST_MULTI}"
${ARGN}
)
basis_project_check_metadata ()
endmacro ()
## @addtogroup CMakeUtilities
# @{
# ============================================================================
# initialization
# ============================================================================
# ----------------------------------------------------------------------------
## @brief Ensure certain requirements on build tree.
#
# Requirements:
# - Root of build tree must not be root of source tree.
#
# @param [in] ARGN Not used.
#
# @returns Nothing.
function (basis_buildtree_asserts)
string (TOLOWER "${CMAKE_SOURCE_DIR}" SOURCE_ROOT)
string (TOLOWER "${CMAKE_BINARY_DIR}" BUILD_ROOT)
if ("^${BUILD_ROOT}$" STREQUAL "^${SOURCE_ROOT}$")
message(FATAL_ERROR "This project should not be configured & build in the "
"source directory:\n"
" ${CMAKE_SOURCE_DIR}\n"
"You must run CMake in a separate build directory.")
endif()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Ensure certain requirements on install tree.
#
# Requirements:
# - Prefix must be an absolute path.
# - Install tree must be different from source and build tree.
#
# @param [in] ARGN Not used.
#
# @returns Nothing.
function (basis_installtree_asserts)
if (NOT IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}")
message (FATAL_ERROR "CMAKE_INSTALL_PREFIX must be an absolute path!")
endif ()
string (TOLOWER "${CMAKE_SOURCE_DIR}" SOURCE_ROOT)
string (TOLOWER "${CMAKE_BINARY_DIR}" BUILD_ROOT)
string (TOLOWER "${CMAKE_INSTALL_PREFIX}" INSTALL_ROOT)
if ("^${BUILD_ROOT}$" STREQUAL "^${INSTALL_ROOT}$" OR "^${SOURCE_ROOT}$" STREQUAL "^${INSTALL_ROOT}$")
message (FATAL_ERROR "The current CMAKE_INSTALL_PREFIX points at the source or build tree:\n"
" ${CMAKE_INSTALL_PREFIX}\n"
"This is not permitted by this project. "
"Please choose another installation prefix."
)
endif()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Initialize project modules.
#
# Most parts of this macro were copied from the ITK4 project
# (http://www.vtk.org/Wiki/ITK_Release_4), in particular, the top-level
# CMakeLists.txt file. This file does not state any specific license, but
# the ITK package itself is released under the Apache License Version 2.0,
# January 2004 (http://www.apache.org/licenses/).
macro (basis_project_modules)
# --------------------------------------------------------------------------
# reset variables
set (PROJECT_MODULES)
set (PROJECT_MODULES_ENABLED)
set (PROJECT_MODULES_DISABLED)
# --------------------------------------------------------------------------
# load module DAG
# glob BasisProject.cmake files in modules subdirectory
if (PROJECT_MODULES_DIR)
file (GLOB MODULE_INFO_FILES "${PROJECT_MODULES_DIR}/*/BasisProject.cmake")
endif ()
# add each manually specified module
foreach (_PATH IN LISTS PROJECT_MODULE_DIRS)
if (NOT IS_ABSOLUTE ${_PATH})
set (_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${_PATH}")
endif ()
if (EXISTS "${_PATH}/BasisProject.cmake")
list (APPEND MODULE_INFO_FILES "${_PATH}/BasisProject.cmake")
else ()
message (FATAL_ERROR "Check your top-level ${CMAKE_CURRENT_SOURCE_DIR}/BasisProject.cmake"
" file because the module ${_PATH}/BasisProject.cmake"
" file does not appear to exist.")
endif ()
endforeach ()
unset (_PATH)
# use function scope to avoid overwriting of this project's variables
function (basis_module_info F)
set (PROJECT_IS_MODULE TRUE)
get_filename_component (PROJECT_SOURCE_DIR "${F}" PATH)
set (BASIS_basis_project_CALLED FALSE)
include ("${F}")
# make sure that basis_project() was called
if (NOT BASIS_basis_project_CALLED)
message (FATAL_ERROR "basis_module_info(): Missing basis_project() command in ${F}!")
endif ()
# remember dependencies
foreach (V IN ITEMS DEPENDS OPTIONAL_DEPENDS TEST_DEPENDS OPTIONAL_TEST_DEPENDS)
set (${V})
foreach (D ${PROJECT_${V}})
basis_tokenize_dependency ("${D}" PKG VER CMP)
list (APPEND ${V} "${PKG}")
endforeach ()
endforeach ()
set (${PROJECT_NAME}_DEPENDS "${DEPENDS}" PARENT_SCOPE)
set (${PROJECT_NAME}_OPTIONAL_DEPENDS "${OPTIONAL_DEPENDS}" PARENT_SCOPE)
set (${PROJECT_NAME}_TEST_DEPENDS "${TEST_DEPENDS}" PARENT_SCOPE)
set (${PROJECT_NAME}_OPTIONAL_TEST_DEPENDS "${OPTIONAL_TEST_DEPENDS}" PARENT_SCOPE)
set (${PROJECT_NAME}_DECLARED TRUE PARENT_SCOPE)
# remember source directories - used by basis_add_doxygen_doc()
set (${PROJECT_NAME}_INCLUDE_DIRS "${PROJECT_INCLUDE_DIRS}")
set (${PROJECT_NAME}_CODE_DIRS "${PROJECT_CODE_DIRS}")
# remember if module depends on Slicer - used by basis_find_packages()
if (PROJECT_IS_SLICER_MODULE)
foreach (_D IN LISTS BASIS_SLICER_METADATA_LIST)
if (DEFINED PROJECT_${_D})
set (${PROJECT_NAME}_${_D} "${PROJECT_${_D}}" PARENT_SCOPE)
endif ()
endforeach ()
set (${PROJECT_NAME}_IS_SLICER_MODULE TRUE PARENT_SCOPE)
else ()
set (${PROJECT_NAME}_IS_SLICER_MODULE FALSE PARENT_SCOPE)
endif ()
# do not use MODULE instead of PROJECT_NAME in this function as it is not
# set in the scope of this function but its parent scope only
set (MODULE "${PROJECT_NAME}" PARENT_SCOPE)
endfunction ()
set (PROJECT_MODULES)
foreach (F IN LISTS MODULE_INFO_FILES)
basis_module_info (${F})
list (APPEND PROJECT_MODULES ${MODULE})
get_filename_component (${MODULE}_BASE ${F} PATH)
set (MODULE_${MODULE}_SOURCE_DIR "${${MODULE}_BASE}")
# use module name as subdirectory name such that the default package
# configuration file knows where to find the module configurations
set (MODULE_${MODULE}_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/modules/${MODULE}")
# help modules to find each other using basis_find_package()
set (${MODULE}_DIR "${MODULE_${MODULE}_BINARY_DIR}")
endforeach()
unset (MODULE)
# validate the module DAG to identify cyclic dependencies
macro (basis_module_check MODULE NEEDED_BY STACK)
if (${MODULE}_DECLARED)
if (${MODULE}_CHECK_STARTED AND NOT ${MODULE}_CHECK_FINISHED)
# we reached a module while traversing its own dependencies recursively
set (MSG "")
foreach (M ${STACK})
set (MSG " ${M} =>${MSG}")
if ("${M}" STREQUAL "${MODULE}")
break ()
endif ()
endforeach ()
message (FATAL_ERROR "Module dependency cycle detected:\n ${MSG} ${MODULE}")
elseif (NOT ${MODULE}_CHECK_STARTED)
# traverse dependencies of this module
set (${MODULE}_CHECK_STARTED TRUE)
foreach (D IN LISTS ${MODULE}_DEPENDS)
basis_module_check (${D} ${MODULE} "${MODULE};${STACK}")
endforeach ()
set (${MODULE}_CHECK_FINISHED TRUE)
endif ()
endif ()
endmacro ()
foreach (MODULE ${PROJECT_MODULES})
basis_module_check ("${MODULE}" "" "")
endforeach ()
# --------------------------------------------------------------------------
# determine list of enabled modules
# provide an option for all modules
if (PROJECT_MODULES)
option (BUILD_ALL_MODULES "Request to build all modules." OFF)
option (BUILD_MODULES_BY_DEFAULT "ON - Automatically request modules be built, OFF - manually request each." ON)
mark_as_advanced(BUILD_MODULES_BY_DEFAULT)
endif ()
# provide an option for each module
foreach (MODULE ${PROJECT_MODULES})
option (MODULE_${MODULE} "Request to build the module ${MODULE}." ${BUILD_MODULES_BY_DEFAULT})
if (${MODULE}_EXCLUDE_FROM_ALL)
set (${MODULE}_IN_ALL FALSE)
else ()
set (${MODULE}_IN_ALL ${BUILD_ALL_MODULES})
endif ()
endforeach ()
# follow dependencies
macro (basis_module_enable MODULE NEEDED_BY)
if (${MODULE}_DECLARED)
if (NOT "${NEEDED_BY}" STREQUAL "")
list (APPEND ${MODULE}_NEEDED_BY "${NEEDED_BY}")
endif ()
if (NOT ${MODULE}_ENABLED)
if ("${NEEDED_BY}" STREQUAL "")
set (${MODULE}_NEEDED_BY)
endif ()
set (${MODULE}_ENABLED TRUE)
foreach (D IN LISTS ${MODULE}_DEPENDS)
basis_module_enable (${D} ${MODULE})
endforeach ()
endif ()
endif ()
endmacro ()
foreach (MODULE ${PROJECT_MODULES})
if (MODULE_${MODULE} OR ${MODULE}_IN_ALL)
basis_module_enable ("${MODULE}" "")
endif ()
endforeach ()
# build final list of enabled modules
set (PROJECT_MODULES_ENABLED "")
set (PROJECT_MODULES_DISABLED "")
foreach (MODULE ${PROJECT_MODULES})
if (${MODULE}_DECLARED)
if (${MODULE}_ENABLED)
list (APPEND PROJECT_MODULES_ENABLED ${MODULE})
else ()
list (APPEND PROJECT_MODULES_DISABLED ${MODULE})
endif ()
endif ()
endforeach ()
list (SORT PROJECT_MODULES_ENABLED) # Deterministic order.
list (SORT PROJECT_MODULES_DISABLED) # Deterministic order.
# order list to satisfy dependencies
include (${BASIS_MODULE_PATH}/TopologicalSort.cmake)
topological_sort (PROJECT_MODULES_ENABLED "" "_DEPENDS")
# remove external dependencies
set (L)
foreach (MODULE ${PROJECT_MODULES_ENABLED})
if (${MODULE}_DECLARED)
list (APPEND L "${MODULE}")
endif ()
endforeach ()
set (PROJECT_MODULES_ENABLED "${L}")
unset (L)
# report what will be built
if (PROJECT_MODULES_ENABLED)
message (STATUS "Enabled modules [${PROJECT_MODULES_ENABLED}].")
endif ()
# turn options ON for modules that are required by other modules
foreach (MODULE ${PROJECT_MODULES})
if (DEFINED MODULE_${MODULE} # there was an option for the user
AND NOT MODULE_${MODULE} # user did not set it to ON themself
AND NOT ${MODULE}_IN_ALL # BUILD_ALL_MODULES was not set ON
AND ${MODULE}_NEEDED_BY) # module is needed by other module(s)
set (MODULE_${MODULE} ON CACHE BOOL "Request building module ${MODULE}." FORCE)
message ("Enabled module ${MODULE}, needed by [${${MODULE}_NEEDED_BY}].")
endif ()
endforeach ()
endmacro ()
# ----------------------------------------------------------------------------
## @brief Configure public header files.
function (basis_configure_public_headers)
# --------------------------------------------------------------------------
# settings
# log file which lists the configured header files
set (CMAKE_FILE "${BINARY_INCLUDE_DIR}/${PROJECT_NAME}PublicHeaders.cmake")
# ----------------------------------------------------------------------------
# header files to configure excluding the .in suffix
set (
EXTENSIONS
".h"
".hh"
".hpp"
".hxx"
".inl"
".txx"
".inc"
)
# --------------------------------------------------------------------------
# clean up last run before the error because a file was added/removed
file (REMOVE "${CMAKE_FILE}.tmp")
file (REMOVE "${CMAKE_FILE}.updated")
if (EXISTS "${CMAKE_FILE}")
# required to be able to remove now obsolete files from the build tree
file (RENAME "${CMAKE_FILE}" "${CMAKE_FILE}.tmp")
endif ()
# --------------------------------------------------------------------------
# configure public header files
message (STATUS "Configuring public header files...")
if (NOT PROJECT_INCLUDE_DIRS)
message (FATAL_ERROR "Missing argument PROJECT_INCLUDE_DIRS!")
endif ()
# configure all .in files with substitution
set (CONFIGURED_HEADERS)
foreach (INCLUDE_DIR IN LISTS PROJECT_INCLUDE_DIRS)
set (PATTERN)
foreach (E IN LISTS EXTENSIONS)
list (APPEND PATTERN "${INCLUDE_DIR}/*${E}.in")
endforeach ()
file (GLOB_RECURSE FILES RELATIVE "${INCLUDE_DIR}" ${PATTERN})
foreach (HEADER IN LISTS FILES)
get_filename_component (SOURCE "${INCLUDE_DIR}/${HEADER}" ABSOLUTE)
string (REGEX REPLACE "\\.in$" "" HEADER "${HEADER}")
configure_file ("${SOURCE}" "${BINARY_INCLUDE_DIR}/${HEADER}" @ONLY)
list (APPEND CONFIGURED_HEADERS "${SOURCE}")
endforeach ()
endforeach ()
# regular headers are copied separately via
# execute_process to avoid a full configure step
# However, all headers should be checked for changes.
execute_process (
COMMAND "${CMAKE_COMMAND}" ${COMMON_ARGS}
-D "PROJECT_INCLUDE_DIRS=${PROJECT_INCLUDE_DIRS}"
-D "BINARY_INCLUDE_DIR=${BINARY_INCLUDE_DIR}"
-D "EXTENSIONS=${EXTENSIONS}"
-D "CMAKE_FILE=${CMAKE_FILE}"
-D "CONFIGURED_HEADERS=${CONFIGURED_HEADERS}"
-P "${BASIS_MODULE_PATH}/ConfigureIncludeFiles.cmake"
RESULT_VARIABLE RT
)
if (RT EQUAL 0)
execute_process (
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_FILE}.updated"
)
else ()
message (FATAL_ERROR "Failed to configure public header files!")
endif ()
if (NOT EXISTS "${CMAKE_FILE}")
message (FATAL_ERROR "File ${CMAKE_FILE} not generated as it should have been!")
endif ()
# remove header files from build tree which were copied there before but
# are part of a now disabled module or were simply removed from the source tree
if (EXISTS "${CMAKE_FILE}.tmp")
execute_process (
# Compare current list of headers to list of previously configured files.
# If the lists differ, this command removes files which have been removed
# from the directory tree with root PROJECT_INCLUDE_DIR also from the
# tree with root directory BINARY_INCLUDE_DIR.
COMMAND "${CMAKE_COMMAND}" ${COMMON_ARGS}