-
Notifications
You must be signed in to change notification settings - Fork 54
/
CMakeLists.txt
304 lines (274 loc) · 12.7 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
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_LOGGER_AUTOINIT TRUE BOOL "Enable logger-autoinit zenoh-c feature")
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")
#
# Setup project version
#
set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
if(NOT DEFINED PROJECT_VERSION_TWEAK)
set(project_version "${project_version}")
elseif(PROJECT_VERSION_TWEAK EQUAL 0)
set(project_version "${project_version}-dev")
elseif(PROJECT_VERSION_TWEAK GREATER 1)
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
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 libraty
# staticlibs[r|d] - list of files required for use static libraty
set_lib(dylibsr dylibr ${CMAKE_SHARED_LIBRARY_PREFIX}zenohc${CMAKE_SHARED_LIBRARY_SUFFIX})
set_lib(dylibsd dylibd ${CMAKE_SHARED_LIBRARY_PREFIX}zenohcd${CMAKE_SHARED_LIBRARY_SUFFIX})
set_lib(staticlibsr staticlibr ${CMAKE_STATIC_LIBRARY_PREFIX}zenohc${CMAKE_STATIC_LIBRARY_SUFFIX})
set_lib(staticlibsd staticlibd ${CMAKE_STATIC_LIBRARY_PREFIX}zenohcd${CMAKE_STATIC_LIBRARY_SUFFIX})
if(WIN32)
set_lib(dylibsr implibr ${CMAKE_IMPORT_LIBRARY_PREFIX}zenohc${CMAKE_SHARED_LIBRARY_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX})
set_lib(dylibsd implibd ${CMAKE_IMPORT_LIBRARY_PREFIX}zenohcd${CMAKE_SHARED_LIBRARY_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX})
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_LOGGER_AUTOINIT)
set(cargo_flags ${cargo_flags} --features=logger-autoinit)
endif()
if(ZENOHC_BUILD_WITH_SHARED_MEMORY)
set(cargo_flags ${cargo_flags} --features=shared-memory)
endif()
if(ZENOHC_BUILD_WITH_UNSTABLE_API)
set(cargo_flags ${cargo_flags} --features=unstable)
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)
#
if (BUILD_SHARED_LIBS)
add_library(zenohc_shared SHARED IMPORTED GLOBAL)
add_library(zenohc::lib 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})
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)
else()
add_library(zenohc_static STATIC IMPORTED GLOBAL)
add_library(zenohc::lib ALIAS zenohc_static)
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)
endif()
#
# Components included only if project is the root project
#
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
include(cmake/cross_build_check.cmake)
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()