diff --git a/CMakeLists.txt b/CMakeLists.txt index 6be50b9..f8d966b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,59 +1,48 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) + project( cpp_request + VERSION 0.9.0 DESCRIPTION "A lightweight synchronous C++17 HTTP/1.1 client built on native sockets" - VERSION 0.1.0 - LANGUAGES CXX C + LANGUAGES CXX ) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") -option(CPP_REQUEST_BUILD_BENCHMARKS "Build cpp_request benchmarks" OFF) +include(options) +cpp_request_setup_options() -include(CTest) -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) -include(cmake/modules/output.cmake) -include(cmake/modules/warning.cmake) -include(cmake/modules/sanitizing.cmake) -include(cmake/modules/optimizing.cmake) +include(project-settings) +cpp_request_setup_project() add_subdirectory(src) -if(BUILD_TESTING) + +if(CPP_REQUEST_BUILD_TESTS) + include(testing) add_subdirectory(tests) endif() + if(CPP_REQUEST_BUILD_BENCHMARKS) + include(benchmarking) add_subdirectory(benchmarks) endif() -add_subdirectory(examples) -set(CPP_REQUEST_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/cpp_request") - -configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpp_requestConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfig.cmake - INSTALL_DESTINATION ${CPP_REQUEST_INSTALL_CMAKEDIR} -) +if(CPP_REQUEST_BUILD_EXAMPLES) + include(examples) + add_subdirectory(examples) +endif() -write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfigVersion.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMinorVersion -) +if(CPP_REQUEST_ENABLE_INSTALL) + include(install) + cpp_request_configure_install() +endif() -install( - EXPORT cpp_requestTargets - FILE cpp_requestTargets.cmake - NAMESPACE cpp_request:: - DESTINATION ${CPP_REQUEST_INSTALL_CMAKEDIR} -) +if(PROJECT_IS_TOP_LEVEL AND CPP_REQUEST_ENABLE_CLANG_FORMAT) + include("${PROJECT_SOURCE_DIR}/cmake/tools/clang-format.cmake") + cpp_request_add_clang_format_targets() +endif() -install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfigVersion.cmake - DESTINATION ${CPP_REQUEST_INSTALL_CMAKEDIR} -) +if(PROJECT_IS_TOP_LEVEL AND CPP_REQUEST_ENABLE_DOXYGEN) + include("${PROJECT_SOURCE_DIR}/cmake/tools/doxygen.cmake") + cpp_request_add_doxygen_target(cpp_request_docs) +endif() diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 9125d2c..a6d9e0c 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,26 +1,3 @@ -include(${PROJECT_SOURCE_DIR}/cmake/packages/google-benchmark.cmake) -find_package(Threads REQUIRED) - -function(cpp_request_add_benchmark target source) - add_executable(${target} ${source}) - target_include_directories(${target} - PRIVATE - ${PROJECT_SOURCE_DIR}/src - ${CMAKE_CURRENT_SOURCE_DIR} - ) - target_link_libraries(${target} - PRIVATE - cpp_request::internal - benchmark::benchmark_main - Threads::Threads - ) - target_compile_features(${target} PRIVATE cxx_std_17) - - if(WIN32) - target_link_libraries(${target} PRIVATE ws2_32) - endif() -endfunction() - cpp_request_add_benchmark( cpp_request_bench_request_serializer request_serializer_benchmark.cpp diff --git a/cmake/README.md b/cmake/README.md new file mode 100644 index 0000000..93afd9d --- /dev/null +++ b/cmake/README.md @@ -0,0 +1,27 @@ +# CMake structure + +`cpp_request` keeps the root `CMakeLists.txt` as an orchestrator. Project behavior is split by responsibility: + +- `modules/` — project options, target policy, tests, benchmarks, examples, and install/export rules. +- `packages/` — development-only third-party discovery with `find_package()` first and `FetchContent` fallback. +- `tools/` — optional developer tooling such as clang-format, clang-tidy, and Doxygen. +- `templates/` — inputs for files generated into the build/install tree. + +Normal CMake configure must not modify files in the source tree. In particular, `vcpkg.json` is source-controlled input and is not generated by CMake. + +## Main options + +- `CPP_REQUEST_BUILD_TESTS` +- `CPP_REQUEST_BUILD_BENCHMARKS` +- `CPP_REQUEST_BUILD_EXAMPLES` +- `CPP_REQUEST_ENABLE_INSTALL` +- `CPP_REQUEST_ENABLE_WARNINGS` +- `CPP_REQUEST_WARNINGS_AS_ERRORS` +- `CPP_REQUEST_ENABLE_SANITIZERS` +- `CPP_REQUEST_ENABLE_IPO` +- `CPP_REQUEST_ENABLE_NATIVE_OPTIMIZATION` +- `CPP_REQUEST_ENABLE_CLANG_TIDY` +- `CPP_REQUEST_ENABLE_CLANG_FORMAT` +- `CPP_REQUEST_ENABLE_DOXYGEN` + +Tests, examples, and install rules default on only when `cpp_request` is the top-level project. Benchmarks and developer tools are opt-in. For compatibility with conventional CMake callers, an explicitly supplied `BUILD_TESTING` value is used as the default for `CPP_REQUEST_BUILD_TESTS`. diff --git a/cmake/modules/benchmarking.cmake b/cmake/modules/benchmarking.cmake index 0309414..dda462c 100644 --- a/cmake/modules/benchmarking.cmake +++ b/cmake/modules/benchmarking.cmake @@ -1,10 +1,28 @@ -include(${CMAKE_SOURCE_DIR}/cmake/packages/google-benchmark.cmake) - -function(add_benchmark_target name) - add_executable(${name} ${ARGN}) - target_link_libraries(${name} - PRIVATE +include_guard(GLOBAL) + +include("${PROJECT_SOURCE_DIR}/cmake/packages/google-benchmark.cmake") +find_package(Threads REQUIRED) + +function(cpp_request_add_benchmark target source) + add_executable(${target} ${source}) + + target_include_directories(${target} + PRIVATE + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/benchmarks + ) + + target_link_libraries(${target} + PRIVATE + cpp_request::cpp_request benchmark::benchmark_main - ${PROJECT_NAME}::internal + Threads::Threads ) -endfunction() \ No newline at end of file + + if(WIN32) + target_link_libraries(${target} PRIVATE ws2_32) + endif() + + target_compile_features(${target} PRIVATE cxx_std_17) + cpp_request_configure_target(${target}) +endfunction() diff --git a/cmake/modules/examples.cmake b/cmake/modules/examples.cmake new file mode 100644 index 0000000..951dfcf --- /dev/null +++ b/cmake/modules/examples.cmake @@ -0,0 +1,8 @@ +include_guard(GLOBAL) + +function(cpp_request_add_example target source) + add_executable(${target} ${source}) + target_link_libraries(${target} PRIVATE cpp_request::cpp_request) + target_compile_features(${target} PRIVATE cxx_std_17) + cpp_request_configure_target(${target}) +endfunction() diff --git a/cmake/modules/install.cmake b/cmake/modules/install.cmake new file mode 100644 index 0000000..76bd1f0 --- /dev/null +++ b/cmake/modules/install.cmake @@ -0,0 +1,51 @@ +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) + +function(cpp_request_configure_install) + set( + CPP_REQUEST_INSTALL_CMAKEDIR + "${CMAKE_INSTALL_LIBDIR}/cmake/cpp_request" + ) + + configure_package_config_file( + "${PROJECT_SOURCE_DIR}/cmake/templates/cpp_requestConfig.cmake.in" + "${PROJECT_BINARY_DIR}/cpp_requestConfig.cmake" + INSTALL_DESTINATION "${CPP_REQUEST_INSTALL_CMAKEDIR}" + ) + + write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/cpp_requestConfigVersion.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMinorVersion + ) + + install( + TARGETS cpp_request + EXPORT cpp_requestTargets + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + + install( + DIRECTORY "${PROJECT_SOURCE_DIR}/include/cpp_request" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + FILES_MATCHING PATTERN "*.hpp" + ) + + install( + EXPORT cpp_requestTargets + FILE cpp_requestTargets.cmake + NAMESPACE cpp_request:: + DESTINATION "${CPP_REQUEST_INSTALL_CMAKEDIR}" + ) + + install( + FILES + "${PROJECT_BINARY_DIR}/cpp_requestConfig.cmake" + "${PROJECT_BINARY_DIR}/cpp_requestConfigVersion.cmake" + DESTINATION "${CPP_REQUEST_INSTALL_CMAKEDIR}" + ) +endfunction() diff --git a/cmake/modules/optimizations.cmake b/cmake/modules/optimizations.cmake new file mode 100644 index 0000000..5c347b1 --- /dev/null +++ b/cmake/modules/optimizations.cmake @@ -0,0 +1,30 @@ +include_guard(GLOBAL) + +function(cpp_request_apply_optimizations target) + if(CPP_REQUEST_ENABLE_NATIVE_OPTIMIZATION) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + target_compile_options(${target} + PRIVATE + $<$:-march=native> + $<$:-mtune=native> + ) + else() + message(WARNING + "CPP_REQUEST_ENABLE_NATIVE_OPTIMIZATION currently supports Clang and GCC only" + ) + endif() + endif() + + if(CPP_REQUEST_ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported(RESULT _cpp_request_ipo_supported OUTPUT _cpp_request_ipo_error) + if(_cpp_request_ipo_supported) + set_property( + TARGET ${target} + PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE + ) + else() + message(WARNING "IPO is unavailable: ${_cpp_request_ipo_error}") + endif() + endif() +endfunction() diff --git a/cmake/modules/optimizing.cmake b/cmake/modules/optimizing.cmake deleted file mode 100644 index 2d41cf5..0000000 --- a/cmake/modules/optimizing.cmake +++ /dev/null @@ -1,56 +0,0 @@ -if(ENABLE_RELEASE_OPTIMIZATION) - include(CheckIPOSupported) - check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR) -endif() - -function(add_release_optimizations_target target) - if(ENABLE_RELEASE_OPTIMIZATION) - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") - target_compile_options(${target} - PRIVATE - $<$:-O3> - $<$:-ffunction-sections> - $<$:-fdata-sections> - ) - if(ENABLE_NATIVE_OPTIMIZATION) - target_compile_options(${target} - PRIVATE - $<$:-march=native> - $<$:-mtune=native> - ) - endif() - if(WIN32) - target_link_options(${target} - PRIVATE - $<$:LINKER:/OPT:REF> - $<$:LINKER:/OPT:ICF> - ) - else() - target_link_options(${target} - PRIVATE - $<$:LINKER:--gc-sections> - ) - endif() - elseif(MSVC) - target_compile_options(${target} - PRIVATE - $<$:/O2> - $<$:/GL> - $<$:/arch:AVX2> - ) - target_link_options(${target} - PRIVATE - $<$:/LTCG> - ) - endif() - if(IPO_SUPPORTED AND ENABLE_IPO) - set_property( - TARGET - ${target} - PROPERTY - INTERPROCEDURAL_OPTIMIZATION_RELEASE - TRUE - ) - endif() - endif() -endfunction() \ No newline at end of file diff --git a/cmake/modules/options.cmake b/cmake/modules/options.cmake new file mode 100644 index 0000000..fd9bc17 --- /dev/null +++ b/cmake/modules/options.cmake @@ -0,0 +1,44 @@ +include_guard(GLOBAL) + +function(cpp_request_setup_options) + set(_cpp_request_top_level_default OFF) + if(PROJECT_IS_TOP_LEVEL) + set(_cpp_request_top_level_default ON) + endif() + + set(_cpp_request_test_default ${_cpp_request_top_level_default}) + if(DEFINED BUILD_TESTING) + set(_cpp_request_test_default ${BUILD_TESTING}) + endif() + + option( + CPP_REQUEST_BUILD_TESTS + "Build cpp_request tests" + ${_cpp_request_test_default} + ) + option( + CPP_REQUEST_BUILD_BENCHMARKS + "Build cpp_request benchmarks" + OFF + ) + option( + CPP_REQUEST_BUILD_EXAMPLES + "Build cpp_request examples" + ${_cpp_request_top_level_default} + ) + option( + CPP_REQUEST_ENABLE_INSTALL + "Enable cpp_request install and package export rules" + ${_cpp_request_top_level_default} + ) + + option(CPP_REQUEST_ENABLE_WARNINGS "Enable compiler warnings" ON) + option(CPP_REQUEST_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) + option(CPP_REQUEST_ENABLE_SANITIZERS "Enable AddressSanitizer and UndefinedBehaviorSanitizer" OFF) + option(CPP_REQUEST_ENABLE_IPO "Enable interprocedural optimization for Release builds" OFF) + option(CPP_REQUEST_ENABLE_NATIVE_OPTIMIZATION "Enable host-specific optimization for local Release builds" OFF) + + option(CPP_REQUEST_ENABLE_CLANG_TIDY "Enable clang-tidy for cpp_request targets" OFF) + option(CPP_REQUEST_ENABLE_CLANG_FORMAT "Add clang-format helper targets" OFF) + option(CPP_REQUEST_ENABLE_DOXYGEN "Add the Doxygen documentation target" OFF) +endfunction() diff --git a/cmake/modules/output.cmake b/cmake/modules/output.cmake deleted file mode 100644 index cd24611..0000000 --- a/cmake/modules/output.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(PROJECT_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/out") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/bin") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/lib") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/lib") -set(DOXYGEN_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/docs") \ No newline at end of file diff --git a/cmake/modules/project-settings.cmake b/cmake/modules/project-settings.cmake new file mode 100644 index 0000000..0364fe2 --- /dev/null +++ b/cmake/modules/project-settings.cmake @@ -0,0 +1,34 @@ +include_guard(GLOBAL) + +include(GNUInstallDirs) +include(warnings) +include(sanitizers) +include(optimizations) + +if(CPP_REQUEST_ENABLE_CLANG_TIDY) + include("${PROJECT_SOURCE_DIR}/cmake/tools/clang-tidy.cmake") +endif() + +function(cpp_request_setup_project) + if(PROJECT_IS_TOP_LEVEL AND NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS) + set( + CMAKE_EXPORT_COMPILE_COMMANDS + ON + CACHE BOOL "Export compile_commands.json" FORCE + ) + endif() +endfunction() + +function(cpp_request_configure_target target) + if(NOT TARGET ${target}) + message(FATAL_ERROR "cpp_request_configure_target: unknown target '${target}'") + endif() + + cpp_request_apply_warnings(${target}) + cpp_request_apply_sanitizers(${target}) + cpp_request_apply_optimizations(${target}) + + if(CPP_REQUEST_ENABLE_CLANG_TIDY) + cpp_request_apply_clang_tidy(${target}) + endif() +endfunction() diff --git a/cmake/modules/sanitizers.cmake b/cmake/modules/sanitizers.cmake new file mode 100644 index 0000000..26774d7 --- /dev/null +++ b/cmake/modules/sanitizers.cmake @@ -0,0 +1,25 @@ +include_guard(GLOBAL) + +function(cpp_request_apply_sanitizers target) + if(NOT CPP_REQUEST_ENABLE_SANITIZERS) + return() + endif() + + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + target_compile_options(${target} + PRIVATE + -fsanitize=address + -fsanitize=undefined + -fno-omit-frame-pointer + ) + target_link_options(${target} + PRIVATE + -fsanitize=address + -fsanitize=undefined + ) + else() + message(WARNING + "CPP_REQUEST_ENABLE_SANITIZERS is enabled, but the current compiler is unsupported" + ) + endif() +endfunction() diff --git a/cmake/modules/sanitizing.cmake b/cmake/modules/sanitizing.cmake deleted file mode 100644 index aae5a1e..0000000 --- a/cmake/modules/sanitizing.cmake +++ /dev/null @@ -1,15 +0,0 @@ -function(add_sanitize_target target) - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") - target_compile_options(${target} - PRIVATE - -fsanitize=address - -fsanitize=undefined - -fno-omit-frame-pointer - ) - target_link_options(${target} - PRIVATE - -fsanitize=address - -fsanitize=undefined - ) - endif() -endfunction() \ No newline at end of file diff --git a/cmake/modules/testing.cmake b/cmake/modules/testing.cmake index 835a5f1..9580956 100644 --- a/cmake/modules/testing.cmake +++ b/cmake/modules/testing.cmake @@ -1,11 +1,29 @@ -include("${CMAKE_SOURCE_DIR}/cmake/packages/google-test.cmake") +include_guard(GLOBAL) -function(add_test_target name) - add_executable(${name} ${ARGN}) - target_link_libraries(${name} - PRIVATE +enable_testing() +include("${PROJECT_SOURCE_DIR}/cmake/packages/google-test.cmake") +find_package(Threads REQUIRED) + +function(cpp_request_add_test target) + add_executable(${target} ${ARGN}) + + target_include_directories(${target} + PRIVATE + ${PROJECT_SOURCE_DIR}/src + ) + + target_link_libraries(${target} + PRIVATE + cpp_request::cpp_request GTest::gtest_main - ${PROJECT_NAME}::internal + Threads::Threads ) - gtest_discover_tests(${name}) -endfunction() \ No newline at end of file + + if(WIN32) + target_link_libraries(${target} PRIVATE ws2_32) + endif() + + target_compile_features(${target} PRIVATE cxx_std_17) + cpp_request_configure_target(${target}) + gtest_discover_tests(${target}) +endfunction() diff --git a/cmake/modules/warning.cmake b/cmake/modules/warning.cmake deleted file mode 100644 index 6c8e1ce..0000000 --- a/cmake/modules/warning.cmake +++ /dev/null @@ -1,18 +0,0 @@ -function(add_warning_target target) - if(MSVC) - target_compile_options(${target} - PRIVATE - /W4 - /permissive- - ) - else() - target_compile_options(${target} - PRIVATE - -Wall - -Wextra - -Wpedantic - -Wconversion - -Wshadow - ) - endif() -endfunction() \ No newline at end of file diff --git a/cmake/modules/warnings.cmake b/cmake/modules/warnings.cmake new file mode 100644 index 0000000..c9ce7c8 --- /dev/null +++ b/cmake/modules/warnings.cmake @@ -0,0 +1,30 @@ +include_guard(GLOBAL) + +function(cpp_request_apply_warnings target) + if(NOT CPP_REQUEST_ENABLE_WARNINGS) + return() + endif() + + if(MSVC) + target_compile_options(${target} + PRIVATE + /W4 + /permissive- + ) + if(CPP_REQUEST_WARNINGS_AS_ERRORS) + target_compile_options(${target} PRIVATE /WX) + endif() + else() + target_compile_options(${target} + PRIVATE + -Wall + -Wextra + -Wpedantic + -Wconversion + -Wshadow + ) + if(CPP_REQUEST_WARNINGS_AS_ERRORS) + target_compile_options(${target} PRIVATE -Werror) + endif() + endif() +endfunction() diff --git a/cmake/packages/google-test.cmake b/cmake/packages/google-test.cmake index d1ea176..177757a 100644 --- a/cmake/packages/google-test.cmake +++ b/cmake/packages/google-test.cmake @@ -1,4 +1,5 @@ -enable_testing() +include_guard(GLOBAL) + find_package(GTest CONFIG QUIET) if(NOT GTest_FOUND) @@ -7,10 +8,11 @@ if(NOT GTest_FOUND) googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.18.0 + GIT_SHALLOW TRUE ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) endif() -include(GoogleTest) \ No newline at end of file +include(GoogleTest) diff --git a/cmake/templates/CMakeLists.txt b/cmake/templates/CMakeLists.txt deleted file mode 100644 index a180188..0000000 --- a/cmake/templates/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(${CMAKE_SOURCE_DIR}/cmake/tools/vcpkg.cmake) \ No newline at end of file diff --git a/cmake/templates/Doxyfile.in b/cmake/templates/Doxyfile.in new file mode 100644 index 0000000..3c294ae --- /dev/null +++ b/cmake/templates/Doxyfile.in @@ -0,0 +1,11 @@ +PROJECT_NAME = "@PROJECT_NAME@" +PROJECT_NUMBER = "@PROJECT_VERSION@" +OUTPUT_DIRECTORY = "@PROJECT_BINARY_DIR@/docs" +INPUT = "@PROJECT_SOURCE_DIR@/include" +RECURSIVE = YES +FILE_PATTERNS = *.h *.hpp +EXTRACT_ALL = YES +GENERATE_HTML = YES +GENERATE_LATEX = NO +QUIET = YES +WARN_IF_UNDOCUMENTED = NO diff --git a/cmake/cpp_requestConfig.cmake.in b/cmake/templates/cpp_requestConfig.cmake.in similarity index 100% rename from cmake/cpp_requestConfig.cmake.in rename to cmake/templates/cpp_requestConfig.cmake.in diff --git a/cmake/templates/vcpkg.json.in b/cmake/templates/vcpkg.json.in deleted file mode 100644 index 12f6da4..0000000 --- a/cmake/templates/vcpkg.json.in +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@PROJECT_NAME_SLUG@", - "version": "@PROJECT_VERSION@", - "description": "@PROJECT_DESCRIPTION@", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/cmake/tools/clang-format.cmake b/cmake/tools/clang-format.cmake index 46dffda..7cfc5ae 100644 --- a/cmake/tools/clang-format.cmake +++ b/cmake/tools/clang-format.cmake @@ -1,19 +1,46 @@ -find_program(CLANG_FORMAT_EXE NAMES clang-format) +include_guard(GLOBAL) -function(add_clang_format_target target) - if(CLANG_FORMAT_EXE) - get_target_property(TARGET_SOURCES ${target} SOURCES) +find_program(CLANG_FORMAT_EXE NAMES clang-format) - add_custom_target(format - COMMAND ${CLANG_FORMAT_EXE} -i -style=file ${TARGET_SOURCES} - COMMENT "Formatting ${target} source files with clang-format" +function(cpp_request_add_clang_format_targets) + if(NOT CLANG_FORMAT_EXE) + message(WARNING + "CPP_REQUEST_ENABLE_CLANG_FORMAT is ON, but clang-format was not found" ) + return() + endif() - add_custom_target(format-check - COMMAND ${CLANG_FORMAT_EXE} --dry-run --Werror -style=file ${TARGET_SOURCES} - COMMENT "Checking ${target} source formatting" - ) - else() - message(WARNING "clang format not found! Target '${target}' will not be created.") + file(GLOB_RECURSE _cpp_request_format_sources + CONFIGURE_DEPENDS + LIST_DIRECTORIES FALSE + "${PROJECT_SOURCE_DIR}/include/*.h" + "${PROJECT_SOURCE_DIR}/include/*.hpp" + "${PROJECT_SOURCE_DIR}/src/*.c" + "${PROJECT_SOURCE_DIR}/src/*.cc" + "${PROJECT_SOURCE_DIR}/src/*.cpp" + "${PROJECT_SOURCE_DIR}/src/*.h" + "${PROJECT_SOURCE_DIR}/src/*.hpp" + "${PROJECT_SOURCE_DIR}/tests/*.cpp" + "${PROJECT_SOURCE_DIR}/tests/*.hpp" + "${PROJECT_SOURCE_DIR}/benchmarks/*.cpp" + "${PROJECT_SOURCE_DIR}/benchmarks/*.hpp" + "${PROJECT_SOURCE_DIR}/examples/*.cpp" + "${PROJECT_SOURCE_DIR}/examples/*.hpp" + ) + + if(NOT _cpp_request_format_sources) + return() endif() -endfunction() \ No newline at end of file + + add_custom_target(cpp_request_format + COMMAND "${CLANG_FORMAT_EXE}" -i -style=file ${_cpp_request_format_sources} + COMMENT "Formatting cpp_request C++ sources" + VERBATIM + ) + + add_custom_target(cpp_request_format_check + COMMAND "${CLANG_FORMAT_EXE}" --dry-run --Werror -style=file ${_cpp_request_format_sources} + COMMENT "Checking cpp_request C++ source formatting" + VERBATIM + ) +endfunction() diff --git a/cmake/tools/clang-tidy.cmake b/cmake/tools/clang-tidy.cmake index 6fc3404..68ba2a4 100644 --- a/cmake/tools/clang-tidy.cmake +++ b/cmake/tools/clang-tidy.cmake @@ -1,9 +1,16 @@ +include_guard(GLOBAL) + find_program(CLANG_TIDY_EXE NAMES clang-tidy) -function(add_clang_tidy_target target) +function(cpp_request_apply_clang_tidy target) if(CLANG_TIDY_EXE) - set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") + set_target_properties( + ${target} + PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE}" + ) else() - message(WARNING "clang tidy not found! Target '${target}' will not be created.") + message(WARNING + "CPP_REQUEST_ENABLE_CLANG_TIDY is ON, but clang-tidy was not found" + ) endif() -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/tools/doxygen.cmake b/cmake/tools/doxygen.cmake index d671ada..7581478 100644 --- a/cmake/tools/doxygen.cmake +++ b/cmake/tools/doxygen.cmake @@ -1,28 +1,26 @@ -find_program(DOXYGEN_EXE NAMES DOXYGEN) +include_guard(GLOBAL) -function(add_doxygen_target target) - if(DOXYGEN_EXE) - set(DOXYFILE_IN "${CMAKE_SOURCE_DIR}/cmake/templates/Doxyfile.in") - set(DOXYFILE_OUT "${CMAKE_SOURCE_DIR}/Doxyfile") +find_package(Doxygen QUIET) - if(EXISTS ${DOXYFILE_IN}) - configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) - - add_custom_target(${target} - COMMAND ${DOXYGEN_EXE} ${DOXYGEN_OUT} - WORKING_DIRECTORY ${DOXYGEN_OUTPUT_DIRECTORY} - COMMENT "Generating API documentation with Doxygen..." - VERBATIM - ) - else() - add_custom_target(${target} - COMMAND ${DOXYGEN_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Generating API documentation with Doxygen..." - VERBATIM - ) - endif() - else() - message(WARNING "Doxygen not found! Target '${target}' will not be created.") +function(cpp_request_add_doxygen_target target) + if(NOT Doxygen_FOUND) + message(WARNING + "CPP_REQUEST_ENABLE_DOXYGEN is ON, but Doxygen was not found" + ) + return() endif() + + set(_cpp_request_doxyfile "${PROJECT_BINARY_DIR}/Doxyfile") + configure_file( + "${PROJECT_SOURCE_DIR}/cmake/templates/Doxyfile.in" + "${_cpp_request_doxyfile}" + @ONLY + ) + + add_custom_target(${target} + COMMAND Doxygen::doxygen "${_cpp_request_doxyfile}" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Generating cpp_request API documentation" + VERBATIM + ) endfunction() diff --git a/cmake/tools/vcpkg.cmake b/cmake/tools/vcpkg.cmake deleted file mode 100644 index 69b7f23..0000000 --- a/cmake/tools/vcpkg.cmake +++ /dev/null @@ -1,10 +0,0 @@ -string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_SLUG) -string(REGEX REPLACE "[ _]" "-" PROJECT_NAME_SLUG "${PROJECT_NAME_SLUG}") -string(REGEX REPLACE "-+" "-" PROJECT_NAME_SLUG "${PROJECT_NAME_SLUG}") -string(REGEX REPLACE "^-*(.*[^-])-*$" "\\1" PROJECT_NAME_SLUG "${PROJECT_NAME_SLUG}") - -configure_file( - "${CMAKE_SOURCE_DIR}/cmake/templates/vcpkg.json.in" - "${CMAKE_SOURCE_DIR}/vcpkg.json" - @ONLY -) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ee4ba0..f8800f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(internal +add_library(cpp_request ${CMAKE_CURRENT_SOURCE_DIR}/core/client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/core/headers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/core/url.cpp @@ -15,15 +15,15 @@ add_library(internal ${CMAKE_CURRENT_SOURCE_DIR}/net/tcp_connection.cpp ) -set_target_properties(internal PROPERTIES +set_target_properties(cpp_request PROPERTIES EXPORT_NAME cpp_request OUTPUT_NAME cpp_request ) -add_library(${PROJECT_NAME}::internal ALIAS internal) -add_library(${PROJECT_NAME}::cpp_request ALIAS internal) +add_library(cpp_request::cpp_request ALIAS cpp_request) +add_library(cpp_request::internal ALIAS cpp_request) -target_include_directories(internal +target_include_directories(cpp_request PUBLIC $ $ @@ -31,23 +31,10 @@ target_include_directories(internal ${PROJECT_SOURCE_DIR}/src ) -target_compile_features(internal PUBLIC cxx_std_17) +target_compile_features(cpp_request PUBLIC cxx_std_17) if(WIN32) - target_link_libraries(internal PRIVATE ws2_32) + target_link_libraries(cpp_request PRIVATE ws2_32) endif() -install( - TARGETS internal - EXPORT cpp_requestTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) - -install( - DIRECTORY ${PROJECT_SOURCE_DIR}/include/cpp_request - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING PATTERN "*.hpp" -) +cpp_request_configure_target(cpp_request) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 167b55a..edbe9d8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,4 @@ -include(${PROJECT_SOURCE_DIR}/cmake/packages/google-test.cmake) -find_package(Threads REQUIRED) - -add_executable(cpp_request_tests +cpp_request_add_test(cpp_request_tests ${CMAKE_CURRENT_SOURCE_DIR}/result_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/url_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/headers_test.cpp @@ -22,26 +19,6 @@ add_executable(cpp_request_tests ${CMAKE_CURRENT_SOURCE_DIR}/tcp_io_test.cpp ) -target_include_directories(cpp_request_tests - PRIVATE - ${PROJECT_SOURCE_DIR}/src -) - -target_link_libraries(cpp_request_tests - PRIVATE - cpp_request::internal - GTest::gtest_main - Threads::Threads -) - -if(WIN32) - target_link_libraries(cpp_request_tests PRIVATE ws2_32) -endif() - -target_compile_features(cpp_request_tests PRIVATE cxx_std_17) - -gtest_discover_tests(cpp_request_tests) - add_test( NAME PackageConsumer.InstallAndUse COMMAND