summaryrefslogtreecommitdiffhomepage
path: root/CMakeLists.txt
blob: 9c2aead6b68afa86504f28a008d83debf9c3b711 (plain)
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
cmake_minimum_required(VERSION 3.13)
include(CheckFunctionExists)
include(CheckSymbolExists)

PROJECT(ucode C)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -ffunction-sections -fwrapv -D_GNU_SOURCE)

IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
	ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
	ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral)
ENDIF()
ADD_DEFINITIONS(-Wmissing-declarations -Wno-error=unused-variable -Wno-unused-parameter)

INCLUDE_DIRECTORIES(include)

OPTION(COMPILE_SUPPORT "Support compilation from source" ON)

IF(NOT COMPILE_SUPPORT)
  ADD_DEFINITIONS(-DNO_COMPILE)
ENDIF()

OPTION(DEBUG_SUPPORT "Debug plugin support" ON)
OPTION(FS_SUPPORT "Filesystem plugin support" ON)
OPTION(MATH_SUPPORT "Math plugin support" ON)
OPTION(UBUS_SUPPORT "Ubus plugin support" ON)
OPTION(UCI_SUPPORT "UCI plugin support" ON)
OPTION(RTNL_SUPPORT "Route Netlink plugin support" ${LINUX})
OPTION(NL80211_SUPPORT "Wireless Netlink plugin support" ${LINUX})
OPTION(RESOLV_SUPPORT "NS resolve plugin support" ON)
OPTION(STRUCT_SUPPORT "Struct plugin support" ON)
OPTION(ULOOP_SUPPORT "Uloop plugin support" ON)

SET(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/lib/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path")
STRING(REPLACE ":" "\", \"" LIB_SEARCH_DEFINE "${LIB_SEARCH_PATH}")
ADD_DEFINITIONS(-DLIB_SEARCH_PATH="${LIB_SEARCH_DEFINE}")

IF(APPLE)
  SET(UCODE_MODULE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup")
  ADD_DEFINITIONS(-DBIND_8_COMPAT)
ELSE()
  SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,--gc-sections")
ENDIF()

IF(DEBUG)
  ADD_DEFINITIONS(-DDEBUG -g3 -O0)
ELSE()
  ADD_DEFINITIONS(-DNDEBUG)
ENDIF()

INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(JSONC REQUIRED json-c)
INCLUDE_DIRECTORIES(${JSONC_INCLUDE_DIRS})

SET(UCODE_SOURCES lexer.c lib.c vm.c chunk.c vallist.c compiler.c source.c types.c program.c platform.c)
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})
TARGET_LINK_LIBRARIES(libucode ${JSONC_LINK_LIBRARIES})

SET(CLI_SOURCES main.c)
ADD_EXECUTABLE(ucode ${CLI_SOURCES})
TARGET_LINK_LIBRARIES(ucode libucode ${JSONC_LINK_LIBRARIES})

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()

SET(CMAKE_REQUIRED_INCLUDES ${JSONC_INCLUDE_DIRS})
SET(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)
  ADD_DEFINITIONS(-DHAVE_PARSE_END)
ENDIF()
CHECK_SYMBOL_EXISTS(json_object_new_array_ext "json-c/json.h" HAVE_ARRAY_EXT)
IF(HAVE_ARRAY_EXT)
  ADD_DEFINITIONS(-DHAVE_ARRAY_EXT)
ENDIF()
CHECK_SYMBOL_EXISTS(json_object_new_uint64 "json-c/json.h" HAVE_JSON_UINT64)
IF(HAVE_JSON_UINT64)
  ADD_DEFINITIONS(-DHAVE_JSON_UINT64)
ENDIF()
UNSET(CMAKE_REQUIRED_INCLUDES)
UNSET(CMAKE_REQUIRED_LIBRARIES)

SET(LIBRARIES "")

IF(DEBUG_SUPPORT)
  SET(LIBRARIES ${LIBRARIES} debug_lib)
  ADD_LIBRARY(debug_lib MODULE lib/debug.c)
  SET_TARGET_PROPERTIES(debug_lib PROPERTIES OUTPUT_NAME debug PREFIX "")
  TARGET_LINK_OPTIONS(debug_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
  FIND_LIBRARY(ubox NAMES ubox)
  IF(ubox)
    FIND_PATH(uloop_include_dir NAMES libubox/uloop.h)
    INCLUDE_DIRECTORIES(${uloop_include_dir})
    TARGET_LINK_LIBRARIES(debug_lib ${ubox} ${libucode})
    SET_TARGET_PROPERTIES(debug_lib PROPERTIES COMPILE_DEFINITIONS 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(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_LIBRARY(ubus NAMES ubus)
  FIND_LIBRARY(blobmsg_json NAMES blobmsg_json)
  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 ${ubus} ${blobmsg_json})
  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")
  IF(HAVE_NEW_UBUS_STATUS_CODES)
    ADD_DEFINITIONS(-DHAVE_NEW_UBUS_STATUS_CODES)
  ENDIF()
ENDIF()

IF(UCI_SUPPORT)
  FIND_LIBRARY(uci NAMES uci)
  FIND_LIBRARY(ubox NAMES ubox)
  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)
  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 ${uci} ${ubox})
ENDIF()

IF(RTNL_SUPPORT)
  FIND_LIBRARY(nl NAMES nl-tiny)
  FIND_LIBRARY(ubox NAMES ubox)
  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 ${nl} ${ubox})
ENDIF()

IF(NL80211_SUPPORT)
  FIND_LIBRARY(nl NAMES nl-tiny)
  FIND_LIBRARY(ubox NAMES ubox)
  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 ${nl} ${ubox})
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_LIBRARY(ubox NAMES ubox)
  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})
  SET(CMAKE_REQUIRED_LIBRARIES ${ubox})
  CHECK_FUNCTION_EXISTS(uloop_timeout_remaining64 REMAINING64_FUNCTION_EXISTS)
  UNSET(CMAKE_REQUIRED_LIBRARIES)
  IF (REMAINING64_FUNCTION_EXISTS)
    TARGET_COMPILE_DEFINITIONS(uloop_lib PUBLIC HAVE_ULOOP_TIMEOUT_REMAINING64)
  ENDIF()
  TARGET_LINK_LIBRARIES(uloop_lib ${ubox})
ENDIF()

IF(UNIT_TESTING)
  ENABLE_TESTING()
  ADD_DEFINITIONS(-DUNIT_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 ${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()

INSTALL(TARGETS ucode RUNTIME DESTINATION bin)
INSTALL(TARGETS libucode LIBRARY DESTINATION lib)
INSTALL(TARGETS ${LIBRARIES} LIBRARY DESTINATION lib/ucode)

ADD_CUSTOM_TARGET(utpl ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ucode utpl)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/utpl DESTINATION bin)

IF(COMPILE_SUPPORT)
  ADD_CUSTOM_TARGET(ucc ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ucode ucc)
  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ucc DESTINATION bin)
ENDIF()

FILE(GLOB UCODE_HEADERS "include/ucode/*.h")
INSTALL(FILES ${UCODE_HEADERS} DESTINATION include/ucode)

ADD_SUBDIRECTORY(examples)