From 3ad20d71ffd6828d7b3596361f56f74a2b35a281 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 12 Jan 2020 23:45:03 +0100 Subject: [PATCH] build: refactor config infrastructure and test build setup * Configuration is now done with files, instead of through command line switches specified in CMakeLists.txt. * Link tests with a static library instead of compiling individual wepoll source files as part of the test executable. This should make the CI run significantly faster. --- .gitignore | 1 + CMakeLists.txt | 173 +++++++++++++------- config/external/dllexport/config-external.h | 5 + config/external/static/config-external.h | 1 + config/internal/bundle/config-internal.h | 2 + config/internal/default/config-internal.h | 2 + include/wepoll.h | 4 +- src/afd.h | 2 +- src/api.h | 2 +- src/bundle/internal.h | 7 - src/config.h | 6 + src/error.h | 2 +- src/init.h | 2 +- src/nt.h | 2 +- src/poll-group.h | 2 +- src/port.h | 2 +- src/queue.h | 2 +- src/reflock.h | 2 +- src/regular/internal.h | 7 - src/sock.h | 2 +- src/thread-safe-tree.h | 2 +- src/tree.h | 2 +- src/ws.h | 2 +- test/shared/test-util.h | 4 +- 24 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 config/external/dllexport/config-external.h create mode 100644 config/external/static/config-external.h create mode 100644 config/internal/bundle/config-internal.h create mode 100644 config/internal/default/config-internal.h delete mode 100644 src/bundle/internal.h create mode 100644 src/config.h delete mode 100644 src/regular/internal.h diff --git a/.gitignore b/.gitignore index e23086c..ef5cae9 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ /CMakeScripts/ /Debug/ /dist/ +/gen/ /ipch/ /lib/ /MinSizeRel/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b1d6031..86cb6ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.0.0) project(wepoll) +include(CMakeParseArguments) + link_libraries(ws2_32) if(MSVC) @@ -15,91 +17,148 @@ endif() # Work around bug in in Windows SDK 10.0.17763.0 and maybe other versions. add_definitions(-D_CRT_HAS_CXX17=0) -set(DIST_DIR "dist") -set(TEST_RUNNER "tools/run-tests.js") - -file(GLOB SOURCES_HEADER include/*.h) +file(GLOB SOURCES_DOC LICENSE *.md) +file(GLOB_RECURSE SOURCES_CONFIG config/*.h) +file(GLOB SOURCES_CONFIG_EXTERNAL_DLLEXPORT config/external/dllexport/*.h) +file(GLOB SOURCES_CONFIG_EXTERNAL_STATIC config/external/static/*.h) +file(GLOB SOURCES_CONFIG_INTERNAL_BUNDLE config/internal/bundle/*.h) +file(GLOB SOURCES_CONFIG_INTERNAL_DEFAULT config/internal/default/*.h) +file(GLOB SOURCES_INCLUDE include/*.h) file(GLOB SOURCES_SRC src/*.c src/*.h) file(GLOB SOURCES_SRC_C src/*.c) -file(GLOB SOURCES_SRC_REGULAR src/regular/*.c src/regular/*.h) -file(GLOB SOURCES_SRC_BUNDLE src/bundle/*.c src/bundle/*.h) file(GLOB SOURCES_TEST test/*.c) file(GLOB SOURCES_TEST_SHARED test/shared/*.c test/shared/*.h) -file(GLOB SOURCES_DOC LICENSE *.md) - -get_filename_component(HEADER_NAME ${SOURCES_HEADER} NAME_WE) -string(TOUPPER ${HEADER_NAME} HEADER_NAME_UC) - -set(BUNDLE_HEADER "${DIST_DIR}/${HEADER_NAME}.h") -set(BUNDLE_SRC "${DIST_DIR}/${HEADER_NAME}.c") -set(DLL_NAME "${HEADER_NAME}") -set(BUNDLE_DLL_NAME "${HEADER_NAME}-bundle") set_property(GLOBAL PROPERTY USE_FOLDERS ON) -source_group("" FILES ${SOURCES_HEADER}) +source_group(doc FILES ${SOURCES_DOC}) +source_group(config FILES ${SOURCES_CONFIG}) +source_group(include FILES ${SOURCES_INCLUDE}) source_group(src FILES ${SOURCES_SRC}) -source_group(src FILES ${SOURCES_SRC_REGULAR}) -source_group(src FILES ${SOURCES_SRC_BUNDLE}) source_group("" FILES ${SOURCES_TEST}) source_group(test/shared FILES ${SOURCES_TEST_SHARED}) -source_group(doc FILES ${SOURCES_DOC}) -source_group(${DIST_DIR} FILES ${BUNDLE_HEADER} ${BUNDLE_SRC}) -add_custom_command( - OUTPUT ${BUNDLE_HEADER} - COMMAND node tools/bundle.js ${SOURCES_HEADER} > ${BUNDLE_HEADER} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - IMPLICIT_DEPENDS c ${SOURCES_HEADER} -) +get_filename_component(LIB_NAME ${SOURCES_INCLUDE} NAME_WE) -add_custom_command( - OUTPUT ${BUNDLE_SRC} - COMMAND node tools/bundle.js -Iinclude -Isrc -Isrc/bundle --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${BUNDLE_SRC} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - IMPLICIT_DEPENDS c ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_BUNDLE} -) +set(TOOL_RUN_TESTS "tools/run-tests.js") +set(TOOL_BUNDLE "tools/bundle.js") + +set(DIST_DIR "${PROJECT_BINARY_DIR}/dist") +set(GEN_DIR "${PROJECT_BINARY_DIR}/gen") -add_custom_target(dist DEPENDS ${BUNDLE_SRC} ${BUNDLE_HEADER}) file(MAKE_DIRECTORY ${DIST_DIR}) +file(MAKE_DIRECTORY ${GEN_DIR}) + +function(bundle_header) + cmake_parse_arguments(BUNDLE "" "OUTPUT;EXTERNAL_CONFIG" "" ${ARGN}) + set(CONFIG_EXTERNAL_DIR "config/external/${BUNDLE_EXTERNAL_CONFIG}") + file(GLOB SOURCES_CONFIG_EXTERNAL "${CONFIG_EXTERNAL_DIR}/*.h") + add_custom_command( + OUTPUT ${BUNDLE_OUTPUT} + COMMAND node ${TOOL_BUNDLE} + -I${CONFIG_EXTERNAL_DIR} + ${SOURCES_INCLUDE} + > ${BUNDLE_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${TOOL_BUNDLE} ${SOURCES_CONFIG_EXTERNAL} ${SOURCES_INCLUDE} + ) +endfunction() + +function(bundle_source) + cmake_parse_arguments(BUNDLE "" "OUTPUT;EXTERNAL_CONFIG" "" ${ARGN}) + set(CONFIG_EXTERNAL_DIR "config/external/${BUNDLE_EXTERNAL_CONFIG}") + file(GLOB SOURCES_CONFIG_EXTERNAL "${CONFIG_EXTERNAL_DIR}/*.h") + add_custom_command( + OUTPUT ${BUNDLE_OUTPUT} + COMMAND node ${TOOL_BUNDLE} --strip-guards + -I${CONFIG_EXTERNAL_DIR} -Iconfig/internal/bundle -Iinclude -Isrc + ${SOURCES_INCLUDE} ${SOURCES_SRC_C} + > ${BUNDLE_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${TOOL_BUNDLE} + ${SOURCES_CONFIG_EXTERNAL} ${SOURCES_CONFIG_INTERNAL_BUNDLE} + ${SOURCES_INCLUDE} ${SOURCES_SRC} + ) +endfunction() + +set(BUNDLE_DIST_TARGET "dist") +set(BUNDLE_DIST_HEADER "${DIST_DIR}/${LIB_NAME}.h") +set(BUNDLE_DIST_SOURCE "${DIST_DIR}/${LIB_NAME}.c") +bundle_header(OUTPUT ${BUNDLE_DIST_HEADER} EXTERNAL_CONFIG static) +bundle_source(OUTPUT ${BUNDLE_DIST_SOURCE} EXTERNAL_CONFIG static) +set_source_files_properties( + ${BUNDLE_DIST_HEADER} ${BUNDLE_DIST_SOURCE} + PROPERTIES GENERATED TRUE +) +add_custom_target( + ${BUNDLE_DIST_TARGET} + DEPENDS ${BUNDLE_DIST_SOURCE} ${BUNDLE_DIST_HEADER} + SOURCES ${SOURCES_CONFIG_EXTERNAL_STATIC} ${SOURCES_CONFIG_INTERNAL_BUNDLE} + ${SOURCES_INCLUDE} ${SOURCES_SRC} ${SOURCES_DOC} +) add_custom_command( - TARGET dist POST_BUILD + TARGET ${BUNDLE_DIST_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SOURCES_DOC} ${DIST_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${SOURCES_DOC} ) -set(DLL_TARGET "${HEADER_NAME}.dll") -add_library(${DLL_TARGET} SHARED ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_REGULAR}) -target_include_directories(${DLL_TARGET} PUBLIC include src/regular) -if(MSVC) - target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) -else() - target_compile_options(${DLL_TARGET} PUBLIC -fvisibility=hidden) - target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") -endif() -set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_NAME}) +set(DLL_TARGET "${LIB_NAME}.dll") +add_library( + ${DLL_TARGET} SHARED + ${SOURCES_CONFIG_EXTERNAL_DLLEXPORT} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${SOURCES_INCLUDE} ${SOURCES_SRC} +) +target_include_directories( + ${DLL_TARGET} PUBLIC + config/external/dllexport config/internal/default include src +) +set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_TARGET}) -set(BUNDLE_DLL_TARGET "${BUNDLE_DLL_NAME}.dll") -add_library(${BUNDLE_DLL_TARGET} SHARED ${BUNDLE_HEADER} ${BUNDLE_SRC}) -if(MSVC) - target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) -else() - target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") -endif() -set_target_properties(${BUNDLE_DLL_TARGET} PROPERTIES OUTPUT_NAME ${BUNDLE_DLL_NAME}) +set(BUNDLE_DLL_TARGET "${LIB_NAME}-bundle.dll") +set(BUNDLE_DLL_SOURCE "${GEN_DIR}/${LIB_NAME}-bundle-dll.c") +bundle_source(OUTPUT ${BUNDLE_DLL_SOURCE} EXTERNAL_CONFIG dllexport) +set_source_files_properties(${BUNDLE_DLL_SOURCE} PROPERTIES GENERATED TRUE) +add_library( + ${BUNDLE_DLL_TARGET} SHARED + ${SOURCES_CONFIG_EXTERNAL_DLLEXPORT} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${BUNDLE_DLL_SOURCE} +) +set_target_properties( + ${BUNDLE_DLL_TARGET} + PROPERTIES OUTPUT_NAME "${LIB_NAME}-bundle" +) + +set(TESTING_LIB_TARGET "${LIB_NAME}-testing.lib") +add_library( + ${TESTING_LIB_TARGET} STATIC + ${SOURCES_CONFIG_EXTERNAL_STATIC} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${SOURCES_INCLUDE} ${SOURCES_SRC} ${SOURCES_TEST_SHARED} +) +target_include_directories( + ${TESTING_LIB_TARGET} PUBLIC + config/external/static config/internal/default include src +) +set_target_properties( + ${TESTING_LIB_TARGET} PROPERTIES + OUTPUT_NAME "${LIB_NAME}-testing" +) foreach(TEST_SOURCE ${SOURCES_TEST}) get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) - add_executable(${TEST_NAME} ${TEST_SOURCE} ${SOURCES_SRC} ${SOURCES_SRC_REGULAR} ${SOURCES_TEST_SHARED}) + add_executable(${TEST_NAME} ${TEST_SOURCE}) + target_include_directories( + ${TEST_NAME} PUBLIC + config/external/static config/internal/default include src test/shared + ) + target_link_libraries(${TEST_NAME} ${TESTING_LIB_TARGET}) set_target_properties(${TEST_NAME} PROPERTIES FOLDER Tests) - target_include_directories(${TEST_NAME} PUBLIC include src src/regular test/shared) list(APPEND TEST_TARGETS ${TEST_NAME}) list(APPEND TEST_OUTPUTS $) -endforeach(TEST_SOURCE ${SOURCES_TEST}) +endforeach() add_custom_target( test-all - COMMAND node ${TEST_RUNNER} ${TEST_OUTPUTS} + COMMAND node ${TOOL_RUN_TESTS} ${TEST_OUTPUTS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${TEST_RUNNER} ${TEST_TARGETS} + DEPENDS ${TOOL_RUN_TESTS} ${TEST_TARGETS} ) diff --git a/config/external/dllexport/config-external.h b/config/external/dllexport/config-external.h new file mode 100644 index 0000000..039e07a --- /dev/null +++ b/config/external/dllexport/config-external.h @@ -0,0 +1,5 @@ +#ifdef _MSC_VER +#define WEPOLL_EXPORT __declspec(dllexport) +#else /* GCC/Clang */ +#define WEPOLL_EXPORT __attribute__((dllexport)) +#endif diff --git a/config/external/static/config-external.h b/config/external/static/config-external.h new file mode 100644 index 0000000..28a7045 --- /dev/null +++ b/config/external/static/config-external.h @@ -0,0 +1 @@ +#define WEPOLL_EXPORT diff --git a/config/internal/bundle/config-internal.h b/config/internal/bundle/config-internal.h new file mode 100644 index 0000000..d14707d --- /dev/null +++ b/config/internal/bundle/config-internal.h @@ -0,0 +1,2 @@ +#define WEPOLL_INTERNAL static +#define WEPOLL_INTERNAL_VAR static diff --git a/config/internal/default/config-internal.h b/config/internal/default/config-internal.h new file mode 100644 index 0000000..8d58100 --- /dev/null +++ b/config/internal/default/config-internal.h @@ -0,0 +1,2 @@ +#define WEPOLL_INTERNAL +#define WEPOLL_INTERNAL_VAR extern diff --git a/include/wepoll.h b/include/wepoll.h index c6f12e2..416e30b 100644 --- a/include/wepoll.h +++ b/include/wepoll.h @@ -1,9 +1,7 @@ #ifndef WEPOLL_H_ #define WEPOLL_H_ -#ifndef WEPOLL_EXPORT -#define WEPOLL_EXPORT -#endif +#include "config-external.h" #include diff --git a/src/afd.h b/src/afd.h index 844a09e..93dde65 100644 --- a/src/afd.h +++ b/src/afd.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_AFD_H_ #define WEPOLL_AFD_H_ -#include "internal.h" +#include "config.h" #include "nt.h" #include "win.h" diff --git a/src/api.h b/src/api.h index a4e9540..9bda65e 100644 --- a/src/api.h +++ b/src/api.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_API_H_ #define WEPOLL_API_H_ -#include "internal.h" +#include "config.h" WEPOLL_INTERNAL int epoll_global_init(void); diff --git a/src/bundle/internal.h b/src/bundle/internal.h deleted file mode 100644 index 7d36eff..0000000 --- a/src/bundle/internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef WEPOLL_INTERNAL_H_ -#define WEPOLL_INTERNAL_H_ - -#define WEPOLL_INTERNAL static -#define WEPOLL_INTERNAL_VAR static - -#endif /* WEPOLL_INTERNAL_H_ */ diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..c469e5c --- /dev/null +++ b/src/config.h @@ -0,0 +1,6 @@ +#ifndef WEPOLL_CONFIG_H_ +#define WEPOLL_CONFIG_H_ + +#include "config-internal.h" + +#endif /* WEPOLL_CONFIG_H_ */ diff --git a/src/error.h b/src/error.h index 6efc258..3d4f9d6 100644 --- a/src/error.h +++ b/src/error.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_ERROR_H_ #define WEPOLL_ERROR_H_ -#include "internal.h" +#include "config.h" #include "win.h" #define return_map_error(value) \ diff --git a/src/init.h b/src/init.h index ae7a050..1278489 100644 --- a/src/init.h +++ b/src/init.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_INIT_H_ #define WEPOLL_INIT_H_ -#include "internal.h" +#include "config.h" WEPOLL_INTERNAL int init(void); diff --git a/src/nt.h b/src/nt.h index 10a98d8..8c31882 100644 --- a/src/nt.h +++ b/src/nt.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_NT_H_ #define WEPOLL_NT_H_ -#include "internal.h" +#include "config.h" #include "win.h" WEPOLL_INTERNAL int nt_global_init(void); diff --git a/src/poll-group.h b/src/poll-group.h index 2dd100d..9aa97f8 100644 --- a/src/poll-group.h +++ b/src/poll-group.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_POLL_GROUP_H_ #define WEPOLL_POLL_GROUP_H_ -#include "internal.h" +#include "config.h" #include "win.h" typedef struct poll_group poll_group_t; diff --git a/src/port.h b/src/port.h index bedfaf3..93f45d8 100644 --- a/src/port.h +++ b/src/port.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_PORT_H_ #define WEPOLL_PORT_H_ -#include "internal.h" +#include "config.h" #include "wepoll.h" #include "win.h" diff --git a/src/queue.h b/src/queue.h index 49a603d..dc7aad9 100644 --- a/src/queue.h +++ b/src/queue.h @@ -3,7 +3,7 @@ #include -#include "internal.h" +#include "config.h" typedef struct queue_node queue_node_t; diff --git a/src/reflock.h b/src/reflock.h index c4525ca..155eb7c 100644 --- a/src/reflock.h +++ b/src/reflock.h @@ -19,7 +19,7 @@ * should use another lock to guarantee that this can't happen. */ -#include "internal.h" +#include "config.h" typedef struct reflock { volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ diff --git a/src/regular/internal.h b/src/regular/internal.h deleted file mode 100644 index 95d51b6..0000000 --- a/src/regular/internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef WEPOLL_INTERNAL_H_ -#define WEPOLL_INTERNAL_H_ - -#define WEPOLL_INTERNAL -#define WEPOLL_INTERNAL_VAR extern - -#endif /* WEPOLL_INTERNAL_H_ */ diff --git a/src/sock.h b/src/sock.h index e22f14e..f55f5f4 100644 --- a/src/sock.h +++ b/src/sock.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_SOCK_H_ #define WEPOLL_SOCK_H_ -#include "internal.h" +#include "config.h" #include "nt.h" #include "wepoll.h" #include "win.h" diff --git a/src/thread-safe-tree.h b/src/thread-safe-tree.h index 8b4235d..41f3222 100644 --- a/src/thread-safe-tree.h +++ b/src/thread-safe-tree.h @@ -3,7 +3,7 @@ #include -#include "internal.h" +#include "config.h" #include "reflock.h" #include "tree.h" #include "win.h" diff --git a/src/tree.h b/src/tree.h index 1e01257..95f42f7 100644 --- a/src/tree.h +++ b/src/tree.h @@ -4,7 +4,7 @@ #include #include -#include "internal.h" +#include "config.h" /* N.b.: the tree functions do not set errno or LastError when they fail. Each * of the API functions has at most one failure mode. It is up to the caller to diff --git a/src/ws.h b/src/ws.h index 34ce5bb..6fd1fa0 100644 --- a/src/ws.h +++ b/src/ws.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_WS_H_ #define WEPOLL_WS_H_ -#include "internal.h" +#include "config.h" #include "win.h" WEPOLL_INTERNAL int ws_global_init(void); diff --git a/test/shared/test-util.h b/test/shared/test-util.h index 4acb5c5..1859483 100644 --- a/test/shared/test-util.h +++ b/test/shared/test-util.h @@ -12,13 +12,13 @@ #ifdef _MSC_VER #define no_return __declspec(noreturn) -#else /* GCC/clang */ +#else /* GCC/Clang */ #define no_return __attribute__((noreturn)) #endif #ifdef _MSC_VER #define no_inline __declspec(noinline) -#else /* GCC/clang */ +#else /* GCC/Clang */ #define no_inline __attribute__((noinline)) #endif