-
Notifications
You must be signed in to change notification settings - Fork 57
/
CMakeLists.txt
325 lines (294 loc) · 13.4 KB
/
CMakeLists.txt
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
cmake_minimum_required(VERSION 3.16)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.txt version)
project(
zenohc
VERSION ${version}
DESCRIPTION "The C bindings for Zenoh"
HOMEPAGE_URL "https://github.com/eclipse-zenoh/zenoh-c"
LANGUAGES C CXX
)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
include(helpers)
set_default_build_type(Release)
enable_testing()
#
# Build zenohc library from rust sources
#
# target zenohc::lib - for linking zenoh-c as static or dynamic library depending on BUILD_SHARED_LIBS boolean cache var
# target zenohc::static - for linking zenoh-c as static library
# target zenohc::shared - for linking zenoh-c as dynamic library
#
#
# Configuration options
#
declare_cache_var_true_if_vscode(ZENOHC_BUILD_IN_SOURCE_TREE "Do build inside source tree")
declare_cache_var(ZENOHC_BUILD_WITH_SHARED_MEMORY FALSE BOOL "Enable shared-memory zenoh-c feature")
declare_cache_var(ZENOHC_BUILD_WITH_UNSTABLE_API FALSE BOOL "Enable unstable API feature")
declare_cache_var(ZENOHC_BUILD_TESTS_WITH_CXX FALSE BOOL "Use C++ compiler for building tests to check API's C++ compatibility")
declare_cache_var(ZENOHC_CUSTOM_TARGET "" STRING "Rust target for cross compilation, 'aarch64-unknown-linux-gnu' for example")
declare_cache_var(ZENOHC_CARGO_CHANNEL "" STRING "Cargo channel parameter. Should be '+stable', '+nightly' or empty value")
declare_cache_var(ZENOHC_CARGO_FLAGS "" STRING "Additional cargo flags")
declare_cache_var(BUILD_SHARED_LIBS TRUE BOOL "Alias zenohc::lib target to zenohc::shared if TRUE, to zenohc::static if FALSE")
declare_cache_var(ZENOHC_TREAT_WARNING_AS_ERROR OFF BOOL "Whether to treat compilation warnings as errors")
set(CMAKE_COMPILE_WARNING_AS_ERROR ${ZENOHC_TREAT_WARNING_AS_ERROR})
set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
if(PROJECT_VERSION_TWEAK STREQUAL "")
set(project_version "${project_version}")
elseif(PROJECT_VERSION_TWEAK EQUAL 0)
set(project_version "${project_version}-dev")
elseif(PROJECT_VERSION_TWEAK GREATER 0)
set(project_version "${project_version}-pre.${PROJECT_VERSION_TWEAK}")
endif()
status_print(project_version)
#
# There are 3 possible variants of placement generated Cargo.toml files:
# 1. Build in source tree (in IDE usually), using single config generator (Ninja, Makefiles)
#
# In this case Cargo.toml is placed at the root of source tree to make it visible for rust-analyzer. When release or debug
# configuration is selected, Cargo.toml is updated accordingly
#
# 2. Build in source tree (in IDE usually), using multi config generator (Visual Studio, Ninja Multi-Config)
#
# Cargo.toml is placed at the root of source tree to make it visible for rust-analyzer. Also two additional Cargo.toml files
# are placed in ${CMAKE_CURRENT_BINARY_DIR}/debug and ${CMAKE_CURRENT_BINARY_DIR}/release directories configured for debug and
# release builds respectively
#
# 3. Build in build tree, no matter what generator is used
#
# Cargo.toml is placed in ${CMAKE_CURRENT_BINARY_DIR}/debug and ${CMAKE_CURRENT_BINARY_DIR}/release directories. No care is taken
# about Cargo.toml at the root of source tree
#
if(ZENOHC_BUILD_IN_SOURCE_TREE AND(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}))
set(cargo_toml_dir_ide ${CMAKE_SOURCE_DIR})
if (GENERATOR_IS_MULTI_CONFIG)
message(STATUS "Mode: IDE, Multi-Config generator (${CMAKE_GENERATOR}))")
set(cargo_toml_dir_debug ${CMAKE_CURRENT_BINARY_DIR}/debug)
set(cargo_toml_dir_release ${CMAKE_CURRENT_BINARY_DIR}/release)
file(MAKE_DIRECTORY ${cargo_toml_dir_debug}/include)
file(MAKE_DIRECTORY ${cargo_toml_dir_release}/include)
else()
message(STATUS "Mode: IDE, Single-Config generator (${CMAKE_GENERATOR})")
set(cargo_toml_dir_debug ${cargo_toml_dir_ide})
set(cargo_toml_dir_release ${cargo_toml_dir_ide})
endif()
else()
message(STATUS "Mode: Non-IDE")
unset(cargo_toml_dir_ide)
set(cargo_toml_dir_debug ${CMAKE_CURRENT_BINARY_DIR}/debug)
set(cargo_toml_dir_release ${CMAKE_CURRENT_BINARY_DIR}/release)
file(MAKE_DIRECTORY ${cargo_toml_dir_debug}/include)
file(MAKE_DIRECTORY ${cargo_toml_dir_release}/include)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEBUG TRUE)
endif()
set_genexpr_condition(cargo_toml_dir DEBUG $<CONFIG:Debug> ${cargo_toml_dir_debug} ${cargo_toml_dir_release})
set_genexpr_condition(cargo_generated_include_dir DEBUG $<CONFIG:Debug> ${cargo_toml_dir_debug}/include ${cargo_toml_dir_release}/include)
set(cargo_target_dir_debug ${cargo_toml_dir_debug}/target)
set(cargo_target_dir_release ${cargo_toml_dir_release}/target)
if(NOT(ZENOHC_CUSTOM_TARGET STREQUAL ""))
set(cargo_target_dir_debug ${cargo_target_dir_debug}/${ZENOHC_CUSTOM_TARGET})
set(cargo_target_dir_release ${cargo_target_dir_release}/${ZENOHC_CUSTOM_TARGET})
endif()
set(cargo_binary_dir_debug ${cargo_target_dir_debug}/debug)
set(cargo_binary_dir_release ${cargo_target_dir_release}/release)
set_genexpr_condition(cargo_binary_dir DEBUG $<CONFIG:Debug> ${cargo_binary_dir_debug} ${cargo_binary_dir_release})
set(source_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
function(configure_cargo_toml cargo_toml_dir CARGO_PROJECT_VERSION CARGO_LIB_NAME)
message(STATUS "Configuring Cargo.toml in ${cargo_toml_dir} for ${CARGO_LIB_NAME}")
if(NOT(cargo_toml_dir STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}))
set(CARGO_PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/")
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/splitguide.yaml
${CMAKE_CURRENT_SOURCE_DIR}/cbindgen.toml
${CMAKE_CURRENT_SOURCE_DIR}/Cargo.lock
${CMAKE_CURRENT_SOURCE_DIR}/rust-toolchain.toml
${CMAKE_CURRENT_SOURCE_DIR}/version.txt
DESTINATION ${cargo_toml_dir})
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh.h
${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh_memory.h
${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh_constants.h
DESTINATION ${cargo_toml_dir}/include/)
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml.in" "${cargo_toml_dir}/Cargo.toml" @ONLY)
endfunction()
#
# Configure Cargo.toml files
#
set(cargo_lib_name_debug zenohcd)
set(cargo_lib_name_release zenohc)
if(cargo_toml_dir_debug STREQUAL cargo_toml_dir_release)
# same Cargo.toml is for ide, debug and release configurations
# This happens only for non-multiconfig generators, so testing for debug/release on configuration stage is allowed
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(cargo_lib_name ${cargo_lib_name_debug})
else()
set(cargo_lib_name ${cargo_lib_name_release})
endif()
configure_cargo_toml(${cargo_toml_dir_ide} ${project_version} ${cargo_lib_name})
else()
set_genexpr_condition(cargo_lib_name DEBUG $<CONFIG:Debug> ${cargo_lib_name_debug} ${cargo_lib_name_release})
if(DEFINED cargo_toml_dir_ide)
configure_cargo_toml(${cargo_toml_dir_ide} ${project_version} ${cargo_lib_name_release})
endif()
configure_cargo_toml(${cargo_toml_dir_debug} ${project_version} ${cargo_lib_name_debug})
configure_cargo_toml(${cargo_toml_dir_release} ${project_version} ${cargo_lib_name_release})
endif()
#
# Copy toolchain configuration to build directory to ensure it is used when cargo is invoked from a directory other
# than the directory containing the manifest file
#
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/rust-toolchain.toml")
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/rust-toolchain.toml
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif()
#
# Configure result library names
#
macro(set_lib list var value)
set(${var} ${value})
list(APPEND ${list} ${value})
endmacro()
# dylib[r|d] - dymamic library (.so, .dll, .dylib)
# staticlib[r|d] - static library (.a, .lib)
# implib[r|d] - import library for windows dynamic library (DLL) - .lib
# dylibs[r|d] - list of files required for use dynamic library
# staticlibs[r|d] - list of files required for use static library
# get rust output library names from https://github.com/corrosion-rs/corrosion/blob/1c6974c2473765449e7c4649f9f96f1b751420c3/cmake/Corrosion.cmake#L331
if(WIN32)
set_lib(dylibsr dylibr zenohc.dll)
set_lib(dylibsd dylibd zenohcd.dll)
if(MSVC)
set_lib(staticlibsr staticlibr zenohc.lib)
set_lib(staticlibsd staticlibd zenohcd.lib)
set_lib(dylibsr implibr zenohc.dll.lib)
set_lib(dylibsd implibd zenohcd.dll.lib)
else() #gnu/mingw/msys ?
set_lib(staticlibsr staticlibr libzenohc.a)
set_lib(staticlibsd staticlibd libzenohcd.a)
set_lib(dylibsr implibr libzenohc.dll.a)
set_lib(dylibsd implibd libzenohcd.dll.a)
endif()
elseif(APPLE)
set_lib(dylibsr dylibr libzenohc.dylib)
set_lib(dylibsd dylibd libzenohcd.dylib)
set_lib(staticlibsr staticlibr libzenohc.a)
set_lib(staticlibsd staticlibd libzenohcd.a)
else() #UNIX
set_lib(dylibsr dylibr libzenohc.so)
set_lib(dylibsd dylibd libzenohcd.so)
set_lib(staticlibsr staticlibr libzenohc.a)
set_lib(staticlibsd staticlibd libzenohcd.a)
endif()
list(APPEND libsr ${dylibsr})
list(APPEND libsr ${staticlibsr})
list(APPEND libsd ${dylibsd})
list(APPEND libsd ${staticlibsd})
list(TRANSFORM libsr PREPEND "${cargo_binary_dir_release}/")
list(TRANSFORM libsd PREPEND "${cargo_binary_dir_debug}/")
set_genexpr_condition(libs DEBUG $<CONFIG:Debug> "${libsd}" "${libsr}")
#
# Build rust sources
#
# Combine "--release" and "--manifest-path" options under DEBUG condition to avoid passing empty parameter to cargo command line in `add_custom_command`, causing build failure
# This empty item ($<IF:$<CONFIG:Debug>;,--release>) can't be filtered out by `list(FILTER ...)` because it becomes empty only on
# build stage when generator expressions are evaluated.
set_genexpr_condition(cargo_flags DEBUG $<CONFIG:Debug>
"--manifest-path=${cargo_toml_dir_debug}/Cargo.toml"
"--release;--manifest-path=${cargo_toml_dir_release}/Cargo.toml")
set(cargo_flags ${cargo_flags} ${ZENOHC_CARGO_FLAGS})
if(ZENOHC_BUILD_WITH_SHARED_MEMORY)
set(cargo_flags ${cargo_flags} --features=shared-memory)
elseif("${cargo_flags}" MATCHES ^.*shared-memory.*$)
set(ZENOHC_BUILD_WITH_SHARED_MEMORY TRUE)
message(STATUS "Due to ZENOHC_CARGO_FLAGS setting ZENOHC_BUILD_WITH_SHARED_MEMORY = TRUE")
endif()
if(ZENOHC_BUILD_WITH_UNSTABLE_API)
set(cargo_flags ${cargo_flags} --features=unstable)
elseif("${cargo_flags}" MATCHES ^.*unstable.*$)
set(ZENOHC_BUILD_WITH_UNSTABLE_API TRUE)
message(STATUS "Due to ZENOHC_CARGO_FLAGS setting ZENOHC_BUILD_WITH_UNSTABLE_API = TRUE")
endif()
if(NOT(ZENOHC_CUSTOM_TARGET STREQUAL ""))
set(cargo_flags ${cargo_flags} --target=${ZENOHC_CUSTOM_TARGET})
endif()
status_print(cargo_flags)
status_print(libs)
file(GLOB_RECURSE rust_sources "Cargo.toml.in" "src/*.rs" "build.rs" "splitguide.yaml")
add_custom_command(
OUTPUT ${libs}
COMMAND ${CMAKE_COMMAND} -E echo \"RUSTFLAGS = $$RUSTFLAGS\"
COMMAND ${CMAKE_COMMAND} -E echo \"cargo ${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}\"
COMMAND cargo ${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}
VERBATIM
COMMAND_EXPAND_LISTS
DEPENDS "${rust_sources}"
)
add_custom_target(cargo ALL DEPENDS "${libs}")
#
# Define libraries built by cargo as targets
#
function(set_target_imported_locations target libr libd)
set_target_properties(${target}
PROPERTIES
IMPORTED_GLOBAL TRUE
IMPORTED_LOCATION_DEBUG ${cargo_binary_dir_debug}/${libd}
IMPORTED_LOCATION_RELEASE ${cargo_binary_dir_release}/${libr}
IMPORTED_LOCATION_MINSIZEREL ${cargo_binary_dir_release}/${libr}
IMPORTED_LOCATION_RELWITHDEBINFO ${cargo_binary_dir_release}/${libr}
)
endfunction()
function(set_target_imported_implib target libr libd)
set_target_properties(${target}
PROPERTIES
IMPORTED_GLOBAL TRUE
IMPORTED_IMPLIB_DEBUG ${cargo_binary_dir_debug}/${libd}
IMPORTED_IMPLIB_RELEASE ${cargo_binary_dir_release}/${libr}
IMPORTED_IMPLIB_MINSIZEREL ${cargo_binary_dir_release}/${libr}
IMPORTED_IMPLIB_RELWITHDEBINFO ${cargo_binary_dir_release}/${libr}
)
endfunction()
#
# Setup additional properties for library targets
# *IMPORTANT* any options in this section should be repeated in install/PackageConfig.cmake.in
# to achieve correct behavior of find_package(zenohc)
#
add_library(zenohc_shared SHARED IMPORTED GLOBAL)
add_library(zenohc::shared ALIAS zenohc_shared)
add_dependencies(zenohc_shared cargo)
target_compile_definitions(zenohc_shared INTERFACE ZENOHC_DYN_LIB)
# Workaroud for https://github.com/rust-lang/cargo/issues/5045
# mentioned in https://github.com/eclipse-zenoh/zenoh-c/issues/138
# If it's fixed, do not forget to correct PackageConfig.cmake.in also
set_target_properties(zenohc_shared PROPERTIES IMPORTED_NO_SONAME TRUE)
set_target_imported_locations(zenohc_shared ${dylibr} ${dylibd})
add_library(zenohc_static STATIC IMPORTED GLOBAL)
add_library(zenohc::static ALIAS zenohc_static)
add_dependencies(zenohc_static cargo)
get_required_static_libs(NATIVE_STATIC_LIBS)
target_link_libraries(zenohc_static INTERFACE ${NATIVE_STATIC_LIBS})
set_target_imported_locations(zenohc_static ${staticlibr} ${staticlibd})
target_include_directories(zenohc_static INTERFACE ${cargo_generated_include_dir})
set_target_properties(zenohc_static PROPERTIES IMPORTED_GLOBAL TRUE)
if(DEFINED implibr)
set_target_imported_implib(zenohc_shared ${implibr} ${implibd})
endif()
target_include_directories(zenohc_shared INTERFACE ${cargo_generated_include_dir})
set_target_properties(zenohc_shared PROPERTIES IMPORTED_GLOBAL TRUE)
if (BUILD_SHARED_LIBS)
add_library(zenohc::lib ALIAS zenohc_shared)
else()
add_library(zenohc::lib ALIAS zenohc_static)
endif()
#
# Components included only if project is the root project
#
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(install)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${cargo_binary_dir}/tests)
add_subdirectory(tests)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${cargo_binary_dir}/examples)
add_subdirectory(examples)
endif()