CMakeLists.txt (view raw)
1cmake_minimum_required(VERSION 3.10)
2
3# project specification
4
5project(nimisewi
6 VERSION 0.3.3
7 DESCRIPTION "small program that generates random toki pona noun phrase"
8 HOMEPAGE_URL "https://fsl.aaoth.xyz/nimisewi.c/home"
9 LANGUAGES C)
10
11# get compiler name and version
12
13execute_process(COMMAND ${CMAKE_C_COMPILER} "--version"
14 OUTPUT_VARIABLE _PROJECT_C_COMPILER_VERSION)
15string(REGEX REPLACE "\n" ";"
16 PROJECT_C_COMPILER_VERSION ${_PROJECT_C_COMPILER_VERSION})
17list(APPEND PROJECT_C_COMPILER_STRING ${PROJECT_C_COMPILER_VERSION})
18list(POP_FRONT PROJECT_C_COMPILER_STRING PROJECT_C_COMPILER_VERSION)
19
20# configuration header
21
22configure_file(config.h.in config.h)
23
24# warnings
25
26add_compile_options(-g -W -Wall -Wextra -pedantic -Wmissing-prototypes
27 -Wstrict-prototypes -Wwrite-strings)
28
29# main executable
30
31add_executable(nimisewi main.c nimisewi.c
32 ${PROJECT_BINARY_DIR}/nimitoki.c)
33target_include_directories(nimisewi PUBLIC "${PROJECT_BINARY_DIR}")
34
35# supplementary executable
36
37add_executable(makenimitoki makenimitoki.c)
38target_include_directories(makenimitoki PUBLIC "${PROJECT_BINARY_DIR}")
39
40add_custom_command(
41 OUTPUT ${PROJECT_BINARY_DIR}/nimitoki.c
42 ${PROJECT_BINARY_DIR}/nimitoki.h
43 COMMAND makenimitoki ${PROJECT_SOURCE_DIR}/nimitoki.txt
44 DEPENDS makenimitoki)
45
46# includes
47
48include(CheckIncludeFile)
49include(CheckSymbolExists)
50include(CheckCSourceCompiles)
51
52# warning message
53
54set(WARNING_STATIC_BUILD "static build won't work here")
55
56# check libraries
57
58cmake_host_system_information(RESULT OS_NAME QUERY OS_NAME)
59message(VERBOSE "OS_NAME is ${OS_NAME}")
60if(OS_NAME MATCHES "Linux")
61 check_include_file("bsd/string.h" HAVE_BSD_STRING_H)
62 check_include_file("bsd/stdlib.h" HAVE_BSD_STDLIB_H)
63 if(HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H)
64 set(CMAKE_REQUIRED_LIBRARIES "bsd")
65
66 check_symbol_exists(strlcat "bsd/string.h" HAVE_STRLCAT)
67 if(HAVE_STRLCAT)
68 list(APPEND EXTRA_DEFINITIONS HAVE_BSD_STRING_H HAVE_STRLCAT)
69 endif() # HAVE_STRLCAT
70
71 check_symbol_exists(arc4random_uniform "bsd/stdlib.h"
72 HAVE_ARC4RANDOM_UNIFORM)
73 if(HAVE_ARC4RANDOM_UNIFORM)
74 list(APPEND EXTRA_DEFINITIONS HAVE_BSD_STDLIB_H HAVE_ARC4RANDOM_UNIFORM)
75 endif() # HAVE_ARC4RANDOM_UNIFORM
76
77 # check static libraries
78 set(CMAKE_REQUIRED_LINK_OPTIONS "-static")
79 check_c_source_compiles(
80 "#include<bsd/string.h>\nint main(void){return 0;}"
81 HAVE_LIBBSD_STATIC)
82
83 if(NOT ANDROID)
84 # libpthread and libmd are needed when linking statically on linux.
85 # these test aren't really checking particular functions, but
86 # they are here to make sure that program could be linked statically
87 unset(CMAKE_REQUIRED_LIBRARIES)
88 set(CMAKE_REQUIRED_LIBRARIES "pthread")
89 check_c_source_compiles(
90 "#include<pthread.h>\nint main(void){return 0;}"
91 HAVE_LIBPTHREAD_STATIC)
92
93 unset(CMAKE_REQUIRED_LIBRARIES)
94 set(CMAKE_REQUIRED_LIBRARIES "md")
95 check_c_source_compiles(
96 "#include<sha2.h>\nint main(void){return 0;}"
97 HAVE_LIBMD_STATIC)
98
99 if(NOT HAVE_LIBBSD_STATIC)
100 list(APPEND _MISSING_STATIC_LIBS libbsd)
101 if(NOT HAVE_LIBPTHREAD_STATIC)
102 list(APPEND _MISSING_STATIC_LIBS libpthread)
103 if(NOT HAVE_LIBMD_STATIC)
104 list(APPEND _MISSING_STATIC_LIBS libmd)
105 message(WARNING ${WARNING_STATIC_BUILD})
106 endif() # NOT HAVE_LIBMD_STATIC
107 endif() # NOT HAVE_LIBPTHREAD_STATIC
108 endif() # NOT HAVE_LIBBSD_STATIC
109
110 list(APPEND EXTRA_LIBS bsd pthread md)
111
112 else() # NOT ANDROID
113
114 if(NOT (HAVE_LIBBSD_STATIC))
115 list(APPEND _MISSING_STATIC_LIBS libbsd)
116 message(WARNING ${WARNING_STATIC_BUILD})
117 endif()
118 list(APPEND EXTRA_LIBS bsd)
119
120 endif() # NOT ANDROID
121
122 unset(CMAKE_REQUIRED_LIBRARIES)
123 unset(CMAKE_REQUIRED_LINK_OPTIONS)
124
125 endif() # HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H
126
127endif() # OS_NAME MATCHES "Linux"
128
129if(OS_NAME MATCHES "(.*BSD)|(DragonFly)")
130 check_symbol_exists(strlcat "string.h" HAVE_STRLCAT)
131
132 if(HAVE_STRLCAT)
133 list(APPEND EXTRA_DEFINITIONS HAVE_STRLCAT)
134 endif() # HAVE_STRLCAT
135
136 check_symbol_exists(arc4random_uniform "stdlib.h" HAVE_ARC4RANDOM_UNIFORM)
137 if(HAVE_ARC4RANDOM_UNIFORM)
138 list(APPEND EXTRA_DEFINITIONS HAVE_ARC4RANDOM_UNIFORM)
139 endif() # HAVE_ARC4RANDOM_UNIFORM
140
141 check_symbol_exists(pledge "unistd.h" HAVE_PLEDGE)
142 if(HAVE_PLEDGE)
143 list(APPEND EXTRA_DEFINITIONS HAVE_PLEDGE)
144 endif() # HAVE_PLEDGE
145
146endif() # OS_NAME MATCHES "(.*BSD)|(DragonFly)"
147
148set(CMAKE_REQUIRED_LINK_OPTIONS "-static")
149check_c_source_compiles(
150 "#include<stdio.h>\nint main(void){return 0;}" HAVE_LIBC_STATIC
151 )
152if(NOT HAVE_LIBC_STATIC)
153 list(APPEND _MISSING_STATIC_LIBS libc)
154 message(WARNING ${WARNING_STATIC_BUILD})
155endif() # NOT HAVE_LIBC_STATIC
156
157target_link_libraries(nimisewi PUBLIC ${EXTRA_LIBS})
158target_compile_definitions(nimisewi PRIVATE ${EXTRA_DEFINITIONS})
159
160set(NIMISEWI_CGI_STATIC_BUILD FALSE)
161if(HAVE_LIBC_STATIC)
162 if(HAVE_BSD_STRING_H AND HAVE_BSD_STDLIB_H)
163 if(HAVE_LIBBSD_STATIC)
164 set(NIMISEWI_CGI_STATIC_BUILD TRUE)
165 endif() # HAVE_LIBBSD_STATIC
166 else() # HAVE_BSD_STRING_H AND ...
167 set(NIMISEWI_CGI_STATIC_BUILD TRUE)
168 endif() # HAVE_BSD_STRING_H AND ...
169endif() # HAVE_LIBBSD_STATIC
170
171# options
172
173option(NIMISEWI_STATIC_BUILD "build static version of nimisewi" OFF)
174if(NIMISEWI_STATIC_BUILD)
175 if(NIMISEWI_CGI_STATIC_BUILD)
176 target_link_options(nimisewi.cgi PUBLIC -static)
177 else() # NIMISEWI_CGI_STATIC_BUILD
178 message(SEND_ERROR
179 "missing ${_MISSING_STATIC_LIBS}. will not link statically. \
180 consider installing such libraries or switching off this option")
181 endif() # NIMISEWI_CGI_STATIC_BUILD
182endif() # NIMISEWI_STATIC_BUILD
183
184# optional binaries
185
186option(BUILD_CGI "build cgi version of nimisewi" OFF)
187if(BUILD_CGI)
188 add_executable(nimisewi.cgi cgi.c nimisewi.c
189 ${PROJECT_BINARY_DIR}/nimitoki.c)
190 option(CGI_INSTALL_DIR "specify installation directory of cgi script")
191
192 if(CGI_INSTALL_DIR)
193 set_property(TARGET nimisewi.cgi PROPERTY CGI_INSTALL_DIR
194 ${CGI_INSTALL_DIR})
195 else() # CGI_INSTALL_DIR
196 set_property(TARGET nimisewi.cgi PROPERTY CGI_INSTALL_DIR
197 "var/www/htdocs/cgi-bin")
198 endif() # CGI_INSTALL_DIR
199
200 target_include_directories(nimisewi.cgi PUBLIC "${PROJECT_BINARY_DIR}")
201 target_compile_definitions(nimisewi.cgi PRIVATE ${EXTRA_DEFINITIONS})
202 target_link_libraries(nimisewi.cgi PUBLIC ${EXTRA_LIBS})
203
204 if(NIMISEWI_CGI_STATIC_BUILD)
205 target_link_options(nimisewi.cgi PUBLIC -static)
206 endif() # NIMISEWI_CGI_STATIC_BUILD
207
208endif() # BUILD_CGI
209
210option(BUILD_GEMINI_CGI "build cgi version of nimisewi for gemini protocol" OFF)
211if(BUILD_GEMINI_CGI)
212 add_executable(nimisewi_gemini.cgi cgi_gemini.c nimisewi.c
213 ${PROJECT_BINARY_DIR}/nimitoki.c)
214 option(GEMINI_CGI_INSTALL_DIR "specify installation directory of cgi script")
215
216 if(GEMINI_CGI_INSTALL_DIR)
217 set_property(TARGET nimisewi_gemini.cgi PROPERTY GEMINI_CGI_INSTALL_DIR
218 ${GEMINI_CGI_INSTALL_DIR})
219 else() # GEMINI_CGI_INSTALL_DIR
220 set_property(TARGET nimisewi_gemini.cgi PROPERTY GEMINI_CGI_INSTALL_DIR
221 "var/gemini/cgi-bin")
222 endif() # GEMINI_CGI_INSTALL_DIR
223
224 target_include_directories(nimisewi_gemini.cgi PUBLIC "${PROJECT_BINARY_DIR}")
225 target_compile_definitions(nimisewi_gemini.cgi PRIVATE ${EXTRA_DEFINITIONS})
226 target_link_libraries(nimisewi_gemini.cgi PUBLIC ${EXTRA_LIBS})
227
228 if(NIMISEWI_CGI_STATIC_BUILD)
229 target_link_options(nimisewi_gemini.cgi PUBLIC -static)
230 endif() # NIMISEWI_CGI_STATIC_BUILD
231
232endif() # BUILD_GEMINI_CGI
233
234# installation
235
236install(TARGETS nimisewi DESTINATION bin)
237
238if(BUILD_CGI)
239 install(TARGETS nimisewi.cgi
240 DESTINATION $<TARGET_PROPERTY:nimisewi.cgi,CGI_INSTALL_DIR>)
241endif() # BUILD_CGI
242
243if(BUILD_GEMINI_CGI)
244 install(TARGETS nimisewi_gemini.cgi
245 DESTINATION $<TARGET_PROPERTY:nimisewi_gemini.cgi,GEMINI_CGI_INSTALL_DIR>)
246endif() # BUILD_GEMINI_CGI
247
248# packaging
249
250include(InstallRequiredSystemLibraries)
251set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
252set(CPACK_PROJECT_VERSION_MAJOR ${nimisewi_VERSION_MAJOR})
253set(CPACK_PROJECT_VERSION_MINOR ${nimisewi_VERSION_MINOR})
254set(CPACK_PROJECT_VERSION_PATCH ${nimisewi_VERSION_PATCH})
255set(CPACK_PACKAGE_FILE_NAME
256 ${CMAKE_PROJECT_NAME}-${nimisewi_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR})
257set(CPACK_GENERATOR "TGZ" "ZIP")
258set(CPACK_SOURCE_GENERATOR "TGZ" "ZIP")
259set(CPACK_SOURCE_IGNORE_FILES
260 \.fslckout
261 \.fossil-settings
262 build/
263 utils/
264 download.md
265 )
266set(CPACK_STRIP_FILES TRUE)
267include(CPack)
268
269# testing
270
271enable_testing()
272
273add_test(NAME runs COMMAND nimisewi)
274
275add_test(NAME version COMMAND nimisewi -v)
276set_tests_properties(version
277 PROPERTIES PASS_REGULAR_EXPRESSION
278 "nimisewi [0-9]\.[0-9]\.[0-9]\n[a-z ]+(\n([A-Z_]+(\n)?)+)?")
279
280if(BUILD_CGI)
281 add_test(NAME cgi COMMAND nimisewi.cgi)
282 set_tests_properties(cgi
283 PROPERTIES PASS_REGULAR_EXPRESSION
284 "Status: 200 OK\rContent-Type: text\/html\r\r<.*>")
285endif() # BUILD_CGI
286
287if(BUILD_GEMINI_CGI)
288 add_test(NAME gemini_cgi COMMAND nimisewi_gemini.cgi)
289 set_tests_properties(gemini_cgi
290 PROPERTIES PASS_REGULAR_EXPRESSION "20 text\/gemini\r\n.*")
291endif() # BUILD_GEMINI_CGI