diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a2b51e..a23429b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) project( cpp_request - DESCRIPTION "A lightweight, modern C++ HTTP/HTTPS client library designed for low-level performance and clean API ergonomics. Built from the ground up to provide a zero-heavy-dependency network solution, it features an intuitive fluent interface (builder pattern) for crafting requests, an integrated URL parser, and a cross-platform socket wrapper. Ideal for systems engineering and lightweight applications requiring direct control over network transport and memory management" + DESCRIPTION "A lightweight synchronous C++17 HTTP/1.1 client built on native sockets" VERSION 0.1.0 LANGUAGES CXX C ) @@ -12,14 +12,44 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 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) -add_subdirectory(${CMAKE_SOURCE_DIR}/src) +add_subdirectory(src) if(BUILD_TESTING) - add_subdirectory(${CMAKE_SOURCE_DIR}/tests) + add_subdirectory(tests) endif() -add_subdirectory(${CMAKE_SOURCE_DIR}/benchmarks) -add_subdirectory(${CMAKE_SOURCE_DIR}/examples) \ No newline at end of file +add_subdirectory(benchmarks) +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} +) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMinorVersion +) + +install( + EXPORT cpp_requestTargets + FILE cpp_requestTargets.cmake + NAMESPACE cpp_request:: + DESTINATION ${CPP_REQUEST_INSTALL_CMAKEDIR} +) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cpp_requestConfigVersion.cmake + DESTINATION ${CPP_REQUEST_INSTALL_CMAKEDIR} +) diff --git a/cmake/cpp_requestConfig.cmake.in b/cmake/cpp_requestConfig.cmake.in new file mode 100644 index 0000000..44500f8 --- /dev/null +++ b/cmake/cpp_requestConfig.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/cpp_requestTargets.cmake") + +check_required_components(cpp_request) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee98691..6ee4ba0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,13 +15,20 @@ add_library(internal ${CMAKE_CURRENT_SOURCE_DIR}/net/tcp_connection.cpp ) +set_target_properties(internal PROPERTIES + EXPORT_NAME cpp_request + OUTPUT_NAME cpp_request +) + add_library(${PROJECT_NAME}::internal ALIAS internal) +add_library(${PROJECT_NAME}::cpp_request ALIAS internal) target_include_directories(internal PUBLIC - ${CMAKE_SOURCE_DIR}/include + $ + $ PRIVATE - ${CMAKE_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src ) target_compile_features(internal PUBLIC cxx_std_17) @@ -29,3 +36,18 @@ target_compile_features(internal PUBLIC cxx_std_17) if(WIN32) target_link_libraries(internal 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" +) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a0fa74f..167b55a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -include(${CMAKE_SOURCE_DIR}/cmake/packages/google-test.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/packages/google-test.cmake) find_package(Threads REQUIRED) add_executable(cpp_request_tests @@ -24,7 +24,7 @@ add_executable(cpp_request_tests target_include_directories(cpp_request_tests PRIVATE - ${CMAKE_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src ) target_link_libraries(cpp_request_tests @@ -41,3 +41,13 @@ endif() target_compile_features(cpp_request_tests PRIVATE cxx_std_17) gtest_discover_tests(cpp_request_tests) + +add_test( + NAME PackageConsumer.InstallAndUse + COMMAND + ${CMAKE_COMMAND} + -DCPP_REQUEST_SOURCE_DIR=${PROJECT_SOURCE_DIR} + -DCPP_REQUEST_BINARY_DIR=${PROJECT_BINARY_DIR} + -DCPP_REQUEST_CONFIG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/package_consumer_test.cmake +) diff --git a/tests/package_consumer/CMakeLists.txt b/tests/package_consumer/CMakeLists.txt new file mode 100644 index 0000000..10ca2ca --- /dev/null +++ b/tests/package_consumer/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.20) +project(cpp_request_package_consumer LANGUAGES CXX) + +find_package(cpp_request CONFIG REQUIRED) + +add_executable(cpp_request_package_consumer main.cpp) +target_link_libraries( + cpp_request_package_consumer + PRIVATE + cpp_request::cpp_request +) +target_compile_features(cpp_request_package_consumer PRIVATE cxx_std_17) + +enable_testing() +add_test(NAME package_consumer_runs COMMAND cpp_request_package_consumer) diff --git a/tests/package_consumer/main.cpp b/tests/package_consumer/main.cpp new file mode 100644 index 0000000..f406adb --- /dev/null +++ b/tests/package_consumer/main.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +int main() { + cpp_request::Request request{ + cpp_request::Method::Get, + "http://example.com/"}; + request.add_query_param("q", "cpp request"); + + cpp_request::Client client; + cpp_request::ResponseLimits limits; + limits.max_body_bytes = 1024; + client.set_response_limits(limits); + + return cpp_request::error_message(cpp_request::ErrorCode::InvalidUrl).empty() + ? 1 + : 0; +} diff --git a/tests/package_consumer_test.cmake b/tests/package_consumer_test.cmake new file mode 100644 index 0000000..eb8b7ce --- /dev/null +++ b/tests/package_consumer_test.cmake @@ -0,0 +1,86 @@ +if(NOT DEFINED CPP_REQUEST_SOURCE_DIR) + message(FATAL_ERROR "CPP_REQUEST_SOURCE_DIR is required") +endif() + +if(NOT DEFINED CPP_REQUEST_BINARY_DIR) + message(FATAL_ERROR "CPP_REQUEST_BINARY_DIR is required") +endif() + +set(install_prefix "${CPP_REQUEST_BINARY_DIR}/package-consumer-prefix") +set(consumer_build "${CPP_REQUEST_BINARY_DIR}/package-consumer-build") + +file(REMOVE_RECURSE "${install_prefix}" "${consumer_build}") + +set(install_command + "${CMAKE_COMMAND}" + --install "${CPP_REQUEST_BINARY_DIR}" + --prefix "${install_prefix}") +if(DEFINED CPP_REQUEST_CONFIG AND NOT CPP_REQUEST_CONFIG STREQUAL "") + list(APPEND install_command --config "${CPP_REQUEST_CONFIG}") +endif() + +execute_process( + COMMAND ${install_command} + RESULT_VARIABLE install_result + OUTPUT_VARIABLE install_output + ERROR_VARIABLE install_error +) +if(NOT install_result EQUAL 0) + message(FATAL_ERROR + "cpp_request install failed\n${install_output}\n${install_error}") +endif() + +set(configure_command + "${CMAKE_COMMAND}" + -S "${CPP_REQUEST_SOURCE_DIR}/tests/package_consumer" + -B "${consumer_build}" + "-DCMAKE_PREFIX_PATH=${install_prefix}") +if(DEFINED CPP_REQUEST_CONFIG AND NOT CPP_REQUEST_CONFIG STREQUAL "") + list(APPEND configure_command "-DCMAKE_BUILD_TYPE=${CPP_REQUEST_CONFIG}") +endif() + +execute_process( + COMMAND ${configure_command} + RESULT_VARIABLE configure_result + OUTPUT_VARIABLE configure_output + ERROR_VARIABLE configure_error +) +if(NOT configure_result EQUAL 0) + message(FATAL_ERROR + "package consumer configure failed\n${configure_output}\n${configure_error}") +endif() + +set(build_command "${CMAKE_COMMAND}" --build "${consumer_build}") +if(DEFINED CPP_REQUEST_CONFIG AND NOT CPP_REQUEST_CONFIG STREQUAL "") + list(APPEND build_command --config "${CPP_REQUEST_CONFIG}") +endif() + +execute_process( + COMMAND ${build_command} + RESULT_VARIABLE build_result + OUTPUT_VARIABLE build_output + ERROR_VARIABLE build_error +) +if(NOT build_result EQUAL 0) + message(FATAL_ERROR + "package consumer build failed\n${build_output}\n${build_error}") +endif() + +set(test_command + "${CMAKE_CTEST_COMMAND}" + --test-dir "${consumer_build}" + --output-on-failure) +if(DEFINED CPP_REQUEST_CONFIG AND NOT CPP_REQUEST_CONFIG STREQUAL "") + list(APPEND test_command --build-config "${CPP_REQUEST_CONFIG}") +endif() + +execute_process( + COMMAND ${test_command} + RESULT_VARIABLE test_result + OUTPUT_VARIABLE test_output + ERROR_VARIABLE test_error +) +if(NOT test_result EQUAL 0) + message(FATAL_ERROR + "package consumer test failed\n${test_output}\n${test_error}") +endif()