diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..d8a6c655 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.15) + +project(STC + VERSION 6.0 + DESCRIPTION "A modern, user friendly, generic, type-safe and fast C99 container library." + LANGUAGES C) + +option(STC_BUILD_EXAMPLES "Build STC examples" ON) +option(STC_BUILD_TESTS "Build STC tests and enable CTest" ON) +option(STC_INSTALL_DOCS "Install docs directory" OFF) + +include(GNUInstallDirs) + +# Sources +set(STC_SOURCES + src/cregex.c + src/cspan.c + src/cstr_core.c + src/cstr_io.c + src/cstr_utf8.c + src/csview.c + src/fmt.c + src/random.c + src/stc_core.c +) + +add_library(stc ${STC_SOURCES}) +add_library(stc::stc ALIAS stc) + +target_include_directories(stc + PUBLIC + $ + $) + +target_compile_features(stc PUBLIC c_std_11) + +# Link libm when available on non-MSVC platforms +if(NOT MSVC) + include(CheckLibraryExists) + check_library_exists(m cos "" HAVE_LIB_M) + if(HAVE_LIB_M) + target_link_libraries(stc PUBLIC m) + endif() +endif() + +set_target_properties(stc PROPERTIES + OUTPUT_NAME stc + C_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN YES) + +# Install headers (entire include tree) +install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Install library and export targets +install(TARGETS stc + EXPORT stcTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Package config generation +include(CMakePackageConfigHelpers) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/stcConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion) + +configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/cmake/stcConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/stcConfig.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/stc) + +install(EXPORT stcTargets + FILE stcTargets.cmake + NAMESPACE stc:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/stc) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/stcConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/stcConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/stc) + +# Optionally install docs +if(STC_INSTALL_DOCS) + install(DIRECTORY docs/ DESTINATION ${CMAKE_INSTALL_DOCDIR} OPTIONAL) +endif() + +# Examples +if(STC_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +# Tests +if(STC_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..c28ca10f --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,33 @@ +# Build all example programs found in the listed subdirectories + +set(_EXAMPLE_DIRS + algorithms + bitsets + coroutines + hashmaps + linkedlists + mixed + priorityqueues + queues + regularexpressions + smartpointers + sortedmaps + spans + strings + vectors) + +foreach(_dir IN LISTS _EXAMPLE_DIRS) + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_dir}") + file(GLOB _c_files CONFIGURE_DEPENDS "${_dir}/*.c") + foreach(_src IN LISTS _c_files) + get_filename_component(_name_we "${_src}" NAME_WE) + set(_exe "ex_${_dir}_${_name_we}") + add_executable(${_exe} "${_src}") + target_link_libraries(${_exe} PRIVATE stc::stc) + # Link libm if stc didn't already (safe to repeat) + if(NOT MSVC) + target_link_libraries(${_exe} PRIVATE m) + endif() + endforeach() + endif() +endforeach() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..8ead5c6c --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,30 @@ +# Build test executables and register CTest tests + +include(GNUInstallDirs) + +file(GLOB _TEST_SOURCES CONFIGURE_DEPENDS "*_test.c") + +set(_COMMON_SRC main.c) + +set(_TEST_TARGETS) + +foreach(_suite_src IN LISTS _TEST_SOURCES) + get_filename_component(_suite_name "${_suite_src}" NAME_WE) + add_executable(${_suite_name} ${_suite_src} ${_COMMON_SRC}) + target_compile_definitions(${_suite_name} PRIVATE _GNU_SOURCE) + target_link_libraries(${_suite_name} PRIVATE stc::stc) + if(NOT MSVC) + target_link_libraries(${_suite_name} PRIVATE m) + endif() + # Register test using the full path to the built executable to avoid PATH lookup issues + add_test(NAME ${_suite_name} COMMAND $) + list(APPEND _TEST_TARGETS ${_suite_name}) +endforeach() + +# Convenience aggregate target to build all tests in one go +if(_TEST_TARGETS) + add_custom_target(tests ALL DEPENDS ${_TEST_TARGETS}) +endif() + +# Install ctest.h like Meson does +install(FILES ctest.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/stc)