cmake_minimum_required(VERSION 3.5) project( weaseljson VERSION 0.0.1 DESCRIPTION "A constant memory streaming json parser." HOMEPAGE_URL "https://git.weaselab.dev/weaselab/weaseljson" LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) include(CMakePushCheckState) include(CheckCXXCompilerFlag) include(CheckIncludeFileCXX) include(CheckCXXSourceCompiles) set(DEFAULT_BUILD_TYPE "Release") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message( STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.") set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() add_compile_options( -Werror=switch-enum -Wswitch-enum -Wunused-variable -fPIC -fdata-sections -ffunction-sections -fno-jump-tables # https://github.com/llvm/llvm-project/issues/54247 -fno-omit-frame-pointer -g) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") add_link_options("-Wno-unused-command-line-argument") find_program(LLVM_OBJCOPY llvm-objcopy) if(LLVM_OBJCOPY) set(CMAKE_OBJCOPY ${LLVM_OBJCOPY} CACHE FILEPATH "path to objcopy binary" FORCE) endif() endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options("-Wno-maybe-uninitialized") endif() set(full_relro_flags "-pie;LINKER:-z,relro,-z,now,-z,noexecstack") cmake_push_check_state() list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${full_relro_flags}) check_cxx_source_compiles("int main(){}" HAS_FULL_RELRO FAIL_REGEX "warning:") if(HAS_FULL_RELRO) add_link_options(${full_relro_flags}) endif() cmake_pop_check_state() if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) add_compile_options(-mbranch-protection=standard) else() add_compile_options(-fcf-protection) set(rewrite_endbr_flags "-fuse-ld=mold;LINKER:-z,rewrite-endbr") cmake_push_check_state() list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${rewrite_endbr_flags}) check_cxx_source_compiles("int main(){}" HAS_REWRITE_ENDBR FAIL_REGEX "warning:") if(HAS_REWRITE_ENDBR) add_link_options(${rewrite_endbr_flags}) endif() cmake_pop_check_state() endif() set(version_script_flags LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map) cmake_push_check_state() list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${version_script_flags}) check_cxx_source_compiles("int main(){}" HAS_VERSION_SCRIPT FAIL_REGEX "warning:") cmake_pop_check_state() if(CMAKE_SYSTEM_NAME STREQUAL Linux) add_link_options(LINKER:--gc-sections) endif() # This is encouraged according to # https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/valgrind) add_subdirectory(third_party) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") include(CTest) include(doctest) add_library(${PROJECT_NAME}-object OBJECT src/lib.cpp) target_compile_options(${PROJECT_NAME}-object PRIVATE -fno-exceptions -fvisibility=hidden) target_include_directories(${PROJECT_NAME}-object PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) if(NOT LD_EXE) set(LD_EXE ld) endif() set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o COMMAND ${LD_EXE} -r $ -o ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o DEPENDS $ COMMAND_EXPAND_LISTS) add_library(${PROJECT_NAME} SHARED ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o) if(CMAKE_BUILD_TYPE STREQUAL Debug) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) else() set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C) endif() if(HAS_VERSION_SCRIPT) target_link_options( ${PROJECT_NAME} PRIVATE LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map) endif() add_library(${PROJECT_NAME}-static STATIC ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o) if(CMAKE_BUILD_TYPE STREQUAL Debug) set_target_properties(${PROJECT_NAME}-static PROPERTIES LINKER_LANGUAGE CXX) else() set_target_properties(${PROJECT_NAME}-static PROPERTIES LINKER_LANGUAGE C) endif() if(NOT APPLE) add_custom_command( TARGET ${PROJECT_NAME}-static POST_BUILD COMMAND ${CMAKE_OBJCOPY} --keep-global-symbols=${CMAKE_CURRENT_SOURCE_DIR}/symbol-exports.txt $ || echo "Proceeding with all symbols global in static library") endif() set(TEST_FLAGS -Wall -Wextra -Wunreachable-code -Wpedantic -UNDEBUG) add_executable(mytest src/test.cpp) target_include_directories(mytest PRIVATE include) target_link_libraries(mytest PRIVATE ${PROJECT_NAME} doctest nanobench simdjson) target_compile_options(mytest PRIVATE ${TEST_FLAGS}) doctest_discover_tests(mytest WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) include(CMakePushCheckState) include(CheckCXXCompilerFlag) cmake_push_check_state() set(CMAKE_REQUIRED_LINK_OPTIONS -fsanitize=fuzzer-no-link) check_cxx_compiler_flag(-fsanitize=fuzzer-no-link HAS_LIB_FUZZER) cmake_pop_check_state() if(HAS_LIB_FUZZER) add_executable(fuzz src/fuzz.cpp src/lib.cpp) target_include_directories(fuzz PRIVATE include) target_link_libraries(fuzz PRIVATE simdjson) target_compile_options(fuzz PRIVATE -fsanitize=fuzzer ${TEST_FLAGS}) target_link_options(fuzz PRIVATE -fsanitize=fuzzer) endif() add_executable(validate src/validate.cpp) target_link_libraries(validate ${PROJECT_NAME}-static) target_include_directories(validate PRIVATE include) # symbol visibility tests if(NOT CMAKE_BUILD_TYPE STREQUAL Debug) if(APPLE) set(symbol_exports ${CMAKE_CURRENT_SOURCE_DIR}/apple-symbol-exports.txt) set(symbol_imports ${CMAKE_CURRENT_SOURCE_DIR}/apple-symbol-imports.txt) else() set(symbol_exports ${CMAKE_CURRENT_SOURCE_DIR}/symbol-exports.txt) if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) set(symbol_imports ${CMAKE_CURRENT_SOURCE_DIR}/aarch64-symbol-imports.txt) else() set(symbol_imports ${CMAKE_CURRENT_SOURCE_DIR}/symbol-imports.txt) endif() endif() add_test( NAME conflict_set_shared_symbols COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_symbols.sh $ ${symbol_exports} ${symbol_imports}) add_test( NAME conflict_set_static_symbols COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_symbols.sh $ ${symbol_exports} ${symbol_imports}) endif() if(NOT CMAKE_CROSSCOMPILING) find_program(HARDENING_CHECK hardening-check) if(HARDENING_CHECK) add_test(NAME hardening_check COMMAND ${HARDENING_CHECK} $ --nofortify --nostackprotector) endif() endif() # packaging set(CPACK_PACKAGE_CONTACT andrew@weaselab.dev) set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME all) set(CPACK_PACKAGE_VENDOR "Weaselab") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") # rpm set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) set(CPACK_RPM_SPEC_INSTALL_POST "/bin/true") # avoid stripping set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0") set(CPACK_RPM_FILE_NAME RPM-DEFAULT) # deb set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) # see *-imports.txt - dependency versions need to be synced with symbol versions if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)") else() set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.14)") endif() # macos set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0) if(APPLE) find_program(PANDOC_EXE pandoc) if(PANDOC_EXE) execute_process(COMMAND ${PANDOC_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/README.md -o ${CMAKE_CURRENT_BINARY_DIR}/README.txt) set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_BINARY_DIR}/README.txt) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/LICENSE ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt COPYONLY) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt) endif() include(CPack) include(GNUInstallDirs) target_include_directories( ${PROJECT_NAME} PUBLIC $ $) target_include_directories( ${PROJECT_NAME}-static PUBLIC $ $) set_target_properties( ${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) install( TARGETS ${PROJECT_NAME} ${PROJECT_NAME}-static EXPORT ${PROJECT_NAME}Config ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) install(EXPORT ${PROJECT_NAME}Config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) cpack_add_component(all)