forked from CESNET/netopeer2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
419 lines (360 loc) · 14.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
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
409
410
411
412
413
414
415
416
417
418
419
cmake_minimum_required(VERSION 3.5)
project(netopeer2 C)
set(NETOPEER2_DESC "NETCONF tools suite including a server and command-line client")
# include custom Modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
include(GNUInstallDirs)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(UseCompat)
include(SourceFormat)
include(GenCoverage)
if(POLICY CMP0028)
cmake_policy(SET CMP0028 NEW)
endif()
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
# set default build type if not specified by user and normalize it
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER)
# see https://github.com/CESNET/libyang/pull/1692 for why CMAKE_C_FLAGS_<type> are not used directly
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)
endif()
# check the supported platform
if(NOT UNIX)
message(FATAL_ERROR "Only *nix like systems are supported.")
endif()
# 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(NP2SRV_VERSION 2.2.13)
# libyang required version
set(LIBYANG_DEP_VERSION 2.1.146)
set(LIBYANG_DEP_SOVERSION 2.46.1)
set(LIBYANG_DEP_SOVERSION_MAJOR 2)
# libnetconf2 required version
set(LIBNETCONF2_DEP_VERSION 3.0.8)
set(LIBNETCONF2_DEP_SOVERSION 4.1.5)
set(LIBNETCONF2_DEP_SOVERSION_MAJOR 4)
# sysrepo required version
set(SYSREPO_DEP_VERSION 2.2.148)
set(SYSREPO_DEP_SOVERSION 7.22.0)
set(SYSREPO_DEP_SOVERSION_MAJOR 7)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99")
#
# options
#
option(ENABLE_TESTS "Build tests" ON)
if(("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG") OR ("${BUILD_TYPE_UPPER}" STREQUAL "RELWITHDEBINFO"))
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" ON)
else()
option(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF)
endif()
option(ENABLE_COVERAGE "Build code coverage report from tests" OFF)
option(BUILD_CLI "Build and install neotpeer2-cli" ON)
option(ENABLE_URL "Enable URL capability" ON)
set(SSH_AUTHORIZED_KEYS_FORMAT "%h/.ssh/authorized_keys" CACHE STRING "sshd-like pattern (with '%h', '%u', '%U') for determining path to users' SSH authorized_keys file.")
set(THREAD_COUNT 3 CACHE STRING "Number of threads accepting new sessions and handling requests")
set(POLL_IO_TIMEOUT 10 CACHE STRING "Timeout in milliseconds of polling sessions for new data. It is also used for synchronization of low level IO such as sending a reply while a notification is being sent")
set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/netopeer2" CACHE STRING "Directory where to copy the YANG modules to")
set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/netopeer2" CACHE STRING "Directory with shared netopeer2 data")
# script options
option(SYSREPO_SETUP "Install required modules with their default configuration into sysrepo" ON)
set(MODULES_PERMS 600 CACHE STRING "File access permissions set for all the server modules")
if(NOT MODULES_OWNER)
execute_process(COMMAND id -un RESULT_VARIABLE RET
OUTPUT_VARIABLE MODULES_OWNER OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE ERROR_STR OUTPUT_STRIP_TRAILING_WHITESPACE)
if(RET)
message(WARNING "Learning server module user failed (${ERROR_STR}), the current user will be used.")
endif()
endif()
set(MODULES_OWNER "${MODULES_OWNER}" CACHE STRING "System user that will become the owner of server modules, empty means the current user")
if(NOT MODULES_GROUP AND MODULES_OWNER)
execute_process(COMMAND id -gn ${MODULES_OWNER} RESULT_VARIABLE RET
OUTPUT_VARIABLE MODULES_GROUP OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE ERROR_STR OUTPUT_STRIP_TRAILING_WHITESPACE)
if(RET)
message(WARNING "Learning server module group failed (${ERROR_STR}), the current user group will be used.")
endif()
endif()
set(MODULES_GROUP "${MODULES_GROUP}" CACHE STRING "System group that the server modules will belong to, empty means the current user group")
# set prefix for the PID file
if(NOT PIDFILE_PREFIX)
set(PIDFILE_PREFIX "/var/run")
endif()
if(NOT SERVER_DIR)
if("${BUILD_TYPE_UPPER}" STREQUAL "DEBUG")
set(SERVER_DIR "$ENV{HOME}/.netopeer2-server")
else()
set(SERVER_DIR "/var/netopeer2")
endif()
endif()
#
# sources
#
set(SERVER_SRC
src/common.c
src/netconf.c
src/netconf_monitoring.c
src/netconf_nmda.c
src/netconf_subscribed_notifications.c
src/netconf_confirmed_commit.c
src/log.c
src/err_netconf.c)
# source files to be covered by the 'format' target
set(FORMAT_SRC
compat/*.c
compat/*.h*
src/*.c
src/*.h
cli/*.c
cli/*.h
tests/*.c
tests/*.h)
#
# checks
#
# PKGCONFIG {
find_package(PkgConfig REQUIRED)
# find libnetconf2 pkg
pkg_check_modules(PKG_LN2 REQUIRED libnetconf2)
# libnetconf2 thread count check
pkg_get_variable(LN2_THREAD_COUNT libnetconf2 "LN2_MAX_THREAD_COUNT")
if(LN2_THREAD_COUNT)
if(LN2_THREAD_COUNT LESS THREAD_COUNT)
message(FATAL_ERROR "libnetconf2 was compiled with support up to ${LN2_THREAD_COUNT} threads, server is configured with ${THREAD_COUNT}.")
else()
message(STATUS "libnetconf2 was compiled with support of up to ${LN2_THREAD_COUNT} threads")
endif()
else()
message(STATUS "Unable to learn libnetconf2 thread support, check skipped")
endif()
# get libnetconf2 module directory, use it later when installing modules
pkg_get_variable(LN2_YANG_MODULE_DIR libnetconf2 "LN2_SCHEMAS_DIR")
if(NOT LN2_YANG_MODULE_DIR)
message(FATAL_ERROR "Unable to learn libnetconf2 module search directory.")
endif()
# find sysrepo pkg and get sysrepo group
pkg_check_modules(PKG_SR REQUIRED sysrepo)
pkg_get_variable(SR_GROUP sysrepo "SR_GROUP")
# } PKGCONFIG
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()
#
# targets
#
# put all binaries into one directory (even from subprojects)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
# dependencies - OpenSSL (required by later libnetconf2 checks and not really the server itself)
find_package(OpenSSL 3.0.0)
if(OPENSSL_FOUND)
list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
endif()
# dependencies - libssh (also required by libnetconf2 checks)
find_package(LibSSH 0.9.5)
if(LIBSSH_FOUND)
list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBSSH_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBSSH_LIBRARIES})
endif()
# dependencies - libnetconf2 (now, because we need to configure outselves based on it)
find_package(LibNETCONF2 ${LIBNETCONF2_DEP_SOVERSION} REQUIRED)
include_directories(${LIBNETCONF2_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBNETCONF2_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBNETCONF2_LIBRARIES})
# link compat
use_compat()
# netopeer2-server
add_library(serverobj OBJECT ${SERVER_SRC})
add_executable(netopeer2-server $<TARGET_OBJECTS:serverobj> src/main.c ${compatsrc})
#
# dependencies
#
# librt (not required on OSX or QNX)
find_library(LIBRT rt)
if(LIBRT)
target_link_libraries(netopeer2-server ${LIBRT})
endif()
# libnetconf2 (was already found)
target_link_libraries(netopeer2-server ${LIBNETCONF2_LIBRARIES})
# libssh (was already found, if exists)
if(LIBSSH_FOUND AND LIBNETCONF2_ENABLED_SSH_TLS)
target_link_libraries(netopeer2-server ${LIBSSH_LIBRARIES})
include_directories(${LIBSSH_INCLUDE_DIRS})
endif()
# libcurl
if(ENABLE_URL)
find_package(CURL)
if(CURL_FOUND)
include_directories(${CURL_INCLUDE_DIRS})
if(TARGET CURL::libcurl)
target_link_libraries(netopeer2-server CURL::libcurl)
else()
target_link_libraries(netopeer2-server ${CURL_LIBRARIES})
endif()
set(NP2SRV_URL_CAPAB 1)
else()
message(STATUS "libcurl not found, url capability will not be supported")
unset(NP2SRV_URL_CAPAB)
endif()
endif()
# libsystemd
if(NOT PKG_CONFIG_FOUND AND NOT SYSTEMD_UNIT_DIR)
set(SYSTEMD_UNIT_DIR "/usr/lib/systemd/system")
endif()
find_package(LibSystemd)
if(LIBSYSTEMD_FOUND)
set(NP2SRV_HAVE_SYSTEMD 1)
target_link_libraries(netopeer2-server ${LIBSYSTEMD_LIBRARIES})
include_directories(${LIBSYSTEMD_INCLUDE_DIRS})
message(STATUS "systemd system service unit path: ${SYSTEMD_UNIT_DIR}")
else()
message(WARNING "Disabling netopeer2-server systemd support because libsystemd was not found.")
endif()
# pthread
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
target_link_libraries(netopeer2-server ${CMAKE_THREAD_LIBS_INIT})
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_THREAD_LIBS_INIT})
# libyang
find_package(LibYANG ${LIBYANG_DEP_SOVERSION} REQUIRED)
target_link_libraries(netopeer2-server ${LIBYANG_LIBRARIES})
include_directories(${LIBYANG_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBYANG_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBYANG_LIBRARIES})
# sysrepo
find_package(Sysrepo ${SYSREPO_DEP_SOVERSION} REQUIRED)
target_link_libraries(netopeer2-server ${SYSREPO_LIBRARIES})
include_directories(${SYSREPO_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_INCLUDES ${SYSREPO_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${SYSREPO_LIBRARIES})
if(SYSREPO_SETUP)
# find sysrepoctl to be used for installation and tests
if (NOT SYSREPOCTL_EXECUTABLE)
find_program(SYSREPOCTL_EXECUTABLE sysrepoctl)
endif()
if (NOT SYSREPOCTL_EXECUTABLE)
message(FATAL_ERROR "Unable to find sysrepoctl, set SYSREPOCTL_EXECUTABLE manually.")
endif()
# find sysrepocfg to be used for installation and tests
if (NOT SYSREPOCFG_EXECUTABLE)
find_program(SYSREPOCFG_EXECUTABLE sysrepocfg)
endif()
if (NOT SYSREPOCFG_EXECUTABLE)
message(FATAL_ERROR "Unable to find sysrepocfg, set SYSREPOCFG_EXECUTABLE manually.")
endif()
endif()
# generate files
configure_file("${PROJECT_SOURCE_DIR}/src/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ESCAPE_QUOTES @ONLY)
configure_file("${PROJECT_SOURCE_DIR}/service/netopeer2-server.service.in" "${PROJECT_BINARY_DIR}/netopeer2-server.service" @ONLY)
include_directories(${PROJECT_BINARY_DIR})
# install the modules and scripts
install(DIRECTORY "${PROJECT_SOURCE_DIR}/modules/" DESTINATION ${YANG_MODULE_DIR})
install(DIRECTORY "${PROJECT_SOURCE_DIR}/scripts/" DESTINATION ${DATA_DIR}/scripts USE_SOURCE_PERMISSIONS)
# install the binary, required modules, and default configuration
install(TARGETS netopeer2-server DESTINATION ${CMAKE_INSTALL_SBINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/netopeer2-server.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8)
if(NP2SRV_HAVE_SYSTEMD)
install(FILES ${PROJECT_BINARY_DIR}/netopeer2-server.service DESTINATION ${SYSTEMD_UNIT_DIR})
endif()
# copy pam service to /etc/pam.d
if(EXISTS "/etc/pam.d")
install(FILES "${CMAKE_SOURCE_DIR}/pam/netopeer2.conf" DESTINATION "/etc/pam.d")
endif()
if(SYSREPO_SETUP)
install(CODE "
message(STATUS \"Installing missing sysrepo modules...\")
set(ENV{NP2_MODULE_DIR} \"${YANG_MODULE_DIR}\")
set(ENV{NP2_MODULE_PERMS} \"${MODULES_PERMS}\")
set(ENV{NP2_MODULE_OWNER} \"${MODULES_OWNER}\")
set(ENV{NP2_MODULE_GROUP} \"${MODULES_GROUP}\")
set(ENV{LN2_MODULE_DIR} \"${LN2_YANG_MODULE_DIR}\")
set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\")
set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\")
execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/setup.sh\" RESULT_VARIABLE SETUP_RES)
if(NOT SETUP_RES EQUAL \"0\")
message(FATAL_ERROR \" scripts/setup.sh failed: \${SETUP_RES}\")
endif()
")
# generate hostkey
install(CODE "
message(STATUS \"Generating a new RSA host key \\\"genkey\\\" if not already added...\")
set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\")
set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\")
execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/merge_hostkey.sh\" RESULT_VARIABLE MERGE_HOSTKEY_RES)
if(NOT MERGE_HOSTKEY_RES EQUAL \"0\")
message(FATAL_ERROR \" scripts/merge_hostkey.sh failed: \${MERGE_HOSTKEY_RES}\")
endif()
")
# merge listen config
install(CODE "
message(STATUS \"Merging default server listen configuration if there is none...\")
set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\")
set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\")
execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/merge_config.sh\" RESULT_VARIABLE MERGE_CONFIG_RES)
if(NOT MERGE_CONFIG_RES EQUAL \"0\")
message(FATAL_ERROR \" scripts/merge_config.sh failed: \${MERGE_CONFIG_RES}\")
endif()
")
else()
message(WARNING "Server will refuse to start if the modules are not installed!")
endif()
# tests
if(ENABLE_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
# create coverage target for generating coverage reports
gen_coverage("test_.*" "test_.*_valgrind")
# cli
if(BUILD_CLI)
add_subdirectory(cli)
endif()
# source files to be covered by the 'format' target and a test with 'format-check' target
source_format(${FORMAT_SRC})
# clean cmake cache
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}
)
# uninstall
add_custom_target(uninstall ${DATA_DIR}/scripts/remove.sh
COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake"
COMMENT "Removing netopeer2 modules from sysrepo..."
)