8 |
8 |
9 get_cmake_property(COR_IS_MULTI_CONFIG GENERATOR_IS_MULTI_CONFIG) |
9 get_cmake_property(COR_IS_MULTI_CONFIG GENERATOR_IS_MULTI_CONFIG) |
10 set(COR_IS_MULTI_CONFIG "${COR_IS_MULTI_CONFIG}" CACHE BOOL "Do not change this" FORCE) |
10 set(COR_IS_MULTI_CONFIG "${COR_IS_MULTI_CONFIG}" CACHE BOOL "Do not change this" FORCE) |
11 mark_as_advanced(FORCE COR_IS_MULTI_CONFIG) |
11 mark_as_advanced(FORCE COR_IS_MULTI_CONFIG) |
12 |
12 |
13 if (COR_IS_MULTI_CONFIG AND CMAKE_VERSION VERSION_LESS 3.20.0) |
13 |
14 message(FATAL_ERROR "Corrosion requires at least CMake 3.20 with Multi-Config Generators such as " |
14 if(NOT COR_IS_MULTI_CONFIG AND DEFINED CMAKE_CONFIGURATION_TYPES) |
15 "\"Ninja Multi-Config\" or Visual Studio. " |
|
16 "Please use a different generator or update to cmake >= 3.20.\n" |
|
17 "Note: You are using CMake ${CMAKE_VERSION} (Path: `${CMAKE_COMMAND}`) with " |
|
18 " the `${CMAKE_GENERATOR}` Generator." |
|
19 ) |
|
20 elseif(NOT COR_IS_MULTI_CONFIG AND DEFINED CMAKE_CONFIGURATION_TYPES) |
|
21 message(WARNING "The Generator is ${CMAKE_GENERATOR}, which is not a multi-config " |
15 message(WARNING "The Generator is ${CMAKE_GENERATOR}, which is not a multi-config " |
22 "Generator, but CMAKE_CONFIGURATION_TYPES is set. Please don't set " |
16 "Generator, but CMAKE_CONFIGURATION_TYPES is set. Please don't set " |
23 "CMAKE_CONFIGURATION_TYPES unless you are using a multi-config Generator." |
17 "CMAKE_CONFIGURATION_TYPES unless you are using a multi-config Generator." |
24 ) |
18 ) |
25 endif() |
19 endif() |
26 |
20 |
27 option(CORROSION_VERBOSE_OUTPUT "Enables verbose output from Corrosion and Cargo" OFF) |
21 option(CORROSION_VERBOSE_OUTPUT "Enables verbose output from Corrosion and Cargo" OFF) |
28 |
22 |
29 set(CORROSION_NATIVE_TOOLING_DESCRIPTION |
23 if(DEFINED CORROSION_RESPECT_OUTPUT_DIRECTORY AND NOT CORROSION_RESPECT_OUTPUT_DIRECTORY) |
30 "Use native tooling - Required on CMake < 3.19 and available as a fallback option for recent versions" |
24 message(WARNING "The option CORROSION_RESPECT_OUTPUT_DIRECTORY was removed." |
31 ) |
25 " Corrosion now always attempts to respect the output directory.") |
32 |
26 endif() |
33 set(CORROSION_RESPECT_OUTPUT_DIRECTORY_DESCRIPTION |
|
34 "Respect the CMake target properties specifying the output directory of a target, such as |
|
35 `RUNTIME_OUTPUT_DIRECTORY`. This requires CMake >= 3.19, otherwise this option is forced off." |
|
36 ) |
|
37 |
|
38 option( |
|
39 CORROSION_NATIVE_TOOLING |
|
40 "${CORROSION_NATIVE_TOOLING_DESCRIPTION}" |
|
41 OFF |
|
42 ) |
|
43 |
|
44 option(CORROSION_RESPECT_OUTPUT_DIRECTORY |
|
45 "${CORROSION_RESPECT_OUTPUT_DIRECTORY_DESCRIPTION}" |
|
46 ON |
|
47 ) |
|
48 |
27 |
49 option( |
28 option( |
50 CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED |
29 CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED |
51 "Surpresses a warning if the parsing the target triple failed." |
30 "Surpresses a warning if the parsing the target triple failed." |
52 OFF |
31 OFF |
53 ) |
32 ) |
54 |
33 |
55 # The native tooling is required on CMAke < 3.19 so we override whatever the user may have set. |
|
56 if (CMAKE_VERSION VERSION_LESS 3.19.0) |
|
57 set(CORROSION_NATIVE_TOOLING ON CACHE INTERNAL "${CORROSION_NATIVE_TOOLING_DESCRIPTION}" FORCE) |
|
58 set(CORROSION_RESPECT_OUTPUT_DIRECTORY OFF CACHE INTERNAL |
|
59 "${CORROSION_RESPECT_OUTPUT_DIRECTORY_DESCRIPTION}" FORCE |
|
60 ) |
|
61 endif() |
|
62 |
|
63 find_package(Rust REQUIRED) |
34 find_package(Rust REQUIRED) |
64 |
|
65 if(Rust_TOOLCHAIN_IS_RUSTUP_MANAGED) |
|
66 execute_process(COMMAND rustup target list --toolchain "${Rust_TOOLCHAIN}" |
|
67 OUTPUT_VARIABLE AVAILABLE_TARGETS_RAW |
|
68 ) |
|
69 string(REPLACE "\n" ";" AVAILABLE_TARGETS_RAW "${AVAILABLE_TARGETS_RAW}") |
|
70 string(REPLACE " (installed)" "" "AVAILABLE_TARGETS" "${AVAILABLE_TARGETS_RAW}") |
|
71 set(INSTALLED_TARGETS_RAW "${AVAILABLE_TARGETS_RAW}") |
|
72 list(FILTER INSTALLED_TARGETS_RAW INCLUDE REGEX " \\(installed\\)") |
|
73 string(REPLACE " (installed)" "" "INSTALLED_TARGETS" "${INSTALLED_TARGETS_RAW}") |
|
74 list(TRANSFORM INSTALLED_TARGETS STRIP) |
|
75 if("${Rust_CARGO_TARGET}" IN_LIST AVAILABLE_TARGETS) |
|
76 message(DEBUG "Cargo target ${Rust_CARGO_TARGET} is an official target-triple") |
|
77 message(DEBUG "Installed targets: ${INSTALLED_TARGETS}") |
|
78 if(NOT ("${Rust_CARGO_TARGET}" IN_LIST INSTALLED_TARGETS)) |
|
79 message(FATAL_ERROR "Target ${Rust_CARGO_TARGET} is not installed for toolchain ${Rust_TOOLCHAIN}.\n" |
|
80 "Help: Run `rustup target add --toolchain ${Rust_TOOLCHAIN} ${Rust_CARGO_TARGET}` to install " |
|
81 "the missing target." |
|
82 ) |
|
83 endif() |
|
84 endif() |
|
85 |
|
86 endif() |
|
87 |
35 |
88 if(CMAKE_GENERATOR MATCHES "Visual Studio" |
36 if(CMAKE_GENERATOR MATCHES "Visual Studio" |
89 AND (NOT CMAKE_VS_PLATFORM_NAME STREQUAL CMAKE_VS_PLATFORM_NAME_DEFAULT) |
37 AND (NOT CMAKE_VS_PLATFORM_NAME STREQUAL CMAKE_VS_PLATFORM_NAME_DEFAULT) |
90 AND Rust_VERSION VERSION_LESS "1.54") |
38 AND Rust_VERSION VERSION_LESS "1.54") |
91 message(FATAL_ERROR "Due to a cargo issue, cross-compiling with a Visual Studio generator and rust versions" |
39 message(FATAL_ERROR "Due to a cargo issue, cross-compiling with a Visual Studio generator and rust versions" |
92 " before 1.54 is not supported. Rust build scripts would be linked with the cross-compiler linker, which" |
40 " before 1.54 is not supported. Rust build scripts would be linked with the cross-compiler linker, which" |
93 " causes the build to fail. Please upgrade your Rust version to 1.54 or newer.") |
41 " causes the build to fail. Please upgrade your Rust version to 1.54 or newer.") |
94 endif() |
42 endif() |
95 |
43 |
96 if (NOT TARGET Corrosion::Generator) |
44 # message(STATUS "Using Corrosion as a subdirectory") |
97 message(STATUS "Using Corrosion as a subdirectory") |
|
98 endif() |
|
99 |
45 |
100 get_property( |
46 get_property( |
101 RUSTC_EXECUTABLE |
47 RUSTC_EXECUTABLE |
102 TARGET Rust::Rustc PROPERTY IMPORTED_LOCATION |
48 TARGET Rust::Rustc PROPERTY IMPORTED_LOCATION |
103 ) |
49 ) |
104 |
50 |
105 get_property( |
51 get_property( |
106 CARGO_EXECUTABLE |
52 CARGO_EXECUTABLE |
107 TARGET Rust::Cargo PROPERTY IMPORTED_LOCATION |
53 TARGET Rust::Cargo PROPERTY IMPORTED_LOCATION |
108 ) |
54 ) |
109 |
|
110 # Note: Legacy function, used when respecting the `XYZ_OUTPUT_DIRECTORY` target properties is not |
|
111 # possible. |
|
112 function(_corrosion_set_imported_location_legacy target_name base_property filename) |
|
113 foreach(config_type ${CMAKE_CONFIGURATION_TYPES}) |
|
114 set(binary_root "${CMAKE_CURRENT_BINARY_DIR}/${config_type}") |
|
115 string(TOUPPER "${config_type}" config_type_upper) |
|
116 message(DEBUG "Setting ${base_property}_${config_type_upper} for target ${target_name}" |
|
117 " to `${binary_root}/${filename}`.") |
|
118 # For Multiconfig we want to specify the correct location for each configuration |
|
119 set_property( |
|
120 TARGET ${target_name} |
|
121 PROPERTY "${base_property}_${config_type_upper}" |
|
122 "${binary_root}/${filename}" |
|
123 ) |
|
124 endforeach() |
|
125 if(NOT COR_IS_MULTI_CONFIG) |
|
126 set(binary_root "${CMAKE_CURRENT_BINARY_DIR}") |
|
127 endif() |
|
128 |
|
129 message(DEBUG "Setting ${base_property} for target ${target_name}" |
|
130 " to `${binary_root}/${filename}`.") |
|
131 |
|
132 # IMPORTED_LOCATION must be set regardless of possible overrides. In the multiconfig case, |
|
133 # the last configuration "wins". |
|
134 set_property( |
|
135 TARGET ${target_name} |
|
136 PROPERTY "${base_property}" "${binary_root}/${filename}" |
|
137 ) |
|
138 endfunction() |
|
139 |
|
140 |
|
141 # Sets out_var to true if the byproduct copying and imported location is done in a deferred |
|
142 # manner to respect target properties, etc. that may be set later. |
|
143 function(_corrosion_determine_deferred_byproduct_copying_and_import_location_handling out_var) |
|
144 set(${out_var} ${CORROSION_RESPECT_OUTPUT_DIRECTORY} PARENT_SCOPE) |
|
145 endfunction() |
|
146 |
55 |
147 function(_corrosion_bin_target_suffix target_name out_var_suffix) |
56 function(_corrosion_bin_target_suffix target_name out_var_suffix) |
148 get_target_property(hostbuild "${target_name}" ${_CORR_PROP_HOST_BUILD}) |
57 get_target_property(hostbuild "${target_name}" ${_CORR_PROP_HOST_BUILD}) |
149 if((hostbuild AND CMAKE_HOST_WIN32) |
58 if((hostbuild AND CMAKE_HOST_WIN32) |
150 OR ((NOT hostbuild) AND (Rust_CARGO_TARGET_OS STREQUAL "windows"))) |
59 OR ((NOT hostbuild) AND (Rust_CARGO_TARGET_OS STREQUAL "windows"))) |
256 # - base_property: Name of the base property - i.e. `IMPORTED_LOCATION` or `IMPORTED_IMPLIB`. |
163 # - base_property: Name of the base property - i.e. `IMPORTED_LOCATION` or `IMPORTED_IMPLIB`. |
257 # - output_directory_property: Target property name that determines the standard location for the |
164 # - output_directory_property: Target property name that determines the standard location for the |
258 # artifact. |
165 # artifact. |
259 # - filename of the artifact. |
166 # - filename of the artifact. |
260 function(_corrosion_set_imported_location target_name base_property output_directory_property filename) |
167 function(_corrosion_set_imported_location target_name base_property output_directory_property filename) |
261 _corrosion_determine_deferred_byproduct_copying_and_import_location_handling("defer") |
168 cmake_language(EVAL CODE " |
262 if(defer) |
169 cmake_language(DEFER |
263 _corrosion_call_set_imported_location_deferred("${target_name}" "${base_property}" "${output_directory_property}" "${filename}") |
170 CALL |
264 else() |
171 _corrosion_set_imported_location_deferred |
265 _corrosion_set_imported_location_legacy("${target_name}" "${base_property}" "${filename}") |
172 [[${target_name}]] |
266 endif() |
173 [[${base_property}]] |
267 endfunction() |
174 [[${output_directory_property}]] |
268 |
175 [[${filename}]] |
269 function(_corrosion_copy_byproduct_legacy target_name cargo_build_dir file_names) |
176 ) |
|
177 ") |
|
178 endfunction() |
|
179 |
|
180 function(_corrosion_copy_byproduct_deferred target_name output_dir_prop_names cargo_build_dir file_names) |
270 if(ARGN) |
181 if(ARGN) |
271 message(FATAL_ERROR "Unexpected additional arguments") |
182 message(FATAL_ERROR "Unexpected additional arguments") |
272 endif() |
183 endif() |
273 |
184 |
274 if(COR_IS_MULTI_CONFIG) |
185 foreach(output_dir_prop_name ${output_dir_prop_names}) |
275 set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>") |
186 get_target_property(output_dir ${target_name} "${output_dir_prop_name}") |
276 else() |
187 if(output_dir) |
277 set(output_dir "${CMAKE_CURRENT_BINARY_DIR}") |
188 break() |
278 endif() |
189 endif() |
279 |
190 endforeach() |
280 list(TRANSFORM file_names PREPEND "${cargo_build_dir}/" OUTPUT_VARIABLE src_file_names) |
|
281 list(TRANSFORM file_names PREPEND "${output_dir}/" OUTPUT_VARIABLE dst_file_names) |
|
282 message(DEBUG "Adding command to copy byproducts `${file_names}` to ${dst_file_names}") |
|
283 add_custom_command(TARGET _cargo-build_${target_name} |
|
284 POST_BUILD |
|
285 COMMAND ${CMAKE_COMMAND} -E make_directory "${output_dir}" |
|
286 COMMAND |
|
287 ${CMAKE_COMMAND} -E copy_if_different |
|
288 # tested to work with both multiple files and paths with spaces |
|
289 ${src_file_names} |
|
290 "${output_dir}" |
|
291 BYPRODUCTS ${dst_file_names} |
|
292 COMMENT "Copying byproducts `${file_names}` to ${output_dir}" |
|
293 VERBATIM |
|
294 COMMAND_EXPAND_LISTS |
|
295 ) |
|
296 endfunction() |
|
297 |
|
298 function(_corrosion_copy_byproduct_deferred target_name output_dir_prop_name cargo_build_dir file_names) |
|
299 if(ARGN) |
|
300 message(FATAL_ERROR "Unexpected additional arguments") |
|
301 endif() |
|
302 get_target_property(output_dir ${target_name} "${output_dir_prop_name}") |
|
303 |
191 |
304 # A Genex expanding to the output directory depending on the configuration. |
192 # A Genex expanding to the output directory depending on the configuration. |
305 set(multiconfig_out_dir_genex "") |
193 set(multiconfig_out_dir_genex "") |
306 |
194 |
307 foreach(config_type ${CMAKE_CONFIGURATION_TYPES}) |
195 foreach(config_type ${CMAKE_CONFIGURATION_TYPES}) |
308 string(TOUPPER "${config_type}" config_type_upper) |
196 string(TOUPPER "${config_type}" config_type_upper) |
309 get_target_property(output_dir_curr_config ${target_name} "${output_dir_prop_name}_${config_type_upper}") |
197 foreach(output_dir_prop_name ${output_dir_prop_names}) |
|
198 get_target_property(output_dir_curr_config ${target_name} "${output_dir_prop_name}_${config_type_upper}") |
|
199 if(output_dir_curr_config) |
|
200 break() |
|
201 endif() |
|
202 endforeach() |
310 |
203 |
311 if(output_dir_curr_config) |
204 if(output_dir_curr_config) |
312 set(curr_out_dir "${output_dir_curr_config}") |
205 set(curr_out_dir "${output_dir_curr_config}") |
313 elseif(output_dir) |
206 elseif(output_dir) |
314 # Fallback to `output_dir` if specified |
207 # Fallback to `output_dir` if specified |
366 VERBATIM |
263 VERBATIM |
367 COMMAND_EXPAND_LISTS |
264 COMMAND_EXPAND_LISTS |
368 ) |
265 ) |
369 endfunction() |
266 endfunction() |
370 |
267 |
371 function(_corrosion_call_copy_byproduct_deferred target_name output_dir_prop_name cargo_build_dir file_names) |
268 # Copy the artifacts generated by cargo to the appropriate destination. |
|
269 # |
|
270 # Parameters: |
|
271 # - target_name: The name of the Rust target |
|
272 # - output_dir_prop_names: The property name(s) controlling the destination (e.g. |
|
273 # `LIBRARY_OUTPUT_DIRECTORY` or `PDB_OUTPUT_DIRECTORY;RUNTIME_OUTPUT_DIRECTORY`) |
|
274 # - cargo_build_dir: the directory cargo build places it's output artifacts in. |
|
275 # - filenames: the file names of any output artifacts as a list. |
|
276 function(_corrosion_copy_byproducts target_name output_dir_prop_names cargo_build_dir file_names) |
372 cmake_language(EVAL CODE " |
277 cmake_language(EVAL CODE " |
373 cmake_language(DEFER |
278 cmake_language(DEFER |
374 CALL |
279 CALL |
375 _corrosion_copy_byproduct_deferred |
280 _corrosion_copy_byproduct_deferred |
376 [[${target_name}]] |
281 [[${target_name}]] |
377 [[${output_dir_prop_name}]] |
282 [[${output_dir_prop_names}]] |
378 [[${cargo_build_dir}]] |
283 [[${cargo_build_dir}]] |
379 [[${file_names}]] |
284 [[${file_names}]] |
380 ) |
285 ) |
381 ") |
286 ") |
382 endfunction() |
|
383 |
|
384 # Copy the artifacts generated by cargo to the appropriate destination. |
|
385 # |
|
386 # Parameters: |
|
387 # - target_name: The name of the Rust target |
|
388 # - output_dir_prop_name: The property name controlling the destination (e.g. |
|
389 # `RUNTIME_OUTPUT_DIRECTORY`) |
|
390 # - cargo_build_dir: the directory cargo build places it's output artifacts in. |
|
391 # - filenames: the file names of any output artifacts as a list. |
|
392 # - is_binary: TRUE if the byproducts are program executables. |
|
393 function(_corrosion_copy_byproducts target_name output_dir_prop_name cargo_build_dir filenames) |
|
394 _corrosion_determine_deferred_byproduct_copying_and_import_location_handling("defer") |
|
395 if(defer) |
|
396 _corrosion_call_copy_byproduct_deferred("${target_name}" "${output_dir_prop_name}" "${cargo_build_dir}" "${filenames}") |
|
397 else() |
|
398 _corrosion_copy_byproduct_legacy("${target_name}" "${cargo_build_dir}" "${filenames}") |
|
399 endif() |
|
400 endfunction() |
287 endfunction() |
401 |
288 |
402 |
289 |
403 # Add targets for the static and/or shared libraries of the rust target. |
290 # Add targets for the static and/or shared libraries of the rust target. |
404 # The generated byproduct names are returned via the `OUT_<type>_BYPRODUCTS` arguments. |
291 # The generated byproduct names are returned via the `OUT_<type>_BYPRODUCTS` arguments. |
579 |
467 |
580 if(Rust_CARGO_TARGET_ENV STREQUAL "msvc") |
468 if(Rust_CARGO_TARGET_ENV STREQUAL "msvc") |
581 set(${out_pdb_byproduct} "${pdb_name}" PARENT_SCOPE) |
469 set(${out_pdb_byproduct} "${pdb_name}" PARENT_SCOPE) |
582 endif() |
470 endif() |
583 |
471 |
|
472 # Potential .exe suffix will be added later, also depending on possible hostbuild |
|
473 # target property |
584 set(bin_filename "${bin_name}") |
474 set(bin_filename "${bin_name}") |
585 _corrosion_determine_deferred_byproduct_copying_and_import_location_handling("defer") |
|
586 if(defer) |
|
587 # .exe suffix will be added later, also depending on possible hostbuild |
|
588 # target property |
|
589 else() |
|
590 if(Rust_CARGO_TARGET_OS STREQUAL "windows") |
|
591 set(bin_filename "${bin_name}.exe") |
|
592 endif() |
|
593 endif() |
|
594 set(${out_bin_byproduct} "${bin_filename}" PARENT_SCOPE) |
475 set(${out_bin_byproduct} "${bin_filename}" PARENT_SCOPE) |
595 |
|
596 |
|
597 # Todo: This is compatible with the way corrosion previously exposed the bin name, |
|
598 # but maybe we want to prefix the exposed name with the package name? |
|
599 add_executable(${bin_name} IMPORTED GLOBAL) |
|
600 add_dependencies(${bin_name} cargo-build_${bin_name}) |
476 add_dependencies(${bin_name} cargo-build_${bin_name}) |
601 |
477 |
602 if(Rust_CARGO_TARGET_OS STREQUAL "darwin") |
478 if(Rust_CARGO_TARGET_OS STREQUAL "darwin") |
603 set_property(TARGET ${bin_name} |
479 set_property(TARGET ${bin_name} |
604 PROPERTY INTERFACE_LINK_DIRECTORIES "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" |
480 PROPERTY INTERFACE_LINK_DIRECTORIES "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" |
611 ) |
487 ) |
612 |
488 |
613 endfunction() |
489 endfunction() |
614 |
490 |
615 |
491 |
616 if (NOT CORROSION_NATIVE_TOOLING) |
492 include(CorrosionGenerator) |
617 include(CorrosionGenerator) |
|
618 endif() |
|
619 |
493 |
620 # Note: `cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>)` requires CMake 3.25, |
494 # Note: `cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>)` requires CMake 3.25, |
621 # so we offer our own option to control verbosity of downstream commands (e.g. cargo build) |
495 # so we offer our own option to control verbosity of downstream commands (e.g. cargo build) |
622 if (CORROSION_VERBOSE_OUTPUT) |
496 if (CORROSION_VERBOSE_OUTPUT) |
623 set(_CORROSION_VERBOSE_OUTPUT_FLAG --verbose CACHE INTERNAL "") |
497 set(_CORROSION_VERBOSE_OUTPUT_FLAG --verbose CACHE INTERNAL "") |
624 else() |
498 else() |
625 # We want to silence some less important commands by default. |
499 # We want to silence some less important commands by default. |
626 set(_CORROSION_QUIET_OUTPUT_FLAG --quiet CACHE INTERNAL "") |
500 set(_CORROSION_QUIET_OUTPUT_FLAG --quiet CACHE INTERNAL "") |
627 endif() |
501 endif() |
628 |
502 |
629 if(CORROSION_NATIVE_TOOLING) |
|
630 if (NOT TARGET Corrosion::Generator ) |
|
631 add_subdirectory(generator) |
|
632 endif() |
|
633 get_property( |
|
634 _CORROSION_GENERATOR_EXE |
|
635 TARGET Corrosion::Generator PROPERTY IMPORTED_LOCATION |
|
636 ) |
|
637 set( |
|
638 _CORROSION_GENERATOR |
|
639 ${CMAKE_COMMAND} -E env |
|
640 CARGO_BUILD_RUSTC=${RUSTC_EXECUTABLE} |
|
641 ${_CORROSION_GENERATOR_EXE} |
|
642 --cargo ${CARGO_EXECUTABLE} |
|
643 ${_CORROSION_VERBOSE_OUTPUT_FLAG} |
|
644 CACHE INTERNAL "corrosion-generator runner" |
|
645 ) |
|
646 endif() |
|
647 |
|
648 set(_CORROSION_CARGO_VERSION ${Rust_CARGO_VERSION} CACHE INTERNAL "cargo version used by corrosion") |
503 set(_CORROSION_CARGO_VERSION ${Rust_CARGO_VERSION} CACHE INTERNAL "cargo version used by corrosion") |
649 set(_CORROSION_RUST_CARGO_TARGET ${Rust_CARGO_TARGET} CACHE INTERNAL "target triple used by corrosion") |
504 set(_CORROSION_RUST_CARGO_TARGET ${Rust_CARGO_TARGET} CACHE INTERNAL "target triple used by corrosion") |
650 set(_CORROSION_RUST_CARGO_HOST_TARGET ${Rust_CARGO_HOST_TARGET} CACHE INTERNAL "host triple used by corrosion") |
505 set(_CORROSION_RUST_CARGO_HOST_TARGET ${Rust_CARGO_HOST_TARGET} CACHE INTERNAL "host triple used by corrosion") |
651 set(_CORROSION_RUSTC "${RUSTC_EXECUTABLE}" CACHE INTERNAL "Path to rustc used by corrosion") |
506 set(_CORROSION_RUSTC "${RUSTC_EXECUTABLE}" CACHE INTERNAL "Path to rustc used by corrosion") |
652 set(_CORROSION_CARGO "${CARGO_EXECUTABLE}" CACHE INTERNAL "Path to cargo used by corrosion") |
507 set(_CORROSION_CARGO "${CARGO_EXECUTABLE}" CACHE INTERNAL "Path to cargo used by corrosion") |
663 # We previously specified some Custom properties as part of our public API, however the chosen names prevented us from |
518 # We previously specified some Custom properties as part of our public API, however the chosen names prevented us from |
664 # supporting CMake versions before 3.19. In order to both support older CMake versions and not break existing code |
519 # supporting CMake versions before 3.19. In order to both support older CMake versions and not break existing code |
665 # immediately, we are using a different property name depending on the CMake version. However users avoid using |
520 # immediately, we are using a different property name depending on the CMake version. However users avoid using |
666 # any of the properties directly, as they are no longer part of the public API and are to be considered deprecated. |
521 # any of the properties directly, as they are no longer part of the public API and are to be considered deprecated. |
667 # Instead use the corrosion_set_... functions as documented in the Readme. |
522 # Instead use the corrosion_set_... functions as documented in the Readme. |
668 if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.19.0) |
523 set(_CORR_PROP_FEATURES CORROSION_FEATURES CACHE INTERNAL "") |
669 set(_CORR_PROP_FEATURES CORROSION_FEATURES CACHE INTERNAL "") |
524 set(_CORR_PROP_ALL_FEATURES CORROSION_ALL_FEATURES CACHE INTERNAL "") |
670 set(_CORR_PROP_ALL_FEATURES CORROSION_ALL_FEATURES CACHE INTERNAL "") |
525 set(_CORR_PROP_NO_DEFAULT_FEATURES CORROSION_NO_DEFAULT_FEATURES CACHE INTERNAL "") |
671 set(_CORR_PROP_NO_DEFAULT_FEATURES CORROSION_NO_DEFAULT_FEATURES CACHE INTERNAL "") |
526 set(_CORR_PROP_ENV_VARS CORROSION_ENVIRONMENT_VARIABLES CACHE INTERNAL "") |
672 set(_CORR_PROP_ENV_VARS CORROSION_ENVIRONMENT_VARIABLES CACHE INTERNAL "") |
527 set(_CORR_PROP_HOST_BUILD CORROSION_USE_HOST_BUILD CACHE INTERNAL "") |
673 set(_CORR_PROP_HOST_BUILD CORROSION_USE_HOST_BUILD CACHE INTERNAL "") |
|
674 else() |
|
675 set(_CORR_PROP_FEATURES INTERFACE_CORROSION_FEATURES CACHE INTERNAL "") |
|
676 set(_CORR_PROP_ALL_FEATURES INTERFACE_CORROSION_ALL_FEATURES CACHE INTERNAL "") |
|
677 set(_CORR_PROP_NO_DEFAULT_FEATURES INTERFACE_NO_DEFAULT_FEATURES CACHE INTERNAL "") |
|
678 set(_CORR_PROP_ENV_VARS INTERFACE_CORROSION_ENVIRONMENT_VARIABLES CACHE INTERNAL "") |
|
679 set(_CORR_PROP_HOST_BUILD INTERFACE_CORROSION_USE_HOST_BUILD CACHE INTERNAL "") |
|
680 endif() |
|
681 |
528 |
682 # Add custom command to build one target in a package (crate) |
529 # Add custom command to build one target in a package (crate) |
683 # |
530 # |
684 # A target may be either a specific bin |
531 # A target may be either a specific bin |
685 function(_add_cargo_build out_cargo_build_out_dir) |
532 function(_add_cargo_build out_cargo_build_out_dir) |
705 set(package_name "${ACB_PACKAGE}") |
552 set(package_name "${ACB_PACKAGE}") |
706 set(target_name "${ACB_TARGET}") |
553 set(target_name "${ACB_TARGET}") |
707 set(path_to_toml "${ACB_MANIFEST_PATH}") |
554 set(path_to_toml "${ACB_MANIFEST_PATH}") |
708 set(target_kinds "${ACB_TARGET_KINDS}") |
555 set(target_kinds "${ACB_TARGET_KINDS}") |
709 set(workspace_manifest_path "${ACB_WORKSPACE_MANIFEST_PATH}") |
556 set(workspace_manifest_path "${ACB_WORKSPACE_MANIFEST_PATH}") |
710 |
557 set(build_byproducts "${ACB_BYPRODUCTS}") |
711 |
558 |
|
559 unset(cargo_rustc_crate_types) |
712 if(NOT target_kinds) |
560 if(NOT target_kinds) |
713 message(FATAL_ERROR "TARGET_KINDS not specified") |
561 message(FATAL_ERROR "TARGET_KINDS not specified") |
714 elseif("staticlib" IN_LIST target_kinds OR "cdylib" IN_LIST target_kinds) |
562 elseif("staticlib" IN_LIST target_kinds OR "cdylib" IN_LIST target_kinds) |
715 set(cargo_rustc_filter "--lib") |
563 set(cargo_rustc_filter "--lib") |
|
564 if("${Rust_VERSION}" VERSION_GREATER_EQUAL "1.64") |
|
565 # https://doc.rust-lang.org/1.64.0/cargo/commands/cargo-rustc.html |
|
566 # `--crate-type` is documented since Rust 1.64 for `cargo rustc`. |
|
567 # We just unconditionally set it when available, to support overriding the crate type. |
|
568 # Due to https://github.com/rust-lang/cargo/issues/14498 we can't use one argument and pass a |
|
569 # comma seperated list. Instead we use multiple arguments. |
|
570 set(cargo_rustc_crate_types "${target_kinds}") |
|
571 list(TRANSFORM cargo_rustc_crate_types PREPEND "--crate-type=") |
|
572 endif() |
716 elseif("bin" IN_LIST target_kinds) |
573 elseif("bin" IN_LIST target_kinds) |
717 set(cargo_rustc_filter "--bin=${target_name}") |
574 set(cargo_rustc_filter "--bin=${target_name}") |
718 else() |
575 else() |
719 message(FATAL_ERROR "TARGET_KINDS contained unknown kind `${target_kind}`") |
576 message(FATAL_ERROR "TARGET_KINDS contained unknown kind `${target_kind}`") |
720 endif() |
577 endif() |
904 ${_CORROSION_VERBOSE_OUTPUT_FLAG} |
766 ${_CORROSION_VERBOSE_OUTPUT_FLAG} |
905 ${all_features_arg} |
767 ${all_features_arg} |
906 ${no_default_features_arg} |
768 ${no_default_features_arg} |
907 ${features_genex} |
769 ${features_genex} |
908 --package ${package_name} |
770 --package ${package_name} |
|
771 ${cargo_rustc_crate_types} |
909 --manifest-path "${path_to_toml}" |
772 --manifest-path "${path_to_toml}" |
910 --target-dir "${cargo_target_dir}" |
773 --target-dir "${cargo_target_dir}" |
911 ${cargo_profile} |
774 ${cargo_profile} |
912 ${flags_genex} |
775 ${flags_genex} |
913 # Any arguments to cargo must be placed before this line |
776 # Any arguments to cargo must be placed before this line |
914 ${local_rustflags_delimiter} |
777 ${local_rustflags_delimiter} |
915 ${local_rustflags_genex} |
778 ${local_rustflags_genex} |
916 |
779 |
917 # Note: Adding `build_byproducts` (the byproducts in the cargo target directory) here |
780 # Note: `BYPRODUCTS` may not contain **target specific** generator expressions. |
918 # causes CMake to fail during the Generate stage, because the target `target_name` was not |
781 # This means we cannot use `${cargo_build_dir}`, since it currently uses `$<TARGET_PROPERTY>` |
919 # found. I don't know why this happens, so we just don't specify byproducts here and |
782 # to determine the correct target directory, depending on if the hostbuild target property is |
920 # only specify the actual byproducts in the `POST_BUILD` custom command that copies the |
783 # set or not. |
921 # byproducts to the final destination. |
784 # BYPRODUCTS "${cargo_build_dir}/${build_byproducts}" |
922 # BYPRODUCTS ${build_byproducts} |
|
923 # The build is conducted in the directory of the Manifest, so that configuration files such as |
785 # The build is conducted in the directory of the Manifest, so that configuration files such as |
924 # `.cargo/config.toml` or `toolchain.toml` are applied as expected. |
786 # `.cargo/config.toml` or `toolchain.toml` are applied as expected. |
925 WORKING_DIRECTORY "${workspace_toml_dir}" |
787 WORKING_DIRECTORY "${workspace_toml_dir}" |
926 USES_TERMINAL |
788 USES_TERMINAL |
927 COMMAND_EXPAND_LISTS |
789 COMMAND_EXPAND_LISTS |
989 * **LOCKED**: Pass [`--locked`] to cargo build and cargo metadata. |
852 * **LOCKED**: Pass [`--locked`] to cargo build and cargo metadata. |
990 * **FROZEN**: Pass [`--frozen`] to cargo build and cargo metadata. |
853 * **FROZEN**: Pass [`--frozen`] to cargo build and cargo metadata. |
991 * **PROFILE**: Specify cargo build profile (`dev`/`release` or a [custom profile]; `bench` and `test` are not supported) |
854 * **PROFILE**: Specify cargo build profile (`dev`/`release` or a [custom profile]; `bench` and `test` are not supported) |
992 * **IMPORTED_CRATES**: Save the list of imported crates into the variable with the provided name in the current scope. |
855 * **IMPORTED_CRATES**: Save the list of imported crates into the variable with the provided name in the current scope. |
993 * **CRATE_TYPES**: Only import the specified crate types. Valid values: `staticlib`, `cdylib`, `bin`. |
856 * **CRATE_TYPES**: Only import the specified crate types. Valid values: `staticlib`, `cdylib`, `bin`. |
|
857 * **OVERRIDE_CRATE_TYPE**: Override the crate-types of a cargo crate with the given comma-separated values. |
|
858 Internally uses the `rustc` flag [`--crate-type`] to override the crate-type. |
|
859 Valid values for the crate types are the library types `staticlib` and `cdylib`. |
994 * **CRATES**: Only import the specified crates from a workspace. Values: Crate names. |
860 * **CRATES**: Only import the specified crates from a workspace. Values: Crate names. |
995 * **FEATURES**: Enable the specified features. Equivalent to [--features] passed to `cargo build`. |
861 * **FEATURES**: Enable the specified features. Equivalent to [--features] passed to `cargo build`. |
996 * **FLAGS**: Arbitrary flags to `cargo build`. |
862 * **FLAGS**: Arbitrary flags to `cargo build`. |
997 |
863 |
998 [custom profile]: https://doc.rust-lang.org/cargo/reference/profiles.html#custom-profiles |
864 [custom profile]: https://doc.rust-lang.org/cargo/reference/profiles.html#custom-profiles |
999 [--all-features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
865 [--all-features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
1000 [--no-default-features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
866 [--no-default-features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
1001 [--features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
867 [--features]: https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options |
1002 [`--locked`]: https://doc.rust-lang.org/cargo/commands/cargo.html#manifest-options |
868 [`--locked`]: https://doc.rust-lang.org/cargo/commands/cargo.html#manifest-options |
1003 [`--frozen`]: https://doc.rust-lang.org/cargo/commands/cargo.html#manifest-options |
869 [`--frozen`]: https://doc.rust-lang.org/cargo/commands/cargo.html#manifest-options |
|
870 [`--crate-type`]: https://doc.rust-lang.org/rustc/command-line-arguments.html#--crate-type-a-list-of-types-of-crates-for-the-compiler-to-emit |
1004 [Cargo.toml Manifest]: https://doc.rust-lang.org/cargo/appendix/glossary.html#manifest |
871 [Cargo.toml Manifest]: https://doc.rust-lang.org/cargo/appendix/glossary.html#manifest |
1005 |
872 |
1006 ANCHOR_END: corrosion-import-crate |
873 ANCHOR_END: corrosion-import-crate |
1007 #]=======================================================================] |
874 #]=======================================================================] |
1008 function(corrosion_import_crate) |
875 function(corrosion_import_crate) |
1009 set(OPTIONS ALL_FEATURES NO_DEFAULT_FEATURES NO_STD NO_LINKER_OVERRIDE LOCKED FROZEN) |
876 set(OPTIONS ALL_FEATURES NO_DEFAULT_FEATURES NO_STD NO_LINKER_OVERRIDE LOCKED FROZEN) |
1010 set(ONE_VALUE_KEYWORDS MANIFEST_PATH PROFILE IMPORTED_CRATES) |
877 set(ONE_VALUE_KEYWORDS MANIFEST_PATH PROFILE IMPORTED_CRATES) |
1011 set(MULTI_VALUE_KEYWORDS CRATE_TYPES CRATES FEATURES FLAGS) |
878 set(MULTI_VALUE_KEYWORDS CRATE_TYPES CRATES FEATURES FLAGS OVERRIDE_CRATE_TYPE) |
1012 cmake_parse_arguments(COR "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}" ${ARGN}) |
879 cmake_parse_arguments(COR "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}" ${ARGN}) |
1013 list(APPEND CMAKE_MESSAGE_CONTEXT "corrosion_import_crate") |
880 list(APPEND CMAKE_MESSAGE_CONTEXT "corrosion_import_crate") |
1014 |
881 |
1015 if(DEFINED COR_UNPARSED_ARGUMENTS) |
882 if(DEFINED COR_UNPARSED_ARGUMENTS) |
1016 message(AUTHOR_WARNING "Unexpected arguments: " ${COR_UNPARSED_ARGUMENTS} |
883 message(AUTHOR_WARNING "Unexpected arguments: " ${COR_UNPARSED_ARGUMENTS} |
1045 " built-in profile instead." |
912 " built-in profile instead." |
1046 ) |
913 ) |
1047 endif() |
914 endif() |
1048 endif() |
915 endif() |
1049 |
916 |
|
917 # intended to be used with foreach(... ZIP_LISTS ...), meaning |
|
918 # that the crate_types at index i of `override_crate_type_types_list` are |
|
919 # for the package_name at index i of `override_crate_type_package_name_list`. |
|
920 # It would really be nice if CMake had structs or dicts. |
|
921 unset(override_crate_type_package_name_list) |
|
922 unset(override_crate_type_types_list) |
|
923 unset(OVERRIDE_CRATE_TYPE_ARGS) |
|
924 if(DEFINED COR_OVERRIDE_CRATE_TYPE) |
|
925 string(JOIN " " usage_help |
|
926 "Each argument to OVERRIDE_CRATE_TYPE must be of the form `<package_name>=<crate_type(s)>." |
|
927 "The package_name must be a valid cargo package name and the crate_type must be " |
|
928 "a comma-seperated list with valid values being `staticlib`, `cdylib` and `bin`" |
|
929 ) |
|
930 foreach(entry IN LISTS COR_OVERRIDE_CRATE_TYPE) |
|
931 string(REPLACE "=" ";" key_val_list ${entry}) |
|
932 list(LENGTH key_val_list key_val_list_len) |
|
933 if(NOT key_val_list_len EQUAL "2") |
|
934 message(FATAL_ERROR "Invalid argument: `${entry}` for parameter OVERRIDE_CRATE_TYPE!\n" |
|
935 "${usage_help}" |
|
936 ) |
|
937 endif() |
|
938 list(GET key_val_list "0" package_name) |
|
939 list(GET key_val_list "1" crate_types) |
|
940 list(APPEND override_crate_type_package_name_list "${package_name}") |
|
941 list(APPEND override_crate_type_types_list "${crate_types}") |
|
942 endforeach() |
|
943 list(LENGTH override_crate_type_package_name_list num_override_packages) |
|
944 list(LENGTH override_crate_type_types_list num_override_packages2) |
|
945 if("${Rust_VERSION}" VERSION_LESS "1.64") |
|
946 message(WARNING "OVERRIDE_CRATE_TYPE requires at Rust 1.64 or newer. Ignoring the option") |
|
947 elseif(NOT num_override_packages EQUAL num_override_packages2) |
|
948 message(WARNING "Internal error while parsing OVERRIDE_CRATE_TYPE arguments.\n" |
|
949 "Corrosion will ignore this argument and continue." |
|
950 ) |
|
951 else() |
|
952 # Pass by ref: we intentionally pass the list names here! |
|
953 set(override_crate_types_arg "OVERRIDE_CRATE_TYPE_ARGS" "override_crate_type_package_name_list" "override_crate_type_types_list") |
|
954 endif() |
|
955 endif() |
|
956 |
1050 if (NOT IS_ABSOLUTE "${COR_MANIFEST_PATH}") |
957 if (NOT IS_ABSOLUTE "${COR_MANIFEST_PATH}") |
1051 set(COR_MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${COR_MANIFEST_PATH}) |
958 set(COR_MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${COR_MANIFEST_PATH}) |
1052 endif() |
959 endif() |
1053 |
960 |
1054 set(additional_cargo_flags ${COR_FLAGS}) |
961 set(additional_cargo_flags ${COR_FLAGS}) |
1059 if(COR_FROZEN AND NOT "--frozen" IN_LIST additional_cargo_flags) |
966 if(COR_FROZEN AND NOT "--frozen" IN_LIST additional_cargo_flags) |
1060 list(APPEND additional_cargo_flags "--frozen") |
967 list(APPEND additional_cargo_flags "--frozen") |
1061 endif() |
968 endif() |
1062 |
969 |
1063 set(imported_crates "") |
970 set(imported_crates "") |
1064 if (CORROSION_NATIVE_TOOLING) |
971 |
1065 get_filename_component(manifest_directory "${COR_MANIFEST_PATH}" DIRECTORY) |
972 _generator_add_cargo_targets( |
1066 get_filename_component(toml_dir_name ${manifest_directory} NAME) |
973 MANIFEST_PATH |
1067 |
974 "${COR_MANIFEST_PATH}" |
1068 set( |
975 IMPORTED_CRATES |
1069 generated_cmake |
976 imported_crates |
1070 "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/corrosion/${toml_dir_name}.dir/cargo-build.cmake" |
977 ${crate_allowlist} |
1071 ) |
978 ${crate_types} |
1072 |
979 ${no_linker_override} |
1073 if (CMAKE_VS_PLATFORM_NAME) |
980 ${override_crate_types_arg} |
1074 set (_CORROSION_CONFIGURATION_ROOT --configuration-root ${CMAKE_VS_PLATFORM_NAME}) |
981 ) |
1075 endif() |
|
1076 |
|
1077 set(crates_args) |
|
1078 foreach(crate ${COR_CRATES}) |
|
1079 list(APPEND crates_args --crates ${crate}) |
|
1080 endforeach() |
|
1081 if(DEFINED COR_CRATE_TYPES) |
|
1082 set(crate_types "--crate-type=${COR_CRATE_TYPES}") |
|
1083 endif() |
|
1084 |
|
1085 list(APPEND passthrough_to_acb_args ${no_linker_override}) |
|
1086 if(passthrough_to_acb_args) |
|
1087 # 31 == 0x1f |
|
1088 string(ASCII 31 unit_seperator) |
|
1089 list(JOIN passthrough_to_acb_args "${unit_seperator}" joined_args) |
|
1090 set(passthrough_to_acb "--passthrough-acb=${joined_args}") |
|
1091 endif() |
|
1092 |
|
1093 execute_process( |
|
1094 COMMAND |
|
1095 ${_CORROSION_GENERATOR} |
|
1096 --manifest-path ${COR_MANIFEST_PATH} |
|
1097 gen-cmake |
|
1098 ${_CORROSION_CONFIGURATION_ROOT} |
|
1099 ${crates_args} |
|
1100 ${crate_types} |
|
1101 --imported-crates=imported_crates |
|
1102 ${passthrough_to_acb} |
|
1103 -o ${generated_cmake} |
|
1104 WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
|
1105 RESULT_VARIABLE ret) |
|
1106 |
|
1107 if (NOT ret EQUAL "0") |
|
1108 message(FATAL_ERROR "corrosion-generator failed") |
|
1109 endif() |
|
1110 |
|
1111 include(${generated_cmake}) |
|
1112 else() |
|
1113 _generator_add_cargo_targets( |
|
1114 MANIFEST_PATH |
|
1115 "${COR_MANIFEST_PATH}" |
|
1116 IMPORTED_CRATES |
|
1117 imported_crates |
|
1118 ${crate_allowlist} |
|
1119 ${crate_types} |
|
1120 ${no_linker_override} |
|
1121 ) |
|
1122 endif() |
|
1123 |
982 |
1124 # Not target props yet: |
983 # Not target props yet: |
1125 # NO_STD |
984 # NO_STD |
1126 # NO_LINKER_OVERRIDE # We could simply zero INTERFACE_CORROSION_LINKER if this is set. |
985 # NO_LINKER_OVERRIDE # We could simply zero INTERFACE_CORROSION_LINKER if this is set. |
1127 # LOCKED / FROZEN get merged into FLAGS after cargo metadata. |
986 # LOCKED / FROZEN get merged into FLAGS after cargo metadata. |
1267 if(NOT TARGET "${target_name}-shared") |
1121 if(NOT TARGET "${target_name}-shared") |
1268 # Early return, since Rust won't invoke the linker for static libraries |
1122 # Early return, since Rust won't invoke the linker for static libraries |
1269 return() |
1123 return() |
1270 endif() |
1124 endif() |
1271 endif() |
1125 endif() |
1272 add_dependencies(_cargo-build_${target_name} ${ARGN}) |
|
1273 foreach(library ${ARGN}) |
1126 foreach(library ${ARGN}) |
1274 set_property( |
1127 set_property( |
1275 TARGET _cargo-build_${target_name} |
1128 TARGET _cargo-build_${target_name} |
1276 APPEND |
1129 APPEND |
1277 PROPERTY CARGO_DEPS_LINKER_LANGUAGES |
1130 PROPERTY CARGO_DEPS_LINKER_LANGUAGES |
1278 $<TARGET_PROPERTY:${library},LINKER_LANGUAGE> |
1131 $<TARGET_PROPERTY:${library},LINKER_LANGUAGE> |
1279 ) |
1132 ) |
1280 |
1133 |
1281 corrosion_add_target_local_rustflags(${target_name} "-L$<TARGET_LINKER_FILE_DIR:${library}>") |
1134 if (TARGET "${library}") |
1282 corrosion_add_target_local_rustflags(${target_name} "-l$<TARGET_LINKER_FILE_BASE_NAME:${library}>") |
1135 corrosion_add_target_local_rustflags(${target_name} |
|
1136 "-L$<TARGET_LINKER_FILE_DIR:${library}>" |
|
1137 "-l$<TARGET_LINKER_FILE_BASE_NAME:${library}>" |
|
1138 ) |
|
1139 add_dependencies(_cargo-build_${target_name} ${library}) |
|
1140 elseif(IS_ABSOLUTE "${library}") |
|
1141 # Linking via full path (See https://doc.rust-lang.org/rustc/command-line-arguments.html#linking-modifiers-verbatim) |
|
1142 corrosion_add_target_local_rustflags(${target_name} "-Clink-arg=${library}") |
|
1143 else() |
|
1144 # We have to assume ${library} is a non-CMake library name |
|
1145 corrosion_add_target_local_rustflags(${target_name} "-l${library}") |
|
1146 endif() |
1283 endforeach() |
1147 endforeach() |
1284 endfunction() |
1148 endfunction() |
1285 |
1149 |
|
1150 #[=======================================================================[.md: |
|
1151 ANCHOR: corrosion-install |
|
1152 ** EXPERIMENTAL **: This function is currently still considered experimental |
|
1153 and is not officially released yet. Feedback and Suggestions are welcome. |
|
1154 |
|
1155 ```cmake |
|
1156 corrosion_install(TARGETS <target1> ... <targetN> [EXPORT <export-name>] |
|
1157 [[ARCHIVE|LIBRARY|RUNTIME|PUBLIC_HEADER] |
|
1158 [DESTINATION <dir>] |
|
1159 [PERMISSIONS <permissions...>] |
|
1160 [CONFIGURATIONS [Debug|Release|<other-configuration>]] |
|
1161 ] [...]) |
|
1162 ``` |
|
1163 * **TARGETS**: Target or targets to install. |
|
1164 * **EXPORT**: Creates an export that can be installed with `install(EXPORT)`. <export-name> must be globally unique. |
|
1165 Also creates a file at ${CMAKE_BINARY_DIR}/corrosion/<export-name>Corrosion.cmake that must be included in the installed config file. |
|
1166 * **ARCHIVE**/**LIBRARY**/**RUNTIME**/PUBLIC_HEADER: Designates that the following settings only apply to that specific type of object. |
|
1167 * **DESTINATION**: The subdirectory within the CMAKE_INSTALL_PREFIX that a specific object should be placed. Defaults to values from GNUInstallDirs. |
|
1168 * **PERMISSIONS**: The permissions of files copied into the install prefix. |
|
1169 |
|
1170 Any `PUBLIC` or `INTERFACE` [file sets] will be installed. |
|
1171 |
|
1172 [file sets]: https://cmake.org/cmake/help/latest/command/target_sources.html#file-sets |
|
1173 |
|
1174 ANCHOR_END: corrosion-install |
|
1175 #]=======================================================================] |
1286 function(corrosion_install) |
1176 function(corrosion_install) |
1287 # Default install dirs |
1177 # Default install dirs |
1288 include(GNUInstallDirs) |
1178 include(GNUInstallDirs) |
1289 |
1179 |
1290 # Parse arguments to corrosion_install |
1180 # Parse arguments to corrosion_install |
1434 FILES $<TARGET_FILE:${INSTALL_TARGET}> |
1328 FILES $<TARGET_FILE:${INSTALL_TARGET}> |
1435 DESTINATION ${DESTINATION} |
1329 DESTINATION ${DESTINATION} |
1436 PERMISSIONS ${PERMISSIONS} |
1330 PERMISSIONS ${PERMISSIONS} |
1437 ${CONFIGURATIONS} |
1331 ${CONFIGURATIONS} |
1438 ) |
1332 ) |
|
1333 elseif(TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") |
|
1334 if(TARGET ${INSTALL_TARGET}-static) |
|
1335 if (DEFINED COR_INSTALL_ARCHIVE_DESTINATION) |
|
1336 set(DESTINATION ${COR_INSTALL_ARCHIVE_DESTINATION}) |
|
1337 elseif (DEFINED COR_INSTALL_DEFAULT_DESTINATION) |
|
1338 set(DESTINATION ${COR_INSTALL_DEFAULT_DESTINATION}) |
|
1339 else() |
|
1340 set(DESTINATION ${CMAKE_INSTALL_LIBDIR}) |
|
1341 endif() |
|
1342 |
|
1343 if (DEFINED COR_INSTALL_ARCHIVE_PERMISSIONS) |
|
1344 set(PERMISSIONS ${COR_INSTALL_ARCHIVE_PERMISSIONS}) |
|
1345 elseif (DEFINED COR_INSTALL_DEFAULT_PERMISSIONS) |
|
1346 set(PERMISSIONS ${COR_INSTALL_DEFAULT_PERMISSIONS}) |
|
1347 else() |
|
1348 set(PERMISSIONS ${DEFAULT_PERMISSIONS}) |
|
1349 endif() |
|
1350 |
|
1351 if (DEFINED COR_INSTALL_ARCHIVE_CONFIGURATIONS) |
|
1352 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_ARCHIVE_CONFIGURATIONS}) |
|
1353 elseif (DEFINED COR_INSTALL_DEFAULT_CONFIGURATIONS) |
|
1354 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_DEFAULT_CONFIGURATIONS}) |
|
1355 else() |
|
1356 set(CONFIGURATIONS) |
|
1357 endif() |
|
1358 |
|
1359 install( |
|
1360 FILES $<TARGET_PROPERTY:${INSTALL_TARGET}-static,IMPORTED_LOCATION> |
|
1361 DESTINATION ${DESTINATION} |
|
1362 PERMISSIONS ${PERMISSIONS} |
|
1363 ${CONFIGURATIONS} |
|
1364 ) |
|
1365 |
|
1366 if(EXPORT_NAME) |
|
1367 get_target_property(COR_FILE_NAME ${INSTALL_TARGET}-static COR_FILE_NAME) |
|
1368 file(APPEND "${EXPORT_FILE_PATH}" |
|
1369 " |
|
1370 add_library(${INSTALL_TARGET}-static STATIC IMPORTED) |
|
1371 set_target_properties(${INSTALL_TARGET}-static |
|
1372 PROPERTIES |
|
1373 IMPORTED_LOCATION \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_FILE_NAME}\" |
|
1374 ) |
|
1375 " |
|
1376 ) |
|
1377 endif() |
|
1378 endif() |
|
1379 |
|
1380 if(TARGET ${INSTALL_TARGET}-shared) |
|
1381 if (DEFINED COR_INSTALL_LIBRARY_DESTINATION) |
|
1382 set(DESTINATION ${COR_INSTALL_LIBRARY_DESTINATION}) |
|
1383 elseif (DEFINED COR_INSTALL_DEFAULT_DESTINATION) |
|
1384 set(DESTINATION ${COR_INSTALL_DEFAULT_DESTINATION}) |
|
1385 else() |
|
1386 set(DESTINATION ${CMAKE_INSTALL_LIBDIR}) |
|
1387 endif() |
|
1388 |
|
1389 if (DEFINED COR_INSTALL_LIBRARY_PERMISSIONS) |
|
1390 set(PERMISSIONS ${COR_INSTALL_LIBRARY_PERMISSIONS}) |
|
1391 elseif (DEFINED COR_INSTALL_DEFAULT_PERMISSIONS) |
|
1392 set(PERMISSIONS ${COR_INSTALL_DEFAULT_PERMISSIONS}) |
|
1393 else() |
|
1394 set( |
|
1395 PERMISSIONS |
|
1396 ${DEFAULT_PERMISSIONS} OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE |
|
1397 ) |
|
1398 endif() |
|
1399 |
|
1400 if (DEFINED COR_INSTALL_LIBRARY_CONFIGURATIONS) |
|
1401 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_LIBRARY_CONFIGURATIONS}) |
|
1402 elseif (DEFINED COR_INSTALL_DEFAULT_CONFIGURATIONS) |
|
1403 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_DEFAULT_CONFIGURATIONS}) |
|
1404 else() |
|
1405 set(CONFIGURATIONS) |
|
1406 endif() |
|
1407 |
|
1408 install( |
|
1409 IMPORTED_RUNTIME_ARTIFACTS ${INSTALL_TARGET}-shared |
|
1410 PERMISSIONS ${PERMISSIONS} |
|
1411 DESTINATION ${DESTINATION} |
|
1412 ${CONFIGURATIONS} |
|
1413 ) |
|
1414 |
|
1415 if(EXPORT_NAME) |
|
1416 get_target_property(COR_FILE_NAME ${INSTALL_TARGET}-shared COR_FILE_NAME) |
|
1417 file(APPEND "${EXPORT_FILE_PATH}" |
|
1418 " |
|
1419 add_library(${INSTALL_TARGET}-shared SHARED IMPORTED) |
|
1420 set_target_properties(${INSTALL_TARGET}-shared |
|
1421 PROPERTIES |
|
1422 IMPORTED_LOCATION \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_FILE_NAME}\" |
|
1423 ) |
|
1424 " |
|
1425 ) |
|
1426 |
|
1427 get_target_property(COR_IMPLIB_FILE_NAME ${INSTALL_TARGET}-shared COR_IMPLIB_FILE_NAME) |
|
1428 if (NOT COR_IMPLIB_FILE_NAME MATCHES .*-NOTFOUND) |
|
1429 file(APPEND "${EXPORT_FILE_PATH}" |
|
1430 " |
|
1431 set_target_properties(${INSTALL_TARGET}-shared |
|
1432 PROPERTIES |
|
1433 IMPORTED_IMPLIB \"\${PACKAGE_PREFIX_DIR}/${DESTINATION}/${COR_IMPLIB_FILE_NAME}\" |
|
1434 )" |
|
1435 ) |
|
1436 endif() |
|
1437 endif() |
|
1438 endif() |
|
1439 else() |
|
1440 message(FATAL_ERROR "Unknown target type ${TARGET_TYPE} for install target ${INSTALL_TARGET}") |
|
1441 endif() |
|
1442 |
|
1443 # Executables can also have export tables, so they _might_ also need header files |
|
1444 if (DEFINED COR_INSTALL_PUBLIC_HEADER_DESTINATION) |
|
1445 set(DESTINATION ${COR_INSTALL_PUBLIC_HEADER_DESTINATION}) |
|
1446 elseif (DEFINED COR_INSTALL_DEFAULT_DESTINATION) |
|
1447 set(DESTINATION ${COR_INSTALL_DEFAULT_DESTINATION}) |
|
1448 else() |
|
1449 set(DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) |
|
1450 endif() |
|
1451 |
|
1452 if (DEFINED COR_INSTALL_PUBLIC_HEADER_PERMISSIONS) |
|
1453 set(PERMISSIONS ${COR_INSTALL_PUBLIC_HEADER_PERMISSIONS}) |
|
1454 elseif (DEFINED COR_INSTALL_DEFAULT_PERMISSIONS) |
|
1455 set(PERMISSIONS ${COR_INSTALL_DEFAULT_PERMISSIONS}) |
|
1456 else() |
|
1457 # Directories need OWNER_EXECUTE in order to be deletable by owner |
|
1458 set(PERMISSIONS ${DEFAULT_PERMISSIONS} OWNER_EXECUTE) |
|
1459 endif() |
|
1460 |
|
1461 if (DEFINED COR_INSTALL_PUBLIC_HEADER_CONFIGURATIONS) |
|
1462 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_PUBLIC_HEADER_CONFIGURATIONS}) |
|
1463 elseif (DEFINED COR_INSTALL_DEFAULT_CONFIGURATIONS) |
|
1464 set(CONFIGURATIONS CONFIGURATIONS ${COR_INSTALL_DEFAULT_CONFIGURATIONS}) |
|
1465 else() |
|
1466 set(CONFIGURATIONS) |
|
1467 endif() |
|
1468 |
|
1469 get_target_property(FILE_SET ${INSTALL_TARGET} INTERFACE_HEADER_SETS) |
|
1470 if(NOT FILE_SET OR FILE_SET MATCHES .*-NOTFOUND) |
|
1471 set(TARGET_HAS_FILE_SET FALSE) |
|
1472 else() |
|
1473 set(TARGET_HAS_FILE_SET TRUE) |
|
1474 endif() |
|
1475 |
|
1476 if(NOT TARGET_HAS_FILE_SET) |
|
1477 if(EXPORT_NAME) |
|
1478 # We still need to generate a EXPORT but we can't do that with install(DIRECTORY) |
|
1479 install(TARGETS ${INSTALL_TARGET} ${EXPORT_NAME}) |
|
1480 endif() |
|
1481 |
|
1482 set(PUBLIC_HEADER_PROPERTIES INCLUDE_DIRECTORIES PUBLIC_INCLUDE_DIRECTORIES INTERFACE_INCLUDE_DIRECTORIES) |
|
1483 foreach(PUBLIC_HEADER_PROPERTY ${PUBLIC_HEADER_PROPERTIES}) |
|
1484 get_target_property(PUBLIC_HEADER ${INSTALL_TARGET} ${PUBLIC_HEADER_PROPERTY}) |
|
1485 |
|
1486 if(NOT PUBLIC_HEADER MATCHES .*-NOTFOUND) |
|
1487 foreach(INCLUDE_DIRECTORY ${PUBLIC_HEADER}) |
|
1488 install( |
|
1489 DIRECTORY ${INCLUDE_DIRECTORY} |
|
1490 DESTINATION . |
|
1491 FILE_PERMISSIONS ${PERMISSIONS} |
|
1492 DIRECTORY_PERMISSIONS ${PERMISSIONS} |
|
1493 ${CONFIGURATIONS} |
|
1494 ) |
|
1495 endforeach() |
|
1496 endif() |
|
1497 endforeach() |
|
1498 else() |
|
1499 install( |
|
1500 TARGETS ${INSTALL_TARGET} |
|
1501 ${EXPORT_NAME} |
|
1502 FILE_SET HEADERS |
|
1503 DESTINATION ${DESTINATION} |
|
1504 PERMISSIONS ${PERMISSIONS} |
|
1505 ${CONFIGURATIONS} |
|
1506 ) |
1439 endif() |
1507 endif() |
1440 endforeach() |
1508 endforeach() |
1441 |
1509 |
1442 elseif(INSTALL_TYPE STREQUAL "EXPORT") |
1510 elseif(INSTALL_TYPE STREQUAL "EXPORT") |
1443 message(FATAL_ERROR "install(EXPORT ...) not yet implemented") |
1511 message(FATAL_ERROR "install(EXPORT ...) not yet implemented") |
|
1512 else() |
|
1513 message(FATAL_ERROR "Unknown arg: ${INSTALL_TYPE}") |
1444 endif() |
1514 endif() |
1445 endfunction() |
1515 endfunction() |
1446 |
1516 |
1447 #[=======================================================================[.md: |
1517 #[=======================================================================[.md: |
1448 ** EXPERIMENTAL **: This function is currently still considered experimental |
1518 ** EXPERIMENTAL **: This function is currently still considered experimental |
1663 COMMAND |
1741 COMMAND |
1664 ${cxxbridge} ${rust_source_path} |
1742 ${cxxbridge} ${rust_source_path} |
1665 --output "${source_placement_dir}/${cxx_source}" |
1743 --output "${source_placement_dir}/${cxx_source}" |
1666 --include "${cxx_target}/${cxx_header}" |
1744 --include "${cxx_target}/${cxx_header}" |
1667 DEPENDS "cxxbridge_v${cxx_required_version}" "${rust_source_path}" |
1745 DEPENDS "cxxbridge_v${cxx_required_version}" "${rust_source_path}" |
1668 COMMENT "Generating cxx bindings for crate ${_arg_CRATE}" |
1746 COMMENT "Generating cxx bindings for crate ${_arg_CRATE} and file src/${filepath}" |
1669 ) |
1747 ) |
1670 |
1748 |
1671 target_sources(${cxx_target} |
1749 list(APPEND GENERATED_FILES |
1672 PRIVATE |
1750 "${header_placement_dir}/${cxx_header}" |
1673 "${header_placement_dir}/${cxx_header}" |
1751 "${source_placement_dir}/${cxx_source}") |
1674 "${generated_dir}/include/rust/cxx.h" |
|
1675 "${source_placement_dir}/${cxx_source}" |
|
1676 ) |
|
1677 endforeach() |
1752 endforeach() |
|
1753 target_sources(${cxx_target} PRIVATE ${GENERATED_FILES}) |
|
1754 |
|
1755 if(DEFINED _arg_REGEN_TARGET) |
|
1756 add_custom_target(${_arg_REGEN_TARGET} |
|
1757 DEPENDS ${GENERATED_FILES} |
|
1758 COMMENT "Generated cxx bindings for crate ${_arg_CRATE}") |
|
1759 endif() |
|
1760 |
1678 endfunction() |
1761 endfunction() |
1679 |
1762 |
1680 #[=======================================================================[.md: |
1763 #[=======================================================================[.md: |
1681 ANCHOR: corrosion_cbindgen |
1764 ANCHOR: corrosion_cbindgen |
1682 ```cmake |
1765 ```cmake |
1683 corrosion_cbindgen( |
1766 corrosion_cbindgen( |
1684 TARGET <imported_target_name> |
1767 TARGET <imported_target_name> |
1685 HEADER_NAME <output_header_name> |
1768 HEADER_NAME <output_header_name> |
|
1769 [CARGO_PACKAGE <cargo_package_name>] |
1686 [MANIFEST_DIRECTORY <package_manifest_directory>] |
1770 [MANIFEST_DIRECTORY <package_manifest_directory>] |
1687 [CBINDGEN_VERSION <version>] |
1771 [CBINDGEN_VERSION <version>] |
1688 [FLAGS <flag1> ... <flagN>] |
1772 [FLAGS <flag1> ... <flagN>] |
1689 ) |
1773 ) |
1690 ``` |
1774 ``` |
1708 * **CBINDGEN_VERSION**: Version requirement for cbindgen. Exact semantics to be specified. Currently not implemented. |
1792 * **CBINDGEN_VERSION**: Version requirement for cbindgen. Exact semantics to be specified. Currently not implemented. |
1709 * **FLAGS**: Arbitrary other flags for `cbindgen`. Run `cbindgen --help` to see the possible flags. |
1793 * **FLAGS**: Arbitrary other flags for `cbindgen`. Run `cbindgen --help` to see the possible flags. |
1710 |
1794 |
1711 [cbindgen]: https://github.com/eqrion/cbindgen |
1795 [cbindgen]: https://github.com/eqrion/cbindgen |
1712 |
1796 |
|
1797 ### Current limitations |
|
1798 |
|
1799 - Cbindgens (optional) macro expansion feature internally actually builds the crate / runs the build script. |
|
1800 For this to work as expected in all cases, we probably need to set all the same environment variables |
|
1801 as when corrosion builds the crate. However the crate is a **library**, so we would need to figure out which |
|
1802 target builds it - and if there are multiple, potentially generate bindings per-target? |
|
1803 Alternatively we could add support of setting some environment variables on rlibs, and pulling that |
|
1804 information in when building the actual corrosion targets |
|
1805 Alternatively we could restrict corrosions support of this feature to actual imported staticlib/cdylib targets. |
1713 ANCHOR_END: corrosion_cbindgen |
1806 ANCHOR_END: corrosion_cbindgen |
1714 #]=======================================================================] |
1807 #]=======================================================================] |
1715 function(corrosion_experimental_cbindgen) |
1808 function(corrosion_experimental_cbindgen) |
1716 set(OPTIONS "") |
1809 set(OPTIONS "") |
1717 set(ONE_VALUE_KEYWORDS TARGET MANIFEST_DIRECTORY HEADER_NAME CBINDGEN_VERSION) |
1810 set(ONE_VALUE_KEYWORDS |
|
1811 TARGET |
|
1812 MANIFEST_DIRECTORY |
|
1813 HEADER_NAME |
|
1814 CBINDGEN_VERSION) |
1718 set(MULTI_VALUE_KEYWORDS "FLAGS") |
1815 set(MULTI_VALUE_KEYWORDS "FLAGS") |
1719 cmake_parse_arguments(PARSE_ARGV 0 CCN "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}") |
1816 cmake_parse_arguments(PARSE_ARGV 0 CCN "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}") |
1720 |
1817 |
1721 set(required_keywords TARGET HEADER_NAME) |
1818 set(required_keywords TARGET HEADER_NAME) |
1722 foreach(keyword ${required_keywords}) |
1819 foreach(keyword ${required_keywords}) |
1826 unset(depfile_cmake_arg) |
1919 unset(depfile_cmake_arg) |
1827 get_filename_component(generated_depfile_dir "${generated_depfile}" DIRECTORY) |
1920 get_filename_component(generated_depfile_dir "${generated_depfile}" DIRECTORY) |
1828 file(MAKE_DIRECTORY "${generated_depfile_dir}") |
1921 file(MAKE_DIRECTORY "${generated_depfile_dir}") |
1829 set(depfile_cbindgen_arg "--depfile=${generated_depfile}") |
1922 set(depfile_cbindgen_arg "--depfile=${generated_depfile}") |
1830 |
1923 |
1831 # Users might want to call cbindgen multiple times, e.g. to generate separate C++ and C header files. |
1924 add_custom_command( |
1832 string(MAKE_C_IDENTIFIER "${output_header_name}" header_identifier ) |
1925 OUTPUT |
1833 if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.22") |
1926 "${generated_header}" |
1834 add_custom_command( |
1927 COMMAND |
1835 OUTPUT |
1928 "${CMAKE_COMMAND}" -E env |
1836 "${generated_header}" |
1929 TARGET="${cbindgen_target_triple}" |
1837 COMMAND |
1930 "${cbindgen}" |
1838 "${CMAKE_COMMAND}" -E env |
1931 --output "${generated_header}" |
1839 TARGET="${cbindgen_target_triple}" |
1932 --crate "${rust_cargo_package}" |
1840 "${cbindgen}" |
1933 ${depfile_cbindgen_arg} |
1841 --output "${generated_header}" |
1934 ${CCN_FLAGS} |
1842 --crate "${rust_cargo_package}" |
1935 COMMENT "Generate cbindgen bindings for package ${rust_cargo_package} and output header ${generated_header}" |
1843 ${depfile_cbindgen_arg} |
1936 DEPFILE "${generated_depfile}" |
1844 ${CCN_FLAGS} |
1937 COMMAND_EXPAND_LISTS |
1845 COMMENT "Generate cbindgen bindings for package ${rust_cargo_package} and output header ${generated_header}" |
1938 WORKING_DIRECTORY "${package_manifest_dir}" |
1846 DEPFILE "${generated_depfile}" |
1939 ) |
1847 COMMAND_EXPAND_LISTS |
|
1848 WORKING_DIRECTORY "${package_manifest_dir}" |
|
1849 ) |
|
1850 add_custom_target("_corrosion_cbindgen_${rust_target}_bindings_${header_identifier}" |
|
1851 DEPENDS "${generated_header}" |
|
1852 COMMENT "Generate ${generated_header} for ${rust_target}" |
|
1853 ) |
|
1854 else() |
|
1855 add_custom_target("_corrosion_cbindgen_${rust_target}_bindings_${header_identifier}" |
|
1856 "${CMAKE_COMMAND}" -E env |
|
1857 TARGET="${cbindgen_target_triple}" |
|
1858 "${cbindgen}" |
|
1859 --output "${generated_header}" |
|
1860 --crate "${rust_cargo_package}" |
|
1861 ${depfile_cbindgen_arg} |
|
1862 ${CCN_FLAGS} |
|
1863 COMMENT "Generate ${generated_header} for ${rust_target}" |
|
1864 COMMAND_EXPAND_LISTS |
|
1865 WORKING_DIRECTORY "${package_manifest_dir}" |
|
1866 ) |
|
1867 endif() |
|
1868 |
1940 |
1869 if(NOT installed_cbindgen) |
1941 if(NOT installed_cbindgen) |
1870 add_custom_command( |
1942 add_custom_command( |
1871 OUTPUT "${generated_header}" |
1943 OUTPUT "${generated_header}" |
1872 APPEND |
1944 APPEND |