]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/cooking.sh
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / seastar / cooking.sh
CommitLineData
11fdf7f2
TL
1#!/bin/bash
2
3#
4# Copyright 2018 Jesse Haber-Kucharsky
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19#
9f95a23c 20# This is cmake-cooking v0.10.0
11fdf7f2
TL
21# The home of cmake-cooking is https://github.com/hakuch/CMakeCooking
22#
23
24set -e
25
26CMAKE=${CMAKE:-cmake}
27
28invoked_args=("$@")
29source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
30initial_wd=$(pwd)
31memory_file="${initial_wd}/.cooking_memory"
32
9f95a23c 33recipe="${source_dir}/cooking_recipe.cmake"
11fdf7f2
TL
34declare -a excluded_ingredients
35declare -a included_ingredients
36build_dir="${initial_wd}/build"
37build_type="Debug"
38# Depends on `build_dir`.
39ingredients_dir=""
40generator="Ninja"
41list_only=""
42nested=""
43
44usage() {
45 cat <<EOF
46
47Fetch, configure, build, and install dependencies ("ingredients") for a CMake project
48in a local and repeatable development environment.
49
50Usage: $0 [OPTIONS]
51
52where OPTIONS are:
53
54-a
55-r RECIPE
56-e INGREDIENT
57-i INGREDIENT
58-d BUILD_DIR (=${build_dir})
59-p INGREDIENTS_DIR (=${build_dir}/_cooking/installed)
60-t BUILD_TYPE (=${build_type})
61-g GENERATOR (=${generator})
62-s VAR=VALUE
9f95a23c 63-f EXPORT_DIR
11fdf7f2
TL
64-l
65-h
66
9f95a23c
TL
67By default, cmake-cooking reads a file called `cooking_recipe.cmake`.
68
11fdf7f2
TL
69If neither [-i] nor [-e] are specified with a recipe ([-r]), then all ingredients of the recipe
70will be fetched and built.
71
72[-i] and [-e] are mutually-exclusive options: only provide one.
73
74Option details:
75
76-a
77
78 Invoke 'cooking.sh' with the arguments that were provided to it last time, instead
79 of the arguments provided.
80
81-r RECIPE
82
9f95a23c
TL
83 Instead of reading the recipe in a file called `cooking_recipe.cmake`, follow the recipe
84 in the named file.
85
86 If the recipe file is a relative path, it is interpretted relative to the source directory
87 of the project.
11fdf7f2
TL
88
89-e INGREDIENT
90
91 Exclude an ingredient from a recipe. This option can be supplied many times.
92
93 For example, if a recipe consists of 'apple', 'banana', 'carrot', and 'donut', then
94
95 ./cooking.sh -r dev -e apple -e donut
96
97 will prepare 'banana' and 'carrot' but not prepare 'apple' and 'donut'.
98
99 If an ingredient is excluded, then it is assumed that all ingredients that depend on it
100 can satisfy that dependency in some other way from the system (ie, the dependency is
101 removed internally).
102
103-i INGREDIENT
104
105 Include an ingredient from a recipe, ignoring the others. This option can be supplied
106 many times.
107
108 Similar to [-e], but the opposite.
109
110 For example, if a recipe consists of 'apple', 'banana', 'carrot', and 'donut' then
111
112 ./cooking.sh -r dev -i apple -i donut
113
114 will prepare 'apple' and 'donut' but not prepare 'banana' and 'carrot'.
115
116 If an ingredient is not in the "include-list", then it is assumed that all
117 ingredients that are in the list and which depend on it can satisfy that dependency
118 in some other way from the system.
119
120-d BUILD_DIR (=${build_dir})
121
122 Configure the project and build it in the named directory.
123
124-p INGREDIENTS_DIR (=${build_dir}/_cooking/installed)
125
126 Install compiled ingredients into this directory.
127
128-t BUILD_TYPE (=${build_type})
129
130 Configure all ingredients and the project with the named CMake build-type.
131 An example build type is "Release".
132
133-g GENERATOR (=${generator})
134
135 Use the named CMake generator for building all ingredients and the project.
136 An example generator is "Unix Makfiles".
137
138-s VAR=VALUE
139
140 Set an environmental variable 'VAR' to the value 'VALUE' during the invocation of CMake.
141
9f95a23c
TL
142-f EXPORT_DIR
143
144 If provided, and the project is successfully configured, then the tree of installed ingredients
145 is exported to this directory (the actual files: not symbolic links).
146
147 This option requires rsync.
148
149 This may be useful for preparing continuous integration environments, but it is not
150 recommended for distribution or release purposes (since this would be counter
151 to the goal of cmake-cooking).
152
11fdf7f2
TL
153-l
154
155 Only list available ingredients for a given recipe, and don't do anything else.
156
157-h
158
159 Show this help information and exit.
160
161EOF
162}
163
164parse_assignment() {
1e59de90
TL
165 local var
166 local value
167 IFS='=' read -r var value <<< "${1}"
168 export "${var}"="${value}"
11fdf7f2
TL
169}
170
171yell_include_exclude_mutually_exclusive() {
172 echo "Cooking: [-e] and [-i] are mutually exclusive options!" >&2
173}
174
9f95a23c 175while getopts "ar:e:i:d:p:t:g:s:f:lhx" arg; do
11fdf7f2
TL
176 case "${arg}" in
177 a)
178 if [ ! -f "${memory_file}" ]; then
179 echo "No previous invocation found to recall!" >&2
180 exit 1
181 fi
182
183 source "${memory_file}"
184 run_previous && exit 0
185 ;;
9f95a23c
TL
186 r)
187 if [[ "${OPTARG}" = /* ]]; then
188 recipe=${OPTARG}
189 else
190 recipe="${source_dir}/${OPTARG}"
191 fi
192 ;;
11fdf7f2
TL
193 e)
194 if [[ ${#included_ingredients[@]} -ne 0 ]]; then
195 yell_include_exclude_mutually_exclusive
196 exit 1
197 fi
198
199 excluded_ingredients+=(${OPTARG})
200 ;;
201 i)
202 if [[ ${#excluded_ingredients[@]} -ne 0 ]]; then
203 yell_include_exclude_mutually_exclusive
204 exit 1
205 fi
206
207 included_ingredients+=(${OPTARG})
208 ;;
209 d) build_dir=$(realpath "${OPTARG}") ;;
210 p) ingredients_dir=$(realpath "${OPTARG}") ;;
211 t) build_type=${OPTARG} ;;
212 g) generator=${OPTARG} ;;
213 s) parse_assignment "${OPTARG}" ;;
9f95a23c 214 f) export_dir=$(realpath "${OPTARG}") ;;
11fdf7f2
TL
215 l) list_only="1" ;;
216 h) usage; exit 0 ;;
217 x) nested="1" ;;
218 *) usage; exit 1 ;;
219 esac
220done
221
222shift $((OPTIND - 1))
223
224cooking_dir="${build_dir}/_cooking"
11fdf7f2
TL
225cache_file="${build_dir}/CMakeCache.txt"
226ingredients_ready_file="${cooking_dir}/ready.txt"
227
228if [ -z "${ingredients_dir}" ]; then
229 ingredients_dir="${cooking_dir}/installed"
230fi
231
9f95a23c 232mkdir -p "${build_dir}"
11fdf7f2 233
9f95a23c 234cat <<'EOF' > "${build_dir}/Cooking.cmake"
11fdf7f2
TL
235#
236# Copyright 2018 Jesse Haber-Kucharsky
237#
238# Licensed under the Apache License, Version 2.0 (the "License");
239# you may not use this file except in compliance with the License.
240# You may obtain a copy of the License at
241#
242# http://www.apache.org/licenses/LICENSE-2.0
243#
244# Unless required by applicable law or agreed to in writing, software
245# distributed under the License is distributed on an "AS IS" BASIS,
246# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
247# See the License for the specific language governing permissions and
248# limitations under the License.
249#
250
251#
9f95a23c 252# This file was generated by cmake-cooking v0.10.0
11fdf7f2
TL
253# The home of cmake-cooking is https://github.com/hakuch/CMakeCooking
254#
255
256macro (project name)
257 set (_cooking_dir ${CMAKE_CURRENT_BINARY_DIR}/_cooking)
258
259 if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
260 set (_cooking_root ON)
261 else ()
262 set (_cooking_root OFF)
263 endif ()
264
265 find_program (Cooking_STOW_EXECUTABLE
266 stow
267 "Executable path of GNU Stow.")
268
269 if (NOT Cooking_STOW_EXECUTABLE)
270 message (FATAL_ERROR "Cooking: GNU Stow is required!")
271 endif ()
272
273 set (Cooking_INGREDIENTS_DIR
274 ${_cooking_dir}/installed
275 CACHE
276 PATH
277 "Directory where ingredients will be installed.")
278
279 set (Cooking_EXCLUDED_INGREDIENTS
280 ""
281 CACHE
282 STRING
283 "Semicolon-separated list of ingredients that are not provided by Cooking.")
284
285 set (Cooking_INCLUDED_INGREDIENTS
286 ""
287 CACHE
288 STRING
289 "Semicolon-separated list of ingredients that are provided by Cooking.")
290
291 option (Cooking_LIST_ONLY
292 "Available ingredients will be listed and nothing will be installed."
293 OFF)
294
295 set (Cooking_RECIPE "" CACHE STRING "Configure ${name}'s dependencies according to the named recipe.")
296
297 if ((NOT DEFINED Cooking_EXCLUDED_INGREDIENTS) OR (Cooking_EXCLUDED_INGREDIENTS STREQUAL ""))
298 set (_cooking_is_excluding OFF)
299 else ()
300 set (_cooking_is_excluding ON)
301 endif ()
302
303 if ((NOT DEFINED Cooking_INCLUDED_INGREDIENTS) OR (Cooking_INCLUDED_INGREDIENTS STREQUAL ""))
304 set (_cooking_is_including OFF)
305 else ()
306 set (_cooking_is_including ON)
307 endif ()
308
309 if (_cooking_is_excluding AND _cooking_is_including)
310 message (
311 FATAL_ERROR
312 "Cooking: The EXCLUDED_INGREDIENTS and INCLUDED_INGREDIENTS lists are mutually exclusive options!")
313 endif ()
314
315 if (_cooking_root)
316 _project (${name} ${ARGN})
317
318 if (NOT ("${Cooking_RECIPE}" STREQUAL ""))
319 add_custom_target (_cooking_ingredients)
320
321 set (_cooking_ready_marker_file ${_cooking_dir}/ready.txt)
322
323 add_custom_command (
324 OUTPUT ${_cooking_ready_marker_file}
325 DEPENDS _cooking_ingredients
326 COMMAND ${CMAKE_COMMAND} -E touch ${_cooking_ready_marker_file})
327
328 add_custom_target (_cooking_ingredients_ready
329 DEPENDS ${_cooking_ready_marker_file})
330
331 set (_cooking_local_synchronize_marker_file ${Cooking_INGREDIENTS_DIR}/.cooking_local_synchronize)
332
333 add_custom_command (
334 OUTPUT ${_cooking_local_synchronize_marker_file}
335 COMMAND ${CMAKE_COMMAND} -E touch ${_cooking_local_synchronize_marker_file})
336
337 add_custom_target (_cooking_marked_for_local_synchronization
338 DEPENDS ${_cooking_local_synchronize_marker_file})
339
340 list (APPEND CMAKE_PREFIX_PATH ${Cooking_INGREDIENTS_DIR})
9f95a23c 341 include (${Cooking_RECIPE})
11fdf7f2
TL
342
343 if (NOT EXISTS ${_cooking_ready_marker_file})
344 return ()
345 endif ()
346 endif ()
347 endif ()
348endmacro ()
349
350function (_cooking_set_union x y var)
351 set (r ${${x}})
352
353 foreach (e ${${y}})
354 list (APPEND r ${e})
355 endforeach ()
356
357 list (REMOVE_DUPLICATES r)
358 set (${var} ${r} PARENT_SCOPE)
359endfunction ()
360
361function (_cooking_set_difference x y var)
362 set (r ${${x}})
363
364 foreach (e ${${y}})
365 if (${e} IN_LIST ${x})
366 list (REMOVE_ITEM r ${e})
367 endif ()
368 endforeach ()
369
370 set (${var} ${r} PARENT_SCOPE)
371endfunction ()
372
373function (_cooking_set_intersection x y var)
374 set (r "")
375
376 foreach (e ${${y}})
377 if (${e} IN_LIST ${x})
378 list (APPEND r ${e})
379 endif ()
380 endforeach ()
381
382 list (REMOVE_DUPLICATES r)
383 set (${var} ${r} PARENT_SCOPE)
384endfunction ()
385
386function (_cooking_query_by_key list key var)
387 list (FIND ${list} ${key} index)
388
389 if (${index} EQUAL "-1")
390 set (value NOTFOUND)
391 else ()
392 math (EXPR value_index "${index} + 1")
393 list (GET ${list} ${value_index} value)
394 endif ()
395
396 set (${var} ${value} PARENT_SCOPE)
397endfunction ()
398
399function (_cooking_populate_ep_parameter)
400 cmake_parse_arguments (
401 pa
402 ""
403 "EXTERNAL_PROJECT_ARGS_LIST;PARAMETER;DEFAULT_VALUE"
404 ""
405 ${ARGN})
406
407 string (TOLOWER ${pa_PARAMETER} parameter_lower)
408 _cooking_query_by_key (${pa_EXTERNAL_PROJECT_ARGS_LIST} ${pa_PARAMETER} ${parameter_lower})
409 set (value ${${parameter_lower}})
410 set (var_name _cooking_${parameter_lower})
411 set (ep_var_name _cooking_ep_${parameter_lower})
412
413 if (NOT value)
414 set (${var_name} ${pa_DEFAULT_VALUE} PARENT_SCOPE)
415 set (${ep_var_name} ${pa_PARAMETER} ${pa_DEFAULT_VALUE} PARENT_SCOPE)
416 else ()
417 set (${var_name} ${value} PARENT_SCOPE)
418 set (${ep_var_name} "" PARENT_SCOPE)
419 endif ()
420endfunction ()
421
422function (_cooking_define_listing_targets)
423 cmake_parse_arguments (
424 pa
425 ""
426 "NAME;SOURCE_DIR;RECIPE"
427 "REQUIRES"
428 ${ARGN})
429
430 set (stale_file ${Cooking_INGREDIENTS_DIR}/.cooking_stale_ingredient_${pa_NAME})
431
432 add_custom_command (
433 OUTPUT ${stale_file}
434 COMMAND ${CMAKE_COMMAND} -E touch ${stale_file})
435
436 add_custom_target (_cooking_ingredient_${pa_NAME}_stale
437 DEPENDS ${stale_file})
438
439 set (commands
440 COMMAND
441 ${CMAKE_COMMAND} -E touch ${Cooking_INGREDIENTS_DIR}/.cooking_ingredient_${pa_NAME})
442
443 if (pa_RECIPE)
9f95a23c
TL
444 if (pa_RECIPE STREQUAL <DEFAULT>)
445 set (recipe_args "")
446 else ()
447 set (recipe_args -r ${pa_RECIPE})
448 endif ()
449
11fdf7f2
TL
450 list (INSERT commands 0
451 COMMAND
452 ${pa_SOURCE_DIR}/cooking.sh
9f95a23c 453 ${recipe_args}
11fdf7f2
TL
454 -p ${Cooking_INGREDIENTS_DIR}
455 -g ${CMAKE_GENERATOR}
456 -x
457 -l)
458 endif ()
459
460 add_custom_command (
461 OUTPUT ${Cooking_INGREDIENTS_DIR}/.cooking_ingredient_${pa_NAME}
462 DEPENDS
463 _cooking_ingredient_${pa_NAME}_stale
464 ${stale_file}
465 ${commands})
466
467 add_custom_target (_cooking_ingredient_${pa_NAME}_listed
468 DEPENDS ${Cooking_INGREDIENTS_DIR}/.cooking_ingredient_${pa_NAME})
469
470 foreach (d ${pa_REQUIRES})
471 add_dependencies (_cooking_ingredient_${pa_NAME}_listed _cooking_ingredient_${d}_listed)
472 endforeach ()
473
474 add_dependencies (_cooking_ingredients _cooking_ingredient_${pa_NAME}_listed)
475endfunction ()
476
477function (_cooking_adjust_requirements)
478 cmake_parse_arguments (
479 pa
480 ""
481 "IS_EXCLUDING;IS_INCLUDING;OUTPUT_LIST"
482 "REQUIREMENTS"
483 ${ARGN})
484
485 if (pa_IS_EXCLUDING)
486 # Strip out any dependencies that are excluded.
487 _cooking_set_difference (
488 pa_REQUIREMENTS
489 Cooking_EXCLUDED_INGREDIENTS
490 pa_REQUIREMENTS)
491 elseif (_cooking_is_including)
492 # Eliminate dependencies that have not been included.
493 _cooking_set_intersection (
494 pa_REQUIREMENTS
495 Cooking_INCLUDED_INGREDIENTS
496 pa_REQUIREMENTS)
497 endif ()
498
499 set (${pa_OUTPUT_LIST} ${pa_REQUIREMENTS} PARENT_SCOPE)
500endfunction ()
501
502function (_cooking_populate_ep_depends)
503 cmake_parse_arguments (
504 pa
505 ""
506 ""
507 "REQUIREMENTS"
508 ${ARGN})
509
510 if (pa_REQUIREMENTS)
511 set (value DEPENDS)
512
513 foreach (d ${pa_REQUIREMENTS})
514 list (APPEND value ingredient_${d})
515 endforeach ()
516 else ()
517 set (value "")
518 endif ()
519
520 set (_cooking_ep_depends ${value} PARENT_SCOPE)
521endfunction ()
522
523function (_cooking_prepare_restrictions_arguments)
524 cmake_parse_arguments (
525 pa
526 ""
527 "IS_EXCLUDING;IS_INCLUDING;OUTPUT_LIST"
528 "REQUIREMENTS"
529 ${ARGN})
530
531 set (args "")
532
533 if (pa_IS_INCLUDING)
534 _cooking_set_difference (
535 Cooking_INCLUDED_INGREDIENTS
536 pa_REQUIREMENTS
537 included)
538
539 foreach (x ${included})
540 list (APPEND args -i ${x})
541 endforeach ()
542 elseif (pa_IS_EXCLUDING)
543 _cooking_set_union (
544 Cooking_EXCLUDED_INGREDIENTS
545 pa_REQUIREMENTS
546 excluded)
547
548 foreach (x ${excluded})
549 list (APPEND args -e ${x})
550 endforeach ()
551 else ()
552 foreach (x ${pa_REQUIREMENTS})
553 list (APPEND args -e ${x})
554 endforeach ()
555 endif ()
556
557 set (${pa_OUTPUT_LIST} ${args} PARENT_SCOPE)
558endfunction ()
559
560function (_cooking_determine_common_cmake_args output)
561 string (REPLACE ";" ":::" prefix_path_with_colons "${CMAKE_PREFIX_PATH}")
562
1e59de90
TL
563 if (CMAKE_CXX_FLAGS)
564 list(APPEND cmake_args -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS})
565 endif ()
566 if (CMAKE_C_FLAGS)
567 list(APPEND cmake_args -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS})
568 endif ()
569
570 list (APPEND cmake_args
11fdf7f2
TL
571 -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
572 -DCMAKE_PREFIX_PATH=${prefix_path_with_colons}
573 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
1e59de90
TL
574 -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
575 -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER})
576
577 set (${output} ${cmake_args}
11fdf7f2
TL
578 PARENT_SCOPE)
579endfunction ()
580
581function (_cooking_populate_ep_configure_command)
582 cmake_parse_arguments (
583 pa
584 ""
585 "IS_EXCLUDING;IS_INCLUDING;RECIPE;EXTERNAL_PROJECT_ARGS_LIST"
586 "REQUIREMENTS;CMAKE_ARGS;COOKING_CMAKE_ARGS"
587 ${ARGN})
588
589 if (pa_RECIPE)
9f95a23c
TL
590 if (pa_RECIPE STREQUAL <DEFAULT>)
591 set (recipe_args "")
592 else ()
593 set (recipe_args -r ${pa_RECIPE})
594 endif ()
595
11fdf7f2
TL
596 _cooking_prepare_restrictions_arguments (
597 IS_EXCLUDING ${pa_IS_EXCLUDING}
598 IS_INCLUDING ${pa_IS_INCLUDING}
599 REQUIREMENTS ${pa_REQUIREMENTS}
600 OUTPUT_LIST restrictions_args)
601
602 set (value
603 CONFIGURE_COMMAND
604 <SOURCE_DIR>/cooking.sh
9f95a23c 605 ${recipe_args}
11fdf7f2
TL
606 -d <BINARY_DIR>
607 -p ${Cooking_INGREDIENTS_DIR}
608 -g ${CMAKE_GENERATOR}
609 -x
610 ${restrictions_args}
611 --
612 ${pa_COOKING_CMAKE_ARGS})
613 elseif (NOT (CONFIGURE_COMMAND IN_LIST ${pa_EXTERNAL_PROJECT_ARGS_LIST}))
614 set (value
615 CONFIGURE_COMMAND
616 ${CMAKE_COMMAND}
617 ${pa_CMAKE_ARGS}
618 <SOURCE_DIR>)
619 else ()
620 set (value "")
621 endif ()
622
623 set (_cooking_ep_configure_command ${value} PARENT_SCOPE)
624endfunction ()
625
626function (_cooking_populate_ep_build_command ep_args_list)
627 if (NOT (BUILD_COMMAND IN_LIST ${ep_args_list}))
628 set (value BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR>)
629 else ()
630 set (value "")
631 endif ()
632
633 set (_cooking_ep_build_command ${value} PARENT_SCOPE)
634endfunction ()
635
636function (_cooking_populate_ep_install_command ep_args_list)
637 if (NOT (INSTALL_COMMAND IN_LIST ${ep_args_list}))
638 set (value INSTALL_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install)
639 else ()
640 set (value "")
641 endif ()
642
643 set (_cooking_ep_install_command ${value} PARENT_SCOPE)
644endfunction ()
645
646function (_cooking_define_ep)
647 cmake_parse_arguments (
648 pa
649 ""
650 "NAME;SOURCE_DIR;BINARY_DIR;EXTERNAL_PROJECT_ARGS_LIST;RECIPE;INGREDIENT_DIR;STOW_DIR;LOCAL_RECONFIGURE;LOCAL_REBUILD"
651 "DEPENDS;CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND;CMAKE_ARGS"
652 ${ARGN})
653
654 string (REPLACE "<DISABLE>" "" forwarded_ep_args "${${pa_EXTERNAL_PROJECT_ARGS_LIST}}")
655 set (ep_name ingredient_${pa_NAME})
656 include (ExternalProject)
657
658 set (stamp_dir ${pa_INGREDIENT_DIR}/stamp)
659
660 ExternalProject_add (${ep_name}
661 DEPENDS ${pa_DEPENDS}
662 SOURCE_DIR ${pa_SOURCE_DIR}
663 BINARY_DIR ${pa_BINARY_DIR}
664 CONFIGURE_COMMAND ${pa_CONFIGURE_COMMAND}
665 BUILD_COMMAND ${pa_BUILD_COMMAND}
666 INSTALL_COMMAND ${pa_INSTALL_COMMAND}
667 PREFIX ${pa_INGREDIENT_DIR}
668 STAMP_DIR ${stamp_dir}
669 INSTALL_DIR ${pa_STOW_DIR}/${pa_NAME}
670 CMAKE_ARGS ${pa_CMAKE_ARGS}
671 LIST_SEPARATOR :::
672 STEP_TARGETS install
673 "${forwarded_ep_args}")
674
675 set (stow_marker_file ${Cooking_INGREDIENTS_DIR}/.cooking_ingredient_${pa_NAME})
676 set (lock_file ${Cooking_INGREDIENTS_DIR}/.cooking_stow.lock)
677
678 add_custom_command (
679 OUTPUT ${stow_marker_file}
680 DEPENDS
681 ${ep_name}-install
682 ${stamp_dir}/ingredient_${pa_NAME}-install
683 COMMAND
684 flock
685 --wait 30
686 ${lock_file}
687 ${Cooking_STOW_EXECUTABLE}
688 -t ${Cooking_INGREDIENTS_DIR}
689 -d ${pa_STOW_DIR}
690 ${pa_NAME}
691 COMMAND ${CMAKE_COMMAND} -E touch ${stow_marker_file})
692
693 add_custom_target (_cooking_ingredient_${pa_NAME}_stowed
694 DEPENDS ${stow_marker_file})
695
696 if (pa_RECIPE)
697 set (reconfigure_marker_file ${Cooking_INGREDIENTS_DIR}/.cooking_reconfigure_ingredient_${pa_NAME})
698
699 add_custom_command (
700 OUTPUT ${reconfigure_marker_file}
701 COMMAND ${CMAKE_COMMAND} -E touch ${reconfigure_marker_file})
702
703 add_custom_target (_cooking_ingredient_${pa_NAME}_marked_for_reconfigure
704 DEPENDS ${reconfigure_marker_file})
705
706 ExternalProject_add_step (${ep_name}
707 cooking-reconfigure
708 DEPENDERS configure
709 DEPENDS ${reconfigure_marker_file}
710 COMMAND ${CMAKE_COMMAND} -E echo_append)
711
712 ExternalProject_add_stepdependencies (${ep_name}
713 cooking-reconfigure
714 _cooking_ingredient_${pa_NAME}_marked_for_reconfigure)
715 endif ()
716
717 foreach (d ${pa_DEPENDS})
718 ExternalProject_add_stepdependencies (${ep_name}
719 configure
720 _cooking_${d}_stowed)
721 endforeach ()
722
723 add_dependencies (_cooking_ingredients _cooking_ingredient_${pa_NAME}_stowed)
724
725 if (pa_LOCAL_RECONFIGURE OR pa_LOCAL_REBUILD)
726 if (pa_LOCAL_RECONFIGURE)
727 set (step configure)
728 else ()
729 set (step build)
730 endif ()
731
732 ExternalProject_add_step (${ep_name}
733 cooking-local-${step}
734 DEPENDERS ${step}
735 DEPENDS ${_cooking_local_synchronize_marker_file}
736 COMMAND ${CMAKE_COMMAND} -E echo_append)
737
738 ExternalProject_add_stepdependencies (${ep_name}
739 cooking-local-${step}
740 _cooking_marked_for_local_synchronization)
741 endif ()
742endfunction ()
743
744macro (cooking_ingredient name)
745 set (_cooking_args "${ARGN}")
746
747 if ((_cooking_is_excluding AND (${name} IN_LIST Cooking_EXCLUDED_INGREDIENTS))
748 OR (_cooking_is_including AND (NOT (${name} IN_LIST Cooking_INCLUDED_INGREDIENTS))))
749 # Nothing.
750 else ()
751 set (_cooking_ingredient_dir ${_cooking_dir}/ingredient/${name})
752
753 cmake_parse_arguments (
754 _cooking_pa
755 "LOCAL_RECONFIGURE;LOCAL_REBUILD"
756 "COOKING_RECIPE"
757 "CMAKE_ARGS;COOKING_CMAKE_ARGS;EXTERNAL_PROJECT_ARGS;REQUIRES"
758 ${_cooking_args})
759
760 _cooking_populate_ep_parameter (
761 EXTERNAL_PROJECT_ARGS_LIST _cooking_pa_EXTERNAL_PROJECT_ARGS
762 PARAMETER SOURCE_DIR
763 DEFAULT_VALUE ${_cooking_ingredient_dir}/src)
764
765 _cooking_populate_ep_parameter (
766 EXTERNAL_PROJECT_ARGS_LIST _cooking_pa_EXTERNAL_PROJECT_ARGS
767 PARAMETER BINARY_DIR
768 DEFAULT_VALUE ${_cooking_ingredient_dir}/build)
769
770 _cooking_populate_ep_parameter (
771 EXTERNAL_PROJECT_ARGS_LIST _cooking_pa_EXTERNAL_PROJECT_ARGS
772 PARAMETER BUILD_IN_SOURCE
773 DEFAULT_VALUE OFF)
774
775 if (_cooking_build_in_source)
776 set (_cooking_ep_binary_dir "")
777 endif ()
778
779 if (Cooking_LIST_ONLY)
780 _cooking_define_listing_targets (
781 NAME ${name}
782 SOURCE_DIR ${_cooking_source_dir}
783 RECIPE ${_cooking_pa_COOKING_RECIPE}
784 REQUIRES ${_cooking_pa_REQUIRES})
785 else ()
786 _cooking_adjust_requirements (
787 IS_EXCLUDING ${_cooking_is_excluding}
788 IS_INCLUDING ${_cooking_is_including}
789 REQUIREMENTS ${_cooking_pa_REQUIRES}
790 OUTPUT_LIST _cooking_pa_REQUIRES)
791
792 _cooking_populate_ep_depends (
793 REQUIREMENTS ${_cooking_pa_REQUIRES})
794
795 _cooking_determine_common_cmake_args (_cooking_common_cmake_args)
796
797 _cooking_populate_ep_configure_command (
798 IS_EXCLUDING ${_cooking_is_excluding}
799 IS_INCLUDING ${_cooking_is_including}
800 RECIPE ${_cooking_pa_COOKING_RECIPE}
801 REQUIREMENTS ${_cooking_pa_REQUIRES}
802 EXTERNAL_PROJECT_ARGS_LIST _cooking_pa_EXTERNAL_PROJECT_ARGS
803 CMAKE_ARGS
804 ${_cooking_common_cmake_args}
805 ${_cooking_pa_CMAKE_ARGS}
806 COOKING_CMAKE_ARGS
807 ${_cooking_common_cmake_args}
808 ${_cooking_pa_COOKING_CMAKE_ARGS})
809
810 _cooking_populate_ep_build_command (_cooking_pa_EXTERNAL_PROJECT_ARGS)
811 _cooking_populate_ep_install_command (_cooking_pa_EXTERNAL_PROJECT_ARGS)
812
813 _cooking_define_ep (
814 NAME ${name}
815 RECIPE ${_cooking_pa_COOKING_RECIPE}
816 DEPENDS ${_cooking_ep_depends}
817 SOURCE_DIR ${_cooking_ep_source_dir}
818 BINARY_DIR ${_cooking_ep_binary_dir}
819 CONFIGURE_COMMAND ${_cooking_ep_configure_command}
820 BUILD_COMMAND ${_cooking_ep_build_command}
821 INSTALL_COMMAND ${_cooking_ep_install_command}
822 INGREDIENT_DIR ${_cooking_ingredient_dir}
823 STOW_DIR ${_cooking_dir}/stow
824 CMAKE_ARGS ${_cooking_common_cmake_args}
825 EXTERNAL_PROJECT_ARGS_LIST _cooking_pa_EXTERNAL_PROJECT_ARGS
826 LOCAL_RECONFIGURE ${_cooking_pa_LOCAL_RECONFIGURE}
827 LOCAL_REBUILD ${_cooking_pa_LOCAL_REBUILD})
828 endif ()
829 endif ()
830endmacro ()
831EOF
832
833cmake_cooking_args=(
834 "-DCooking_INGREDIENTS_DIR=${ingredients_dir}"
835 "-DCooking_RECIPE=${recipe}"
836)
837
9f95a23c
TL
838#
839# Remove any `Cooking.cmake` file from the source directory. We now generate this file in the build directory, and old
840# copies will cause conflicts.
841#
842
843old_cooking_file="${source_dir}/cmake/Cooking.cmake"
844
845if [ -f "${old_cooking_file}" ]; then
846 grep 'This file was generated by cmake-cooking' "${old_cooking_file}" > /dev/null && rm "${old_cooking_file}"
847fi
848
11fdf7f2
TL
849#
850# Clean-up from a previous run.
851#
852
853if [ -e "${ingredients_ready_file}" ]; then
854 rm "${ingredients_ready_file}"
855fi
856
857if [ -e "${cache_file}" ]; then
858 rm "${cache_file}"
859fi
860
861if [ -d "${ingredients_dir}" -a -z "${nested}" ]; then
862 rm -r --preserve-root "${ingredients_dir}"
863fi
864
865mkdir -p "${ingredients_dir}"
866
867#
868# Validate recipe.
869#
870
871if [ -n "${recipe}" ]; then
9f95a23c 872 if [ ! -f "${recipe}" ]; then
11fdf7f2
TL
873 echo "Cooking: The '${recipe}' recipe does not exist!" >&2
874 exit 1
875 fi
876fi
877
878#
879# Prepare lists of included and excluded ingredients.
880#
881
882if [ -n "${excluded_ingredients}" ] && [ -z "${list_only}" ]; then
883 cmake_cooking_args+=(
884 -DCooking_EXCLUDED_INGREDIENTS=$(printf "%s;" "${excluded_ingredients[@]}")
885 -DCooking_INCLUDED_INGREDIENTS=
886 )
887fi
888
889if [ -n "${included_ingredients}" ] && [ -z "${list_only}" ]; then
890 cmake_cooking_args+=(
891 -DCooking_EXCLUDED_INGREDIENTS=
892 -DCooking_INCLUDED_INGREDIENTS=$(printf "%s;" "${included_ingredients[@]}")
893 )
894fi
895
896#
897# Configure and build ingredients.
898#
899
11fdf7f2
TL
900mkdir -p "${cooking_dir}"/stow
901touch "${cooking_dir}"/stow/.stow
902cd "${build_dir}"
903
904declare -a build_args
905
906if [ "${generator}" == "Ninja" ]; then
907 build_args+=(-v)
908fi
909
910if [ -n "${list_only}" ]; then
911 cmake_cooking_args+=("-DCooking_LIST_ONLY=ON")
912fi
913
914${CMAKE} -DCMAKE_BUILD_TYPE="${build_type}" "${cmake_cooking_args[@]}" -G "${generator}" "${source_dir}" "${@}"
11fdf7f2 915
9f95a23c
TL
916if [ -n "${recipe}" ]; then
917 ${CMAKE} --build . --target _cooking_ingredients_ready -- "${build_args[@]}"
918
919 #
920 # Report what we've done (if we're not nested).
921 #
922
923 if [ -z "${nested}" ]; then
924 ingredients=($(find "${ingredients_dir}" -name '.cooking_ingredient_*' -printf '%f\n' | sed -r 's/\.cooking_ingredient_(.+)/\1/'))
11fdf7f2 925
9f95a23c
TL
926 if [ -z "${list_only}" ]; then
927 printf "\nCooking: Installed the following ingredients:\n"
928 else
929 printf "\nCooking: The following ingredients are necessary for this recipe:\n"
930 fi
11fdf7f2 931
9f95a23c
TL
932 for ingredient in "${ingredients[@]}"; do
933 echo " - ${ingredient}"
934 done
935
936 printf '\n'
11fdf7f2
TL
937 fi
938
9f95a23c
TL
939 if [ -n "${list_only}" ]; then
940 exit 0
941 fi
11fdf7f2 942
9f95a23c
TL
943 #
944 # Configure the project, expecting all requirements satisfied.
945 #
11fdf7f2 946
9f95a23c 947 ${CMAKE} -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON "${@}" .
11fdf7f2 948
9f95a23c
TL
949 #
950 # Optionally export the installed files.
951 #
11fdf7f2 952
9f95a23c
TL
953 if [ -n "${export_dir}" ]; then
954 rsync "${ingredients_dir}/" "${export_dir}" -a --copy-links
955 printf "\nCooking: Exported ingredients to ${export_dir}\n"
956 fi
957fi
11fdf7f2
TL
958
959#
960# Save invocation information.
961#
962
963cd "${initial_wd}"
964
965cat <<EOF > "${memory_file}"
966run_previous() {
967 "${0}" ${invoked_args[@]@Q}
968}
969EOF