Repository navigation
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
672 lines (593 loc) · 24.4 KB
/
Copy pathCMakeLists.txt
File metadata and controls
672 lines (593 loc) · 24.4 KB
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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
cmake_minimum_required(VERSION 3.13)
project(ucode C)
add_library(uc_defines INTERFACE)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckCSourceCompiles)
include(CheckIPOSupported)
include(GNUInstallDirs)
option(BUILD_OPTIMIZE_SIZE "Optimize for size" ON)
if(BUILD_OPTIMIZE_SIZE)
add_compile_options(
-Os
)
endif()
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
add_compile_definitions( _GNU_SOURCE )
add_compile_options(
-Wall
-Werror
-Wmissing-declarations
)
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
add_compile_options(
-Wextra
-Wformat
-Werror=implicit-function-declaration
-Werror=format-security
-Werror=format-nonliteral
)
endif()
add_compile_options(
-Wno-unused-parameter
-Wno-error=unused-variable
)
# signed overflow semantics are defined AND expected
add_compile_options(-fwrapv)
option(BUILD_FUNCTION_SECTIONS "Compile with -ffunction-sections" ON)
if(BUILD_FUNCTION_SECTIONS)
add_compile_options(-ffunction-sections)
endif()
# Omit the async stack-unwind tables (.eh_frame) in release builds. ucode is
# pure C with no exceptions and provides its own bytecode-level stack traces,
# so these tables only serve external C-stack unwinding (backtrace(), C-level
# crash reporters, profilers) and cost roughly 23 KB of the shared library.
# Debug and RelWithDebInfo keep them to preserve native stack traces.
option(BUILD_NO_UNWIND_TABLES "Omit async stack-unwind tables in release builds" ON)
if(BUILD_NO_UNWIND_TABLES)
# listing several configurations in a single $<CONFIG:> expression requires
# CMake >= 3.19, so combine single-configuration expressions to stay
# compatible with the declared minimum CMake version
add_compile_options(
$<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>>:-fno-asynchronous-unwind-tables>
)
endif()
# Link-time optimization in release builds. Cross translation-unit dead code
# elimination and folding of identical functions trims a further few percent
# from libucode. Off by default: it lengthens builds and assumes a matching LTO
# toolchain, so OpenWrt and default builds are unaffected unless requested.
# Only Release and MinSizeRel are enabled, Debug and RelWithDebInfo are not.
option(BUILD_LTO "Enable link-time optimization in release builds" OFF)
if(BUILD_LTO)
check_ipo_supported(RESULT lto_supported OUTPUT lto_error)
if(lto_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON)
else()
message(WARNING "BUILD_LTO requested but IPO is unsupported: ${lto_error}")
endif()
endif()
check_c_source_compiles("
int main() {
#ifndef _FORTIFY_SOURCE
#error No fortification
#endif
return 0;
}
" DEFAULT_FORTIFY_SOURCE)
if(NOT DEFAULT_FORTIFY_SOURCE)
add_compile_definitions( FORTIFY_SOURCE=2 )
endif()
# Emscripten / WebAssembly build:
# cmake -B build-wasm -DCMAKE_TOOLCHAIN_FILE=cmake/emscripten.cmake
#
# Produces libucode.a and ucode-modules.a (modules with renamed
# uc_module_init symbols) for static linking into an embedder's
# executable. The CLI, udbg, dlopen plugins and examples are not built.
if(CMAKE_C_COMPILER_ID STREQUAL "Emscripten")
set(UCODE_WASM_DEFAULT ON)
else()
set(UCODE_WASM_DEFAULT OFF)
endif()
option(UCODE_WASM "Build static libraries for wasm32 (no CLI, no dlopen plugins)" ${UCODE_WASM_DEFAULT})
include_directories(include)
option(COMPILE_SUPPORT "Support compilation from source" ON)
if(NOT COMPILE_SUPPORT)
target_compile_definitions(uc_defines INTERFACE NO_COMPILE)
endif()
if(NOT UCODE_WASM)
find_library(libuci NAMES uci)
find_library(libubox NAMES ubox)
find_library(libubus NAMES ubus)
find_library(libblobmsg_json NAMES blobmsg_json)
find_package(ZLIB)
find_library(libmd NAMES libmd.a md)
find_library(libffi NAMES ffi)
if(LINUX)
find_library(libnl_tiny NAMES nl-tiny)
if(libnl_tiny AND libubox)
set(DEFAULT_NL_SUPPORT ON)
endif()
endif()
if(libuci AND libubox)
set(DEFAULT_UCI_SUPPORT ON)
endif()
if(libubus AND libblobmsg_json)
set(DEFAULT_UBUS_SUPPORT ON)
endif()
if(libubox)
set(DEFAULT_ULOOP_SUPPORT ON)
endif()
if(ZLIB_FOUND)
set(DEFAULT_ZLIB_SUPPORT ON)
endif()
if(libmd)
set(DEFAULT_DIGEST_SUPPORT ON)
endif()
if(libffi)
set(DEFAULT_FFI_SUPPORT ON)
endif()
endif()
if(NOT UCODE_WASM)
option(DEBUG_SUPPORT "Debug plugin support" ON)
option(FS_SUPPORT "Filesystem plugin support" ON)
option(IO_SUPPORT "IO plugin support" ON)
option(MATH_SUPPORT "Math plugin support" ON)
option(NETADDR_SUPPORT "Network address plugin support" ON)
option(FFI_SUPPORT "FFI module support" ${DEFAULT_FFI_SUPPORT})
option(UBUS_SUPPORT "Ubus plugin support" ${DEFAULT_UBUS_SUPPORT})
option(UCI_SUPPORT "UCI plugin support" ${DEFAULT_UCI_SUPPORT})
option(RTNL_SUPPORT "Route Netlink plugin support" ${DEFAULT_NL_SUPPORT})
option(NL80211_SUPPORT "Wireless Netlink plugin support" ${DEFAULT_NL_SUPPORT})
option(RESOLV_SUPPORT "NS resolve plugin support" ON)
option(STRUCT_SUPPORT "Struct plugin support" ON)
option(ULOOP_SUPPORT "Uloop plugin support" ${DEFAULT_ULOOP_SUPPORT})
option(LOG_SUPPORT "Log plugin support" ON)
option(SOCKET_SUPPORT "Socket plugin support" ON)
option(SERIAL_SUPPORT "Serial port plugin support" ON)
option(ZLIB_SUPPORT "Zlib plugin support" ${DEFAULT_ZLIB_SUPPORT})
option(DIGEST_SUPPORT "Digest plugin support" ${DEFAULT_DIGEST_SUPPORT})
option(DIGEST_SUPPORT_EXTENDED "Enable additional hash algorithms" ${DEFAULT_DIGEST_SUPPORT})
else()
# Modules built into ucode-modules.a; each is compiled with
# uc_module_init renamed to uc_module_init_<name> so several can be
# linked into one executable. Server-side socket APIs (bind/listen/
# accept) are compiled in but not supported by emscripten.
set(UCODE_WASM_MODULES "io;math;struct;fs;zlib;resolv;socket;digest;netaddr" CACHE STRING "Modules built into ucode-modules.a")
endif()
if(UCODE_WASM)
# No dlopen under wasm: .so entries would only cause failed lookups.
# Embedders (e.g. the pen service) extend REQUIRE_SEARCH_PATH at
# runtime.
set(LIB_SEARCH_PATH "./*.uc" CACHE STRING "Default library search path")
else()
set(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path")
endif()
string(REPLACE ":" "\", \"" LIB_SEARCH_DEFINE "${LIB_SEARCH_PATH}")
target_compile_definitions(uc_defines INTERFACE LIB_SEARCH_PATH="${LIB_SEARCH_DEFINE}")
if(APPLE)
set(UCODE_MODULE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup")
# TODO: localize target(s) and switch to target_compile_definitions()
add_compile_definitions( BIND_8_COMPAT )
endif()
if(APPLE)
set(DEFAULT_LINK_GC_SECTIONS OFF)
else()
set(DEFAULT_LINK_GC_SECTIONS ON)
endif()
option(LINK_GC_SECTIONS "Link with --gc-sections" ${DEFAULT_LINK_GC_SECTIONS})
if(LINK_GC_SECTIONS)
if(UNIT_TESTING)
message(WARNING "Unit testing **MAY** conflict with --gc-sections")
else()
add_link_options("LINKER:--gc-sections")
endif()
endif()
if(DEBUG)
add_compile_definitions( DEBUG )
add_compile_options(
-Og
-g3
)
else()
add_compile_definitions( NDEBUG )
endif()
if(UCODE_WASM)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/emscripten-deps.cmake)
set(JSONC_INCLUDE_DIRS ${UCODE_DEPS_PREFIX}/json-c/dist/include)
set(JSONC_LINK_LIBRARIES libjson-c)
include_directories(${JSONC_INCLUDE_DIRS})
# json-c is pinned by emscripten-deps.cmake; the features checked for
# below are all present in it
target_compile_definitions(uc_defines INTERFACE HAVE_PARSE_END HAVE_ARRAY_EXT HAVE_JSON_UINT64)
else()
include(FindPkgConfig)
pkg_check_modules(JSONC REQUIRED json-c)
include_directories(${JSONC_INCLUDE_DIRS})
endif()
set(UCODE_SOURCES lexer.c lib.c vm.c chunk.c vallist.c compiler.c source.c types.c program.c platform.c)
if(UCODE_WASM)
add_library(libucode STATIC ${UCODE_SOURCES})
set_target_properties(libucode PROPERTIES OUTPUT_NAME ucode)
else()
add_library(libucode SHARED ${UCODE_SOURCES})
set(SOVERSION 0 CACHE STRING "Override ucode library version")
set_target_properties(libucode PROPERTIES OUTPUT_NAME ucode SOVERSION ${SOVERSION})
endif()
target_link_libraries(libucode uc_defines ${JSONC_LINK_LIBRARIES})
if(NOT UCODE_WASM)
set(CLI_SOURCES main.c)
add_executable(ucode ${CLI_SOURCES})
target_link_libraries(ucode uc_defines libucode)
endif()
# Ensure rpath is used on macOS
set(CMAKE_MACOSX_RPATH ON)
# Automatically include linked library paths in rpath
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if(APPLE)
set_target_properties(libucode PROPERTIES
INSTALL_NAME_DIR "@rpath"
)
set_target_properties(ucode PROPERTIES
INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}"
)
endif()
if(APPLE AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
execute_process(
COMMAND brew --prefix
OUTPUT_VARIABLE HOMEBREW_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(HOMEBREW_PREFIX AND EXISTS "${HOMEBREW_PREFIX}")
message(STATUS "Using Homebrew prefix: ${HOMEBREW_PREFIX}")
set(CMAKE_INSTALL_PREFIX "${HOMEBREW_PREFIX}" CACHE PATH "Install path" FORCE)
endif()
endif()
if(NOT UCODE_WASM)
check_function_exists(dlopen DLOPEN_FUNCTION_EXISTS)
if(NOT DLOPEN_FUNCTION_EXISTS)
target_link_libraries(libucode dl)
endif()
check_function_exists(fmod FMOD_FUNCTION_EXISTS)
if(NOT FMOD_FUNCTION_EXISTS)
target_link_libraries(libucode m)
endif()
endif()
if(NOT UCODE_WASM)
list(APPEND CMAKE_REQUIRED_INCLUDES ${JSONC_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${JSONC_LINK_LIBRARIES})
check_symbol_exists(json_tokener_get_parse_end "json-c/json.h" HAVE_PARSE_END)
if(HAVE_PARSE_END)
target_compile_definitions(uc_defines INTERFACE HAVE_PARSE_END)
endif()
check_symbol_exists(json_object_new_array_ext "json-c/json.h" HAVE_ARRAY_EXT)
if(HAVE_ARRAY_EXT)
target_compile_definitions(uc_defines INTERFACE HAVE_ARRAY_EXT)
endif()
check_symbol_exists(json_object_new_uint64 "json-c/json.h" HAVE_JSON_UINT64)
if(HAVE_JSON_UINT64)
target_compile_definitions(uc_defines INTERFACE HAVE_JSON_UINT64)
endif()
endif()
if(NOT UCODE_WASM)
set(LIBRARIES "")
if(DEBUG_SUPPORT)
set(LIBRARIES ${LIBRARIES} debug_lib)
add_library(debug_lib MODULE lib/debug.c lib/debug_remote.c lib/debug_proto.c)
set_target_properties(debug_lib PROPERTIES OUTPUT_NAME debug PREFIX "")
target_link_options(debug_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(debug_lib PRIVATE libucode)
if(libubox)
find_path(uloop_include_dir NAMES libubox/uloop.h)
include_directories(${uloop_include_dir})
target_link_libraries(debug_lib PRIVATE ${libubox} ${libucode})
target_compile_definitions(debug_lib PRIVATE HAVE_ULOOP)
endif()
endif()
if(FS_SUPPORT)
set(LIBRARIES ${LIBRARIES} fs_lib)
add_library(fs_lib MODULE lib/fs.c)
set_target_properties(fs_lib PROPERTIES OUTPUT_NAME fs PREFIX "")
target_link_options(fs_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
endif()
if(IO_SUPPORT)
set(LIBRARIES ${LIBRARIES} io_lib)
add_library(io_lib MODULE lib/io.c)
set_target_properties(io_lib PROPERTIES OUTPUT_NAME io PREFIX "")
target_link_options(io_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
endif()
if(MATH_SUPPORT)
set(LIBRARIES ${LIBRARIES} math_lib)
add_library(math_lib MODULE lib/math.c)
set_target_properties(math_lib PROPERTIES OUTPUT_NAME math PREFIX "")
target_link_options(math_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
check_function_exists(ceil CEIL_FUNCTION_EXISTS)
if(NOT CEIL_FUNCTION_EXISTS)
target_link_libraries(math_lib m)
endif()
endif()
if(UBUS_SUPPORT)
find_path(ubus_include_dir NAMES libubus.h)
include_directories(${ubus_include_dir})
set(LIBRARIES ${LIBRARIES} ubus_lib)
add_library(ubus_lib MODULE lib/ubus.c)
set_target_properties(ubus_lib PROPERTIES OUTPUT_NAME ubus PREFIX "")
target_link_options(ubus_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(ubus_lib ${libubus} ${libblobmsg_json})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${libubox} ${libubus})
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test.c" "
#include <libubus.h>
int main() { return UBUS_STATUS_NO_MEMORY; }
")
try_compile(HAVE_NEW_UBUS_STATUS_CODES
${CMAKE_BINARY_DIR}
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test.c")
check_function_exists(ubus_flush_requests HAVE_UBUS_FLUSH_REQUESTS)
check_function_exists(uloop_timeout_remaining64 REMAINING64_FUNCTION_EXISTS)
check_function_exists(ubus_channel_connect HAVE_CHANNEL_SUPPORT)
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test2.c" "
#include <libubus.h>
int main() { struct ubus_subscriber sub = { .new_obj_cb = NULL }; return 0; }
")
try_compile(HAVE_UBUS_NEW_OBJ_CB
${CMAKE_BINARY_DIR}
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test2.c")
if(REMAINING64_FUNCTION_EXISTS)
target_compile_definitions(ubus_lib PRIVATE HAVE_ULOOP_TIMEOUT_REMAINING64)
endif()
if(HAVE_CHANNEL_SUPPORT)
target_compile_definitions(ubus_lib PRIVATE HAVE_UBUS_CHANNEL_SUPPORT)
endif()
if(HAVE_NEW_UBUS_STATUS_CODES)
target_compile_definitions(ubus_lib PRIVATE HAVE_NEW_UBUS_STATUS_CODES)
endif()
if(HAVE_UBUS_FLUSH_REQUESTS)
target_compile_definitions(ubus_lib PRIVATE HAVE_UBUS_FLUSH_REQUESTS)
endif()
if (HAVE_UBUS_NEW_OBJ_CB)
target_compile_definitions(ubus_lib PRIVATE HAVE_UBUS_NEW_OBJ_CB)
endif()
endif()
if(UCI_SUPPORT)
find_path(uci_include_dir uci.h)
include_directories(${uci_include_dir})
set(LIBRARIES ${LIBRARIES} uci_lib)
add_library(uci_lib MODULE lib/uci.c)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${libubox} ${libuci})
check_function_exists(uci_set_conf2dir HAVE_UCI_CONF2DIR)
if (HAVE_UCI_CONF2DIR)
target_compile_definitions(uci_lib PRIVATE HAVE_UCI_CONF2DIR)
endif()
set_target_properties(uci_lib PROPERTIES OUTPUT_NAME uci PREFIX "")
target_link_options(uci_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(uci_lib ${libuci} ${libubox})
endif()
if(RTNL_SUPPORT)
find_path(nl_include_dir NAMES netlink/msg.h PATH_SUFFIXES libnl-tiny)
include_directories(${nl_include_dir})
set(LIBRARIES ${LIBRARIES} rtnl_lib)
add_library(rtnl_lib MODULE lib/rtnl.c)
set_target_properties(rtnl_lib PROPERTIES OUTPUT_NAME rtnl PREFIX "")
target_link_options(rtnl_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(rtnl_lib ${libnl_tiny} ${libubox})
endif()
if(NL80211_SUPPORT)
find_path(nl_include_dir NAMES netlink/msg.h PATH_SUFFIXES libnl-tiny)
include_directories(${nl_include_dir})
set(LIBRARIES ${LIBRARIES} nl80211_lib)
add_library(nl80211_lib MODULE lib/nl80211.c)
set_target_properties(nl80211_lib PROPERTIES OUTPUT_NAME nl80211 PREFIX "")
target_link_options(nl80211_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(nl80211_lib ${libnl_tiny} ${libubox})
endif()
if(RESOLV_SUPPORT)
set(LIBRARIES ${LIBRARIES} resolv_lib)
add_library(resolv_lib MODULE lib/resolv.c)
set_target_properties(resolv_lib PROPERTIES OUTPUT_NAME resolv PREFIX "")
target_link_options(resolv_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
check_function_exists(res_mkquery RES_MKQUERY_FUNCTION_EXISTS)
check_function_exists(ns_initparse NS_INITARSE_FUNCTION_EXISTS)
check_function_exists(clock_gettime CLOCK_GETTIME_FUNCTION_EXISTS)
if(NOT RES_MKQUERY_FUNCTION_EXISTS OR NOT NS_INITARSE_FUNCTION_EXISTS)
target_link_libraries(resolv_lib resolv)
endif()
if(NOT CLOCK_GETTIME_FUNCTION_EXISTS)
target_link_libraries(resolv_lib rt)
endif()
endif()
if(STRUCT_SUPPORT)
set(LIBRARIES ${LIBRARIES} struct_lib)
add_library(struct_lib MODULE lib/struct.c)
set_target_properties(struct_lib PROPERTIES OUTPUT_NAME struct PREFIX "")
target_link_options(struct_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
check_function_exists(frexp FREXP_FUNCTION_EXISTS)
if(NOT FREXP_FUNCTION_EXISTS)
target_link_libraries(struct_lib m)
endif()
endif()
if(ULOOP_SUPPORT)
find_path(uloop_include_dir NAMES libubox/uloop.h)
include_directories(${uloop_include_dir})
set(LIBRARIES ${LIBRARIES} uloop_lib)
add_library(uloop_lib MODULE lib/uloop.c)
set_target_properties(uloop_lib PROPERTIES OUTPUT_NAME uloop PREFIX "")
target_link_options(uloop_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${libubox})
check_function_exists(uloop_timeout_remaining64 REMAINING64_FUNCTION_EXISTS)
check_function_exists(uloop_interval_set INTERVAL_FUNCTION_EXISTS)
check_function_exists(uloop_signal_add SIGNAL_FUNCTION_EXISTS)
if(REMAINING64_FUNCTION_EXISTS)
target_compile_definitions(uloop_lib PRIVATE HAVE_ULOOP_TIMEOUT_REMAINING64)
endif()
if(INTERVAL_FUNCTION_EXISTS)
target_compile_definitions(uloop_lib PRIVATE HAVE_ULOOP_INTERVAL)
endif()
if(SIGNAL_FUNCTION_EXISTS)
target_compile_definitions(uloop_lib PRIVATE HAVE_ULOOP_SIGNAL)
endif()
target_link_libraries(uloop_lib ${libubox})
endif()
if(LOG_SUPPORT)
set(LIBRARIES ${LIBRARIES} log_lib)
add_library(log_lib MODULE lib/log.c)
set_target_properties(log_lib PROPERTIES OUTPUT_NAME log PREFIX "")
target_link_options(log_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
if(libubox)
find_path(ulog_include_dir NAMES libubox/ulog.h)
include_directories(${ulog_include_dir})
target_link_libraries(log_lib ${libubox})
target_compile_definitions(log_lib PRIVATE HAVE_ULOG)
endif()
endif()
if(SOCKET_SUPPORT)
set(LIBRARIES ${LIBRARIES} socket_lib)
add_library(socket_lib MODULE lib/socket.c)
set_target_properties(socket_lib PROPERTIES OUTPUT_NAME socket PREFIX "")
target_link_options(socket_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
endif()
if(SERIAL_SUPPORT)
set(LIBRARIES ${LIBRARIES} serial_lib)
add_library(serial_lib MODULE lib/serial.c)
set_target_properties(serial_lib PROPERTIES OUTPUT_NAME serial PREFIX "")
target_link_options(serial_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
endif()
if(ZLIB_SUPPORT)
set(LIBRARIES ${LIBRARIES} zlib_lib)
add_library(zlib_lib MODULE lib/zlib.c)
set_target_properties(zlib_lib PROPERTIES OUTPUT_NAME zlib PREFIX "")
target_link_options(zlib_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(zlib_lib ZLIB::ZLIB)
if(ZLIB_CHUNK_SIZE)
target_compile_definitions(zlib_lib PRIVATE UC_ZLIB_CHUNK=${ZLIB_CHUNK_SIZE})
endif()
endif()
if(DIGEST_SUPPORT)
pkg_check_modules(LIBMD REQUIRED libmd)
include_directories(${LIBMD_INCLUDE_DIRS})
set(LIBRARIES ${LIBRARIES} digest_lib)
add_library(digest_lib MODULE lib/digest.c)
set_target_properties(digest_lib PROPERTIES OUTPUT_NAME digest PREFIX "")
if(DIGEST_SUPPORT_EXTENDED)
target_compile_definitions(digest_lib PRIVATE HAVE_DIGEST_EXTENDED)
endif()
target_link_options(digest_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(digest_lib ${libmd})
endif()
if(FFI_SUPPORT)
pkg_check_modules(LIBFFI REQUIRED libffi)
include_directories(${LIBFFI_INCLUDE_DIRS})
set(LIBRARIES ${LIBRARIES} ffi_lib)
add_library(ffi_lib MODULE lib/ffi/uc_cparse.c lib/ffi/uc_ctype.c lib/ffi/uc_cconv.c lib/ffi/uc_cdata.c lib/ffi/ffi.c)
set_target_properties(ffi_lib PROPERTIES OUTPUT_NAME ffi PREFIX "")
set(CMAKE_REQUIRED_INCLUDES ${LIBFFI_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${LIBFFI_LIBRARIES})
check_c_source_compiles("
#include <ffi.h>
int main() { return FFI_BAD_ARGTYPE; }
" HAVE_FFI_BAD_ARGTYPE)
if(HAVE_FFI_BAD_ARGTYPE)
target_compile_definitions(ffi_lib PRIVATE HAVE_FFI_BAD_ARGTYPE)
endif()
# A backend provides the predefined complex number types only when it
# defines FFI_TARGET_HAS_COMPLEX_TYPE, which powerpc does not. Only declare
# the symbols, as the check may compile to a static library when cross
# compiling, where referencing them would not be caught by the linker.
check_c_source_compiles("
#include <ffi.h>
ffi_type *types[] = { &ffi_type_complex_float, &ffi_type_complex_double,
&ffi_type_complex_longdouble };
int main() { return types != 0; }
" HAVE_FFI_COMPLEX_TYPES)
if(HAVE_FFI_COMPLEX_TYPES)
target_compile_definitions(ffi_lib PRIVATE HAVE_FFI_COMPLEX_TYPES)
endif()
target_link_options(ffi_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
target_link_libraries(ffi_lib ${LIBFFI_LINK_LIBRARIES})
endif()
if(NETADDR_SUPPORT)
set(LIBRARIES ${LIBRARIES} netaddr_lib)
add_library(netaddr_lib MODULE lib/netaddr.c)
set_target_properties(netaddr_lib PROPERTIES OUTPUT_NAME netaddr PREFIX "")
target_link_options(netaddr_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
endif()
endif() # UCODE_WASM
if(UCODE_WASM)
# ucode-modules.a: the selected modules with renamed uc_module_init
# symbols, for static linking into an embedder's executable together
# with libucode.a. The embedder calls uc_module_init_<name>() itself
# (e.g. to preload the modules into the global `modules` dictionary)
# and lists the names in config->force_dynlink_list.
set(UCODE_MODULE_OBJECTS "")
foreach(mod IN LISTS UCODE_WASM_MODULES)
add_library(ucode_mod_${mod} OBJECT lib/${mod}.c)
target_compile_definitions(ucode_mod_${mod} PRIVATE uc_module_init=uc_module_init_${mod})
target_include_directories(ucode_mod_${mod} PRIVATE include ${JSONC_INCLUDE_DIRS})
# the json-c headers only exist once the external project has built
add_dependencies(ucode_mod_${mod} json-c-build)
if(mod STREQUAL "zlib")
target_compile_options(ucode_mod_${mod} PRIVATE -sUSE_ZLIB=1)
endif()
if(mod STREQUAL "socket")
# emscripten's CMSG_NXTHDR() macro expands to a size_t/ptrdiff_t
# comparison; not fixable from the call site
target_compile_options(ucode_mod_${mod} PRIVATE -Wno-sign-compare)
endif()
if(mod STREQUAL "digest")
target_include_directories(ucode_mod_${mod} PRIVATE ${UCODE_DEPS_PREFIX}/libmd/dist/include)
add_dependencies(ucode_mod_${mod} libmd-build)
endif()
list(APPEND UCODE_MODULE_OBJECTS $<TARGET_OBJECTS:ucode_mod_${mod}>)
endforeach()
add_library(ucode-modules STATIC ${UCODE_MODULE_OBJECTS})
set_target_properties(ucode-modules PROPERTIES PREFIX "")
target_link_libraries(ucode-modules PUBLIC libucode libjson-c)
if("digest" IN_LIST UCODE_WASM_MODULES)
target_link_libraries(ucode-modules PUBLIC libmd)
endif()
if("zlib" IN_LIST UCODE_WASM_MODULES)
target_link_options(ucode-modules INTERFACE -sUSE_ZLIB=1)
endif()
endif()
if(NOT UCODE_WASM)
if(UNIT_TESTING)
enable_testing()
add_compile_definitions( UNIT_TESTING )
add_subdirectory(tests)
list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_executable(ucode-san ${CLI_SOURCES} ${UCODE_SOURCES})
set_property(TARGET ucode-san PROPERTY ENABLE_EXPORTS 1)
target_link_libraries(ucode-san uc_defines ${JSONC_LINK_LIBRARIES})
target_compile_options(ucode-san PRIVATE -g -fno-omit-frame-pointer -fsanitize=undefined,address,leak -fno-sanitize-recover=all)
target_link_options(ucode-san PRIVATE -fsanitize=undefined,address,leak)
endif()
endif()
endif() # UCODE_WASM
if(NOT UCODE_WASM)
add_executable(udbg udbg.c debug_highlight.c debug_lineedit.c)
target_link_libraries(udbg PRIVATE libucode ${JSONC_LINK_LIBRARIES})
endif()
if(UCODE_WASM)
install(TARGETS libucode ucode-modules ARCHIVE DESTINATION lib)
else()
install(TARGETS ucode udbg RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS libucode LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS ${LIBRARIES} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ucode)
endif()
if(NOT UCODE_WASM)
add_custom_target(utpl ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ucode utpl)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/utpl DESTINATION ${CMAKE_INSTALL_BINDIR})
if(COMPILE_SUPPORT)
add_custom_target(ucc ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ucode ucc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ucc DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif()
file(GLOB UCODE_HEADERS "include/ucode/*.h")
install(FILES ${UCODE_HEADERS} DESTINATION include/ucode)
if(NOT UCODE_WASM)
add_subdirectory(examples)
endif()