-
Notifications
You must be signed in to change notification settings - Fork 147
/
CMakeLists.txt
408 lines (350 loc) · 14.3 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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
cmake_minimum_required(VERSION 3.5...3.28.1)
project(libnetconf2 C)
# include custom Modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/")
include(GNUInstallDirs)
include(CheckFunctionExists)
include(CheckCSourceCompiles)
include(CheckIncludeFile)
include(UseCompat)
include(ABICheck)
include(SourceFormat)
include(GenDoc)
include(GenCoverage)
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
# set default build type if not specified by user
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# see https://github.com/CESNET/libyang/pull/1692 for why CMAKE_C_FLAGS_<type> are not used directly
# normalize build type string
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER)
if ("${BUILD_TYPE_UPPER}" STREQUAL "RELEASE")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
set(CMAKE_C_FLAGS "-DNDEBUG -O2 ${CMAKE_C_FLAGS}")
elseif("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
set(CMAKE_C_FLAGS "-g -O0 ${CMAKE_C_FLAGS}")
elseif("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO")
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build Type" FORCE)
elseif("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBUG")
set(CMAKE_BUILD_TYPE "RelWithDebug" CACHE STRING "Build Type" FORCE)
elseif("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
set(CMAKE_BUILD_TYPE "ABICheck" CACHE STRING "Build Type" FORCE)
set(CMAKE_C_FLAGS "-g -Og ${CMAKE_C_FLAGS}")
elseif("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY")
set(CMAKE_BUILD_TYPE "DocOnly" CACHE STRING "Build Type" FORCE)
endif()
#
# variables
#
set(LIBNETCONF2_DESCRIPTION "NETCONF server and client library in C.")
# osx specific
set(CMAKE_MACOSX_RPATH TRUE)
# Version of the project
# Generic version of not only the library. Major version is reserved for really big changes of the project,
# minor version changes with added functionality (new tool, functionality of the tool or library, ...) and
# micro version is changed with a set of small changes or bugfixes anywhere in the project.
set(LIBNETCONF2_MAJOR_VERSION 3)
set(LIBNETCONF2_MINOR_VERSION 5)
set(LIBNETCONF2_MICRO_VERSION 1)
set(LIBNETCONF2_VERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION}.${LIBNETCONF2_MICRO_VERSION})
# Version of the library
# Major version is changed with every backward non-compatible API/ABI change in libyang, minor version changes
# with backward compatible change and micro version is connected with any internal change of the library.
set(LIBNETCONF2_MAJOR_SOVERSION 4)
set(LIBNETCONF2_MINOR_SOVERSION 4)
set(LIBNETCONF2_MICRO_SOVERSION 1)
set(LIBNETCONF2_SOVERSION_FULL ${LIBNETCONF2_MAJOR_SOVERSION}.${LIBNETCONF2_MINOR_SOVERSION}.${LIBNETCONF2_MICRO_SOVERSION})
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_SOVERSION})
# Version of libyang library that this project depends on
set(LIBYANG_DEP_VERSION 2.0.0)
set(LIBYANG_DEP_SOVERSION 3.0.0)
set(LIBYANG_DEP_SOVERSION_MAJOR 3)
# global C flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fvisibility=hidden -std=c99")
#
# options
#
if(("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") OR ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO"))
option(ENABLE_TESTS "Build tests" ON)
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" ON)
else()
option(ENABLE_TESTS "Build tests" OFF)
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF)
endif()
option(ENABLE_EXAMPLES "Build examples" ON)
option(ENABLE_COVERAGE "Build code coverage report from tests" OFF)
option(ENABLE_SSH_TLS "Enable NETCONF over SSH and TLS support (via libssh and OpenSSL)" ON)
option(ENABLE_DNSSEC "Enable support for SSHFP retrieval using DNSSEC for SSH (requires OpenSSL and libval)" OFF)
option(ENABLE_COMMON_TARGETS "Define common custom target names such as 'doc' or 'uninstall', may cause conflicts when using add_subdirectory() to build this project" ON)
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
set(READ_INACTIVE_TIMEOUT 20 CACHE STRING "Maximum number of seconds waiting for new data once some data have arrived")
set(READ_ACTIVE_TIMEOUT 300 CACHE STRING "Maximum number of seconds for receiving a full message")
set(MAX_PSPOLL_THREAD_COUNT 6 CACHE STRING "Maximum number of threads that could simultaneously access a ps_poll structure")
set(TIMEOUT_STEP 100 CACHE STRING "Number of microseconds tasks are repeated until timeout elapses")
set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/libnetconf2" CACHE STRING "Directory where to copy the YANG modules to")
set(CLIENT_SEARCH_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules" CACHE STRING "Default NC client YANG module search directory")
#
# sources
#
set(libsrc
src/io.c
src/log.c
src/messages_client.c
src/messages_server.c
src/session.c
src/session_client.c
src/session_server.c
src/server_config.c
src/server_config_util.c)
if(ENABLE_SSH_TLS)
list(APPEND libsrc
src/session_client_ssh.c
src/session_server_ssh.c
src/server_config_util_ssh.c
src/session_client_tls.c
src/session_server_tls.c
src/server_config_util_tls.c
src/server_config_ks.c
src/server_config_ts.c)
set(SSH_TLS_MACRO "#ifndef NC_ENABLED_SSH_TLS\n#define NC_ENABLED_SSH_TLS\n#endif")
endif()
set(headers
src/log.h
src/netconf.h
src/session.h
src/messages_client.h
src/messages_server.h
src/session_client.h
src/session_client_ch.h
src/session_server.h
src/session_server_ch.h
src/server_config.h)
# files to generate doxygen from
set(doxy_files
doc/libnetconf.doc
src/log.h
src/netconf.h
src/session.h
src/messages_client.h
src/messages_server.h
src/session_client.h
src/session_client_ch.h
src/session_server.h
src/session_server_ch.h
src/server_config.h)
# source files to be covered by the 'format' target
set(format_sources
compat/*.c
compat/*.h*
examples/*.c
examples/*.h*
src/*.c
src/*.h
tests/*.c)
#
# checks
#
if(ENABLE_DNSSEC AND NOT ENABLE_SSH_TLS)
message(WARNING "DNSSEC SSHFP retrieval cannot be used without SSH support.")
set(ENABLE_DNSSEC OFF)
endif()
if(ENABLE_VALGRIND_TESTS)
find_program(VALGRIND_FOUND valgrind)
if(NOT VALGRIND_FOUND)
message(WARNING "valgrind executable not found! Disabling memory leaks tests.")
set(ENABLE_VALGRIND_TESTS OFF)
else()
set(ENABLE_TESTS ON)
endif()
endif()
if(ENABLE_TESTS)
find_package(CMocka 1.0.1)
if(NOT CMOCKA_FOUND)
message(STATUS "Disabling tests because of missing CMocka")
set(ENABLE_TESTS OFF)
endif()
endif()
if(ENABLE_COVERAGE)
gen_coverage_enable(${ENABLE_TESTS})
endif()
if ("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
source_format_enable(0.77)
endif()
if("${BUILD_TYPE_UPPER}" STREQUAL "DOCONLY")
gen_doc("${doxy_files}" ${LIBNETCONF2_VERSION} ${LIBNETCONF2_DESCRIPTION} "")
return()
endif()
#
# targets
#
# use compat
use_compat()
# netconf2 sourceless target - need it for linking libs, but the required sources will be added later
add_library(netconf2)
# set the shared library version
set_target_properties(netconf2 PROPERTIES VERSION ${LIBNETCONF2_SOVERSION_FULL} SOVERSION ${LIBNETCONF2_SOVERSION})
# include repository files with highest priority
include_directories(${PROJECT_BINARY_DIR}/src)
# dependencies - pthread
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
target_link_libraries(netconf2 ${CMAKE_THREAD_LIBS_INIT})
# check availability for some pthread functions
set(CMAKE_REQUIRED_LIBRARIES pthread)
check_function_exists(pthread_rwlockattr_setkind_np HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
# header file compatibility
check_include_file("shadow.h" HAVE_SHADOW)
check_include_file("termios.h" HAVE_TERMIOS)
if(ENABLE_SSH_TLS)
# dependencies - mbedTLS (higher preference) or OpenSSL
find_package(MbedTLS 3.5.0)
if (MBEDTLS_FOUND)
# dependencies - mbedtls
set(HAVE_MBEDTLS TRUE)
list(APPEND libsrc src/session_mbedtls.c)
include_directories(${MBEDTLS_INCLUDE_DIRS})
target_link_libraries(netconf2 ${MBEDTLS_LIBRARIES})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARIES})
else()
# dependencies - openssl
find_package(OpenSSL 3.0.0 REQUIRED)
list(APPEND libsrc src/session_openssl.c)
include_directories(${OPENSSL_INCLUDE_DIR})
target_link_libraries(netconf2 ${OPENSSL_LIBRARIES})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
endif()
# dependencies - libssh
find_package(LibSSH 0.9.5 REQUIRED)
target_link_libraries(netconf2 ${LIBSSH_LIBRARIES})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBSSH_LIBRARIES})
include_directories(${LIBSSH_INCLUDE_DIRS})
# dependencies - libcurl
find_package(CURL 7.30.0 REQUIRED)
if(TARGET CURL::libcurl)
target_link_libraries(netconf2 CURL::libcurl)
else()
target_link_libraries(netconf2 ${CURL_LIBRARIES})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURL_LIBRARY})
include_directories(${CURL_INCLUDE_DIRS})
endif()
# crypt (if not found, assume no library needs to be linked)
if(${CMAKE_SYSTEM_NAME} MATCHES "QNX")
set(LIBCRYPT login)
else()
set(LIBCRYPT crypt)
endif()
check_library_exists(${LIBCRYPT} crypt "" HAVE_CRYPT)
if(HAVE_CRYPT)
target_link_libraries(netconf2 ${LIBCRYPT})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBCRYPT})
endif()
# libpam
find_package(LibPAM)
if(LibPAM_FOUND)
set(HAVE_LIBPAM TRUE)
target_link_libraries(netconf2 ${LIBPAM_LIBRARIES})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBPAM_LIBRARIES})
include_directories(${LIBPAM_INCLUDE_DIRS})
message(STATUS "SSH Keyboard Interactive system method: Linux PAM")
elseif(HAVE_SHADOW)
message(STATUS "SSH Keyboard Interactive system method: local users")
else()
message(WARNING "SSH Keyboard Interactive system method: disabled")
endif()
# set compiler flag
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNC_ENABLED_SSH_TLS")
endif()
# dependencies - libval
if(ENABLE_DNSSEC)
find_package(LibVAL REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_DNSSEC")
target_link_libraries(netconf2 ${LIBVAL_LIBRARIES})
include_directories(${LIBVAL_INCLUDE_DIRS})
endif()
# dependencies - libyang
find_package(LibYANG ${LIBYANG_DEP_SOVERSION} REQUIRED)
target_link_libraries(netconf2 ${LIBYANG_LIBRARIES})
include_directories(${LIBYANG_INCLUDE_DIRS})
# function compatibility - getpeereid on QNX
if(${CMAKE_SYSTEM_NAME} MATCHES "QNX")
target_link_libraries(netconf2 -lsocket)
list(APPEND CMAKE_REQUIRED_LIBRARIES socket)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES pthread)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_QNX_SOURCE)
check_symbol_exists(getpeereid "sys/types.h;unistd.h" HAVE_GETPEEREID)
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_QNX_SOURCE)
endif()
# set sources
target_sources(netconf2 PRIVATE ${libsrc} ${compatsrc})
# generate config file
configure_file("${PROJECT_SOURCE_DIR}/src/config.h.in" "${PROJECT_BINARY_DIR}/src/config.h" ESCAPE_QUOTES @ONLY)
# generate and copy public header files
configure_file("${PROJECT_SOURCE_DIR}/nc_client.h.in" "${PROJECT_BINARY_DIR}/include/nc_client.h")
configure_file("${PROJECT_SOURCE_DIR}/nc_server.h.in" "${PROJECT_BINARY_DIR}/include/nc_server.h")
configure_file("${PROJECT_SOURCE_DIR}/nc_version.h.in" "${PROJECT_BINARY_DIR}/include/nc_version.h")
file(COPY ${headers} DESTINATION "${PROJECT_BINARY_DIR}/include/libnetconf2")
# install YANG modules
install(DIRECTORY "${PROJECT_SOURCE_DIR}/modules/" DESTINATION ${YANG_MODULE_DIR} FILES_MATCHING PATTERN "*.yang")
# install library
install(TARGETS netconf2 DESTINATION ${CMAKE_INSTALL_LIBDIR})
# install headers
install(FILES ${PROJECT_BINARY_DIR}/include/nc_client.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${PROJECT_BINARY_DIR}/include/nc_server.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${PROJECT_BINARY_DIR}/include/nc_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(DIRECTORY ${PROJECT_BINARY_DIR}/include/libnetconf2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# install pkg-config file
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
configure_file("libnetconf2.pc.in" "libnetconf2.pc" @ONLY)
install(FILES "${PROJECT_BINARY_DIR}/libnetconf2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# check that pkg-config includes the used path
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable pc_path pkg-config RESULT_VARIABLE RETURN OUTPUT_VARIABLE PC_PATH ERROR_QUIET)
if(RETURN EQUAL 0)
string(REGEX MATCH "${CMAKE_INSTALL_LIBDIR}/pkgconfig" SUBSTR "${PC_PATH}")
string(LENGTH "${SUBSTR}" SUBSTR_LEN)
if(SUBSTR_LEN EQUAL 0)
message(WARNING "pkg-config will not detect the new package after installation, adjust PKG_CONFIG_PATH using \"export PKG_CONFIG_PATH=\${PKG_CONFIG_PATH}:${CMAKE_INSTALL_LIBDIR}/pkgconfig\".")
endif()
endif()
endif()
# examples
if(ENABLE_EXAMPLES)
if(NOT ENABLE_SSH_TLS)
message(WARNING "Examples will not be compiled because SSH and TLS are disabled.")
else()
add_subdirectory(examples)
endif()
endif()
# tests
if(ENABLE_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
# create coverage target for generating coverage reports
gen_coverage("test_.*" "test_.*_valgrind")
# generate doxygen documentation for libnetconf2 API
if(ENABLE_COMMON_TARGETS)
gen_doc("${doxy_files}" ${LIBNETCONF2_VERSION} ${LIBNETCONF2_DESCRIPTION} "")
endif()
# generate API/ABI report
if ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
lib_abi_check(netconf2 "${headers}" ${LIBNETCONF2_SOVERSION_FULL} 15fbc59efa5e6f1f7bea19ab561d03f8852caabb)
endif()
# source files to be covered by the 'format' target and a test with 'format-check' target
source_format(${format_sources})
# clean cmake cache
if(ENABLE_COMMON_TARGETS)
add_custom_target(cleancache
COMMAND make clean
COMMAND find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
COMMAND rm -rf Makefile Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()
# uninstall
if(ENABLE_COMMON_TARGETS)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake")
endif()