Skip to content

Commit b219e44

Browse files
committed
Add cmakelists
1 parent 85958a3 commit b219e44

5 files changed

Lines changed: 410 additions & 0 deletions

File tree

.github/workflows/cmake.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: CMake Build
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
build:
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
runs-on: [ubuntu-latest, macos-latest]
15+
runs-on: ${{ matrix.runs-on }}
16+
steps:
17+
- uses: actions/checkout@v3
18+
with:
19+
submodules: recursive
20+
fetch-depth: 0
21+
- uses: lukka/get-cmake@latest
22+
with:
23+
cmakeVersion: latest
24+
ninjaVersion: latest
25+
26+
- name: Build Summary ${{ matrix.targets }}
27+
run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DTESTS_BUILD=ON -DEXAMPLES_BUILD=ON; cmake --build build --parallel

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
tmp/*
33
.DS_Store
44
*.pem
5+
6+
build/

CMakeLists.txt

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
cmake_minimum_required(VERSION 3.12)
2+
3+
project(facil.io VERSION 0.8.0)
4+
5+
# Set the source directories
6+
set(LIB_ROOT lib)
7+
set(LIB_CONCAT_FOLDER fio-stl)
8+
9+
include_directories(".")
10+
11+
option(ENABLE_SHARED "Build facil.io as shared library" OFF)
12+
option(EXAMPLES_BUILD "Build Examples" OFF)
13+
option(TESTS_BUILD "Build Tests" OFF)
14+
15+
# Detect endianess
16+
include(CheckTypeSize)
17+
check_type_size("void*" SIZE_OF_POINTER)
18+
if(${SIZE_OF_POINTER} EQUAL 8)
19+
set(FLAGS "__BIG_ENDIAN__")
20+
else()
21+
set(FLAGS "__BIG_ENDIAN__=0")
22+
endif()
23+
24+
find_package(Threads REQUIRED)
25+
# Detect SSL/TLS Libraries
26+
find_package(OpenSSL 3.0)
27+
28+
if(OpenSSL_FOUND)
29+
message(STATUS "OpenSSL found.")
30+
else()
31+
message(WARNING "OpenSSL not found. SSL/TLS support will be disabled.")
32+
endif()
33+
34+
# Detect Sodium Library
35+
find_package(Sodium)
36+
37+
if(Sodium_FOUND)
38+
message(STATUS "Sodium found.")
39+
else()
40+
message(WARNING "Sodium not found. Sodium support will be disabled.")
41+
endif()
42+
43+
# Detect 'struct tm' fields
44+
include(CheckStructHasMember)
45+
check_struct_has_member("struct tm" tm_zone time.h HAVE_TM_TM_ZONE)
46+
47+
# Detect SystemV socket libraries
48+
include(CheckLibraryExists)
49+
check_library_exists(socket connect "" HAVE_SOCKET)
50+
check_library_exists(nsl gethostname "" HAVE_NSL)
51+
52+
if(HAVE_SOCKET AND HAVE_NSL)
53+
link_libraries(socket nsl)
54+
endif()
55+
if(WIN32)
56+
link_libraries(ws2_32)
57+
endif()
58+
59+
# Variable to track whether any of the checks have succeeded
60+
set(HAVE_SENDFILE FALSE)
61+
62+
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
63+
# Detect the `sendfile` system call for Linux
64+
if(NOT HAVE_SENDFILE)
65+
include(CheckCSourceCompiles)
66+
check_c_source_compiles("
67+
#define _GNU_SOURCE
68+
#include <stdlib.h>
69+
#include <stdio.h>
70+
#include <sys/sendfile.h>
71+
int main(void) {
72+
off_t offset = 0;
73+
ssize_t result = sendfile(2, 1, (off_t *)&offset, 300);
74+
}
75+
" HAVE_SENDFILE_LINUX)
76+
77+
if(HAVE_SENDFILE_LINUX)
78+
set(FLAGS "${FLAGS} USE_SENDFILE_LINUX HAVE_SENDFILE")
79+
set(HAVE_SENDFILE TRUE)
80+
endif()
81+
endif()
82+
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
83+
# Detect the `sendfile` system call for Apple
84+
if(NOT HAVE_SENDFILE)
85+
check_c_source_compiles("
86+
#define _GNU_SOURCE
87+
#include <stdlib.h>
88+
#include <stdio.h>
89+
#include <sys/types.h>
90+
#include <sys/socket.h>
91+
#include <sys/uio.h>
92+
int main(void) {
93+
off_t sent = 0;
94+
off_t offset = 0;
95+
ssize_t result = sendfile(2, 1, offset, &sent, NULL, 0);
96+
}
97+
" HAVE_SENDFILE_APPLE)
98+
99+
if(HAVE_SENDFILE_APPLE)
100+
set(FLAGS "${FLAGS} USE_SENDFILE_APPLE HAVE_SENDFILE")
101+
set(HAVE_SENDFILE TRUE)
102+
endif()
103+
endif()
104+
else()
105+
# Detect the `sendfile` system call for BSD
106+
if(NOT HAVE_SENDFILE)
107+
check_c_source_compiles("
108+
#define _GNU_SOURCE
109+
#include <stdlib.h>
110+
#include <stdio.h>
111+
#include <sys/types.h>
112+
#include <sys/socket.h>
113+
#include <sys/uio.h>
114+
int main(void) {
115+
off_t sent = 0;
116+
off_t offset = 0;
117+
ssize_t result = sendfile(2, 1, offset, (size_t)sent, NULL, &sent, 0);
118+
}
119+
" HAVE_SENDFILE_BSD)
120+
121+
if(HAVE_SENDFILE_BSD)
122+
set(FLAGS "${FLAGS} USE_SENDFILE_BSD HAVE_SENDFILE")
123+
set(HAVE_SENDFILE TRUE)
124+
endif()
125+
endif()
126+
endif()
127+
128+
# Detect IOCP support for Windows
129+
if(WIN32)
130+
if(NOT HAVE_IOCP)
131+
check_c_source_compiles("
132+
#include <winsock2.h>
133+
#include <windows.h>
134+
int main(void) {
135+
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
136+
if (iocp == NULL) {
137+
return 1;
138+
}
139+
CloseHandle(iocp);
140+
return 0;
141+
}
142+
" HAVE_IOCP)
143+
144+
if(HAVE_IOCP)
145+
set(FLAGS "${FLAGS} FIO_ENGINE_IOCP HAVE_IOCP")
146+
else()
147+
message(FATAL_ERROR "No supported polling engine detected. Unable to compile facil.io.")
148+
endif()
149+
endif()
150+
else()
151+
# Detect polling mechanisms (kqueue / epoll / poll)
152+
if(NOT HAVE_KQUEUE AND NOT HAVE_EPOLL AND NOT HAVE_POLL)
153+
check_c_source_compiles("
154+
#define _GNU_SOURCE
155+
#include <stdlib.h>
156+
#include <sys/event.h>
157+
int main(void) {
158+
int fd = kqueue();
159+
}
160+
" HAVE_KQUEUE)
161+
162+
if(HAVE_KQUEUE)
163+
set(FLAGS "${FLAGS} FIO_ENGINE_KQUEUE HAVE_KQUEUE")
164+
else()
165+
check_c_source_compiles("
166+
#define _GNU_SOURCE
167+
#include <stdlib.h>
168+
#include <stdio.h>
169+
#include <sys/types.h>
170+
#include <sys/stat.h>
171+
#include <fcntl.h>
172+
#include <sys/epoll.h>
173+
int main(void) {
174+
int fd = epoll_create1(EPOLL_CLOEXEC);
175+
}
176+
" HAVE_EPOLL)
177+
178+
if(HAVE_EPOLL)
179+
set(FLAGS "${FLAGS} FIO_ENGINE_EPOLL HAVE_EPOLL")
180+
else()
181+
check_c_source_compiles("
182+
#define _GNU_SOURCE
183+
#include <stdlib.h>
184+
#include <poll.h>
185+
int main(void) {
186+
struct pollfd plist[18];
187+
memset(plist, 0, sizeof(plist[0]) * 18);
188+
poll(plist, 1, 1);
189+
}
190+
" HAVE_POLL)
191+
192+
if(HAVE_POLL)
193+
set(FLAGS "${FLAGS} FIO_ENGINE_POLL HAVE_POLL")
194+
else()
195+
message(FATAL_ERROR "No supported polling engine detected. Unable to compile facil.io.")
196+
endif()
197+
endif()
198+
endif()
199+
endif()
200+
endif()
201+
202+
203+
# Define the source files for the library
204+
file(GLOB_RECURSE LIB_SOURCES ${LIB_ROOT}/*.c ${LIB_ROOT}/*.cpp ${LIB_ROOT}/*.cxx ${LIB_ROOT}/*.c++)
205+
set(SOURCES ${LIB_SOURCES})
206+
207+
# Optimization level
208+
set(OPTIMIZATION "-O3")
209+
# Optimization level in debug mode
210+
set(OPTIMIZATION_DEBUG "-O0 -g -coverage -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-builtin")
211+
# Warning flags
212+
set(WARNINGS "-Wno-missing-field-initializers -Wformat-security")
213+
# Preprocessor definitions
214+
set(FLAGS "-DFIO_LEAK_COUNTER -DFIO_FIOBJ -DFIOBJ_MALLOC")
215+
if(WIN32 AND NOT MSVC)
216+
set(FLAGS "${FLAGS} -D_GNU_SOURCE -D__MINGW32__")
217+
endif()
218+
# C specific compiler options
219+
set(C_EXTRA_OPT "")
220+
# C++ specific compiler options
221+
set(CXX_EXTRA_OPT "-Wno-keyword-macro -Wno-vla-extension -Wno-c99-extensions -Wno-zero-length-array -Wno-variadic-macros -Wno-missing-braces")
222+
223+
# Create the library target
224+
if(ENABLE_SHARED)
225+
add_library(${PROJECT_NAME} SHARED ${SOURCES})
226+
if(OpenSSL_FOUND)
227+
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads OpenSSL::SSL OpenSSL::Crypto)
228+
elseif(Sodium_FOUND)
229+
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads Sodium::Sodium)
230+
else()
231+
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads)
232+
endif()
233+
else()
234+
add_library(${PROJECT_NAME} STATIC ${SOURCES})
235+
endif()
236+
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
237+
target_include_directories(${PROJECT_NAME} PUBLIC ".")
238+
# Add the definitions to the target
239+
target_compile_options(${PROJECT_NAME} PRIVATE
240+
$<$<CONFIG:Debug>:${OPTIMIZATION_DEBUG} ${WARNINGS} ${CXX_EXTRA_OPT}> "-DDEBUG=1"
241+
$<$<NOT:$<CONFIG:Debug>>:${OPTIMIZATION} ${WARNINGS}>
242+
)
243+
target_compile_definitions(${PROJECT_NAME} PRIVATE ${FLAGS})
244+
245+
set(PKG_CONFIG_FILE "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
246+
configure_file(${PROJECT_NAME}.pc.in ${PKG_CONFIG_FILE} @ONLY)
247+
248+
# Install the generated .pc file
249+
install(FILES ${PKG_CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
250+
251+
if(EXAMPLES_BUILD)
252+
# Define a function to build and run an example
253+
function(build_and_run_example EXAMPLE_NAME)
254+
add_executable(${EXAMPLE_NAME} examples/${EXAMPLE_NAME}.c)
255+
if(${EXAMPLE_NAME} STREQUAL server OR ${EXAMPLE_NAME} STREQUAL client)
256+
if(Sodium_FOUND)
257+
target_link_libraries(${EXAMPLE_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads Sodium::Sodium)
258+
elseif(OpenSSL_FOUND)
259+
target_link_libraries(${EXAMPLE_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads OpenSSL::SSL OpenSSL::Crypto)
260+
else()
261+
target_link_libraries(${EXAMPLE_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads)
262+
endif()
263+
else()
264+
target_link_libraries(${EXAMPLE_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads)
265+
endif()
266+
target_compile_definitions(${EXAMPLE_NAME} PRIVATE ${FLAGS})
267+
add_custom_target(run_${EXAMPLE_NAME}
268+
COMMAND ${EXAMPLE_NAME}
269+
DEPENDS ${EXAMPLE_NAME}
270+
)
271+
endfunction()
272+
273+
# List of example files to build and run
274+
# comment all examples w/ issue build
275+
set(EXAMPLES
276+
array
277+
bstr
278+
chat
279+
client
280+
# fiobj
281+
map
282+
server
283+
string
284+
)
285+
286+
# Build and run each example
287+
foreach(EXAMPLE ${EXAMPLES})
288+
build_and_run_example(${EXAMPLE})
289+
endforeach()
290+
endif()
291+
292+
if(TESTS_BUILD)
293+
# Define a function to build and run a test
294+
function(build_and_run_test TEST_NAME)
295+
if(${TEST_NAME} STREQUAL cpp)
296+
add_executable(${TEST_NAME} tests/${TEST_NAME}.cpp)
297+
else()
298+
add_executable(${TEST_NAME} tests/${TEST_NAME}.c)
299+
endif()
300+
if(${TEST_NAME} STREQUAL base64 OR ${TEST_NAME} STREQUAL stl-mutex)
301+
if(Sodium_FOUND)
302+
target_link_libraries(${TEST_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads Sodium::Sodium)
303+
elseif(OpenSSL_FOUND)
304+
target_link_libraries(${TEST_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads OpenSSL::SSL OpenSSL::Crypto)
305+
endif()
306+
else()
307+
target_link_libraries(${TEST_NAME} PUBLIC ${PROJECT_NAME} PRIVATE Threads::Threads)
308+
endif()
309+
target_compile_definitions(${TEST_NAME} PRIVATE ${FLAGS} "-DTESTS=1")
310+
add_custom_target(run_${TEST_NAME}
311+
COMMAND ${TEST_NAME}
312+
DEPENDS ${TEST_NAME}
313+
)
314+
endfunction()
315+
316+
# List of test files to build and run
317+
# comment all tests w/ issue build
318+
set(TESTS
319+
# array
320+
base64
321+
# cpp
322+
http1-parser-old
323+
http1-parser
324+
# json
325+
# json_find
326+
# json_minify
327+
malloc
328+
mempool
329+
# mustache
330+
noop
331+
# random
332+
slowloris
333+
# stl-mutex
334+
# stl
335+
url
336+
)
337+
338+
# Build and run each test
339+
foreach(TEST ${TESTS})
340+
build_and_run_test(${TEST})
341+
endforeach()
342+
endif()

0 commit comments

Comments
 (0)