blob: 017734fd3c922d2f7fa0e712e816c64b84fc15ae [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
cmake_minimum_required(VERSION 2.8)
if(POLICY CMP0026)
cmake_policy(SET CMP0026 OLD)
endif()
if(POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
set(GAR_MAJOR_VERSION 0)
set(GAR_MINOR_VERSION 11)
set(GAR_PATCH_VERSION 4)
set(GAR_VERSION ${GAR_MAJOR_VERSION}.${GAR_MINOR_VERSION}.${GAR_PATCH_VERSION})
project(graph-archive LANGUAGES C CXX VERSION ${GAR_VERSION})
# ------------------------------------------------------------------------------
# cmake options
# ------------------------------------------------------------------------------
option(BUILD_TESTS "Build unit tests" OFF)
option(BUILD_EXAMPLES "Build examples" OFF)
option(BUILD_BENCHMARKS "Build benchmarks" OFF)
# ------------------------------------------------------------------------------
# setting default cmake type to Release
# ------------------------------------------------------------------------------
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_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif ()
if(NOT (CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache") AND NOT (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache"))
find_program(ccache_EXECUTABLE ccache)
if(ccache_EXECUTABLE)
set(CMAKE_C_COMPILER_LAUNCHER ${ccache_EXECUTABLE})
set(CMAKE_CXX_COMPILER_LAUNCHER ${ccache_EXECUTABLE})
add_custom_target(gar-ccache-stats
COMMAND ${ccache_EXECUTABLE} --show-stats
)
else()
add_custom_target(gar-ccache-stats
COMMAND echo "ccache not found."
)
endif(ccache_EXECUTABLE)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall")
if (APPLE)
set(CMAKE_MACOSX_RPATH ON)
else ()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ORIGIN")
endif ()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -g")
message(STATUS "[gar] will build in type: ${CMAKE_BUILD_TYPE}")
# ------------------------------------------------------------------------------
# cmake configs
# ------------------------------------------------------------------------------
include(CheckLibraryExists)
include(GNUInstallDirs)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_library(${PROJECT_NAME} INTERFACE)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
target_include_directories(
${PROJECT_NAME}
INTERFACE
$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# ------------------------------------------------------------------------------
# macro functions
# ------------------------------------------------------------------------------
macro(add_subdirectory_shared directory)
set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS ON)
set(CMAKE_BUILD_TYPE_SAVED "${CMAKE_BUILD_TYPE}")
set(CMAKE_BUILD_TYPE Release)
add_subdirectory(${directory} ${ARGN})
set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE_SAVED}")
endmacro()
macro(add_subdirectory_static directory)
set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_BUILD_TYPE_SAVED "${CMAKE_BUILD_TYPE}")
set(CMAKE_BUILD_TYPE Release)
add_subdirectory(${directory} ${ARGN})
set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE_SAVED}")
endmacro()
macro(find_yaml_cpp)
set(MESSAGE_QUIET ON)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
add_subdirectory_static(thirdparty/yaml-cpp EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)
endmacro()
macro(find_catch2)
set(MESSAGE_QUIET ON)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
add_subdirectory_shared(thirdparty/Catch2)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/Catch2/contrib")
unset(MESSAGE_QUIET)
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)
endmacro()
macro(install_gar_target target)
# install
install(TARGETS ${target}
EXPORT gar-targets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
endmacro()
# ------------------------------------------------------------------------------
# building or find third party library
# ------------------------------------------------------------------------------
find_package(Threads REQUIRED)
find_package(OpenSSL QUIET)
if (APPLE)
find_package(curl REQUIRED)
else()
find_package(CURL REQUIRED)
endif()
if(OPENSSL_FOUND)
if(OPENSSL_VERSION LESS "1.1.0")
message(ERROR "The OpenSSL must be greater than or equal to 1.1.0, current version is ${OPENSSL_VERSION}")
endif()
endif()
# check if arrow is installed
find_package(Arrow QUIET)
find_package(ArrowDataset QUIET)
find_package(ArrowAcero QUIET)
find_package(Parquet QUIET)
if (NOT Arrow_FOUND OR NOT ArrowDataset_FOUND OR NOT ArrowAcero_FOUND OR NOT Parquet_FOUND)
message(STATUS "Arrow is not installed, will build from source.")
set(BUILD_ARROW_FROM_SOURCE ON)
else()
message(STATUS "-- Found Arrow: ${Arrow_VERSION}")
set(BUILD_ARROW_FROM_SOURCE OFF)
endif()
if(BUILD_ARROW_FROM_SOURCE)
include(apache-arrow)
build_arrow()
endif()
macro(get_target_location var target)
if(TARGET ${target})
foreach(prop LOCATION LOCATION_NOCONFIG LOCATION_DEBUG LOCATION_RELEASE)
get_target_property(${var} ${target} ${prop})
if(NOT ("${${var}}" STREQUAL "${var}-NOTFOUND"))
break ()
endif()
endforeach()
endif()
endmacro()
# ------------------------------------------------------------------------------
# generate gar library
# ------------------------------------------------------------------------------
macro(build_gar)
file(GLOB_RECURSE CORE_SRC_FILES "src/*.cc" ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/mini-yaml/yaml/*.cpp)
add_library(gar SHARED ${CORE_SRC_FILES})
install_gar_target(gar)
target_compile_features(gar PRIVATE cxx_std_17)
target_include_directories(gar PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/mini-yaml>
)
if(BUILD_ARROW_FROM_SOURCE)
target_include_directories(gar SYSTEM BEFORE PRIVATE ${GAR_ARROW_INCLUDE_DIR})
endif()
target_link_libraries(gar PRIVATE Threads::Threads ${CMAKE_DL_LIBS})
if(APPLE)
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(gar PRIVATE -Wl,-force_load gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_DATASET_STATIC_LIB}"
"${GAR_ACERO_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}")
else()
target_link_libraries(gar PRIVATE -Wl,-force_load Arrow::arrow_shared
Parquet::parquet_shared
ArrowDataset::arrow_dataset_shared
ArrowAcero::arrow_acero_shared)
endif()
else()
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(gar PRIVATE -Wl,--exclude-libs,ALL -Wl,--whole-archive gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_DATASET_STATIC_LIB}"
"${GAR_ARROW_ACERO_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}" -Wl,--no-whole-archive)
else()
target_link_libraries(gar PRIVATE -Wl,--exclude-libs,ALL -Wl,--whole-archive Arrow::arrow_shared
Parquet::parquet_shared
ArrowDataset::arrow_dataset_shared
ArrowAcero::arrow_acero_shared -Wl,--no-whole-archive)
endif()
endif()
# if OpenSSL library exists, link the OpenSSL library.
# OpenSSL has to be linked after GAR_ARROW_BUNDLED_DEPS_STATIC_LIB
if(OPENSSL_FOUND)
target_link_libraries(gar PRIVATE OpenSSL::SSL)
endif()
if (CURL_FOUND)
target_link_libraries(gar PRIVATE ${CURL_LIBRARIES})
endif()
if (APPLE)
target_link_libraries(gar "-framework CoreFoundation")
endif()
endmacro()
build_gar()
# ------------------------------------------------------------------------------
# build example
# ------------------------------------------------------------------------------
if (BUILD_EXAMPLES)
find_package(Boost REQUIRED COMPONENTS graph)
file(GLOB EXAMPLE_FILES RELATIVE "${PROJECT_SOURCE_DIR}/examples" "${PROJECT_SOURCE_DIR}/examples/*.cc")
foreach(f ${EXAMPLE_FILES})
string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${f})
set(E_NAME ${CMAKE_MATCH_1})
message(STATUS "Found example - " ${E_NAME})
add_executable(${E_NAME} examples/${E_NAME}.cc)
target_include_directories(${E_NAME} PRIVATE examples ${PROJECT_SOURCE_DIR}/include $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/Catch2/single_include>)
target_include_directories(${E_NAME} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
if(BUILD_ARROW_FROM_SOURCE)
target_include_directories(${E_NAME} SYSTEM BEFORE PRIVATE ${GAR_ARROW_INCLUDE_DIR})
endif()
target_link_libraries(${E_NAME} PRIVATE gar ${Boost_LIBRARIES} Threads::Threads ${CMAKE_DL_LIBS})
if(APPLE)
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(${E_NAME} PRIVATE -Wl,-force_load gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}")
else()
target_link_libraries(${E_NAME} PRIVATE Arrow::arrow_shared
Parquet::parquet_shared)
endif()
else()
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(${E_NAME} PRIVATE -Wl,--exclude-libs,ALL -Wl,--whole-archive gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}" -Wl,--no-whole-archive)
else()
target_link_libraries(${E_NAME} PRIVATE Arrow::arrow_shared
Parquet::parquet_shared)
endif()
endif()
# if OpenSSL library exists, link the OpenSSL library.
# OpenSSL has to be linked after GAR_ARROW_BUNDLED_DEPS_STATIC_LIB
if(OPENSSL_FOUND)
target_link_libraries(${E_NAME} PRIVATE OpenSSL::SSL)
endif()
if (CURL_FOUND)
target_link_libraries(${E_NAME} PRIVATE CURL::libcurl)
endif()
endforeach()
endif()
# ------------------------------------------------------------------------------
# Install
# ------------------------------------------------------------------------------
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/gar
DESTINATION include
FILES_MATCHING
PATTERN "*.h"
)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/gar
DESTINATION include
FILES_MATCHING
PATTERN "*.hpp"
)
configure_file(gar-config.in.cmake
"${PROJECT_BINARY_DIR}/gar-config.cmake" @ONLY
)
configure_file(gar-config-version.in.cmake
"${PROJECT_BINARY_DIR}/gar-config-version.cmake" @ONLY
)
install(FILES "${PROJECT_BINARY_DIR}/gar-config.cmake"
"${PROJECT_BINARY_DIR}/gar-config-version.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/gar
)
install(EXPORT gar-targets
FILE gar-targets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/gar
)
# ------------------------------------------------------------------------------
# Test targets
# ------------------------------------------------------------------------------
if (BUILD_TESTS)
find_catch2()
macro(add_test target)
set(options)
set(oneValueArgs)
set(multiValueArgs SRCS)
cmake_parse_arguments(add_test "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
add_executable(${target} ${add_test_SRCS})
target_compile_features(${target} PRIVATE cxx_std_17)
if(BUILD_ARROW_FROM_SOURCE)
target_include_directories(${target} SYSTEM BEFORE PRIVATE ${GAR_ARROW_INCLUDE_DIR})
endif()
target_link_libraries(${target} PRIVATE Catch2::Catch2 gar Threads::Threads ${CMAKE_DL_LIBS})
if(APPLE)
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(${target} PRIVATE -Wl,-force_load gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}")
else()
target_link_libraries(${target} Arrow::arrow_shared
Parquet::parquet_shared)
endif()
else()
if(BUILD_ARROW_FROM_SOURCE)
target_link_libraries(${target} PRIVATE -Wl,--exclude-libs,ALL -Wl,--whole-archive gar_arrow_static
"${GAR_PARQUET_STATIC_LIB}"
"${GAR_ARROW_BUNDLED_DEPS_STATIC_LIB}" -Wl,--no-whole-archive)
else()
target_link_libraries(${target} PRIVATE Arrow::arrow_shared
Parquet::parquet_shared)
endif()
endif()
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/include $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/Catch2/single_include>)
target_include_directories(${target} SYSTEM BEFORE PRIVATE ${GAR_ARROW_INCLUDE_DIR})
include(CTest)
include(Catch)
catch_discover_tests(${target})
# if OpenSSL library exists, link the OpenSSL library.
# OpenSSL has to be linked after GAR_ARROW_BUNDLED_DEPS_STATIC_LIB
if(OPENSSL_FOUND)
target_link_libraries(${target} PRIVATE OpenSSL::SSL)
endif()
if (CURL_FOUND)
target_link_libraries(${target} PRIVATE CURL::libcurl)
endif()
endmacro()
add_test(test_info SRCS test/test_info.cc)
add_test(test_arrow_chunk_writer SRCS test/test_arrow_chunk_writer.cc)
add_test(test_builder SRCS test/test_builder.cc)
add_test(test_chunk_info_reader SRCS test/test_chunk_info_reader.cc)
add_test(test_arrow_chunk_reader SRCS test/test_arrow_chunk_reader.cc)
add_test(test_graph SRCS test/test_graph.cc)
# enable_testing()
endif()
if (BUILD_BENCHMARKS)
find_package(benchmark REQUIRED)
macro(add_benchmark target)
set(options)
set(oneValueArgs)
set(multiValueArgs SRCS)
cmake_parse_arguments(add_test "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
add_executable(${target} ${add_test_SRCS})
target_compile_features(${target} PRIVATE cxx_std_17)
target_link_libraries(${target} PRIVATE benchmark::benchmark_main gar Threads::Threads ${CMAKE_DL_LIBS})
# if OpenSSL library exists, link the OpenSSL library.
# OpenSSL has to be linked after GAR_ARROW_BUNDLED_DEPS_STATIC_LIB
if(OPENSSL_FOUND)
target_link_libraries(${target} PRIVATE OpenSSL::SSL)
endif()
if (CURL_FOUND)
target_link_libraries(${target} PRIVATE CURL::libcurl)
endif()
endmacro()
add_benchmark(arrow_chunk_reader_benchmark SRCS benchmarks/arrow_chunk_reader_benchmark.cc)
add_benchmark(graph_info_benchmark SRCS benchmarks/graph_info_benchmark.cc)
endif()
# ------------------------------------------------------------------------------
# Format code & cpplint
# ------------------------------------------------------------------------------
file(GLOB_RECURSE FILES_NEED_FORMAT "include/gar/*.h" "src/*.cc"
"test/*.h" "test/*.cc"
"examples/*.h" "examples/*.cc"
"benchmarks/*.h" "benchmarks/*.cc")
file(GLOB_RECURSE FILES_NEED_LINT "include/gar/*.h" "src/*.cc"
"test/*.h" "test/*.cc"
"examples/*.h" "examples/*.cc"
"benchmarks/*.h" "benchmarks/*.cc")
add_custom_target(gar-clformat
COMMAND clang-format --style=file -i ${FILES_NEED_FORMAT}
COMMENT "Running clang-format."
VERBATIM)
add_custom_target(gar-cpplint
COMMAND ${PROJECT_SOURCE_DIR}/misc/cpplint.py --root=${PROJECT_SOURCE_DIR}/include ${FILES_NEED_LINT}
COMMENT "Running cpplint check."
VERBATIM)
# ------------------------------------------------------------------------------
# build cpp api doc
# ------------------------------------------------------------------------------
find_program(doxygen_EXECUTABLE doxygen NO_CMAKE_SYSTEM_PATH)
if(doxygen_EXECUTABLE)
add_custom_target(gar-cpp-doc
COMMAND ${doxygen_EXECUTABLE}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/apidoc
VERBATIM
)
else()
if(NOT doxygen_EXECUTABLE)
message(STATUS "Cannot find the doxygen executable.")
endif()
endif()