diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 75cc55a4f..8c63e127d 100755 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -29,6 +29,7 @@ endif () if (POLICY CMP0079) cmake_policy(SET CMP0079 NEW) endif () +include(GNUInstallDirs) set(TsFile_CPP_VERSION 2.3.2.dev) if (MSVC) @@ -305,3 +306,5 @@ else() endif () add_subdirectory(examples) + +include(${CMAKE_SOURCE_DIR}/cmake/TsFileCPack.cmake) diff --git a/cpp/README-zh.md b/cpp/README-zh.md index a8af952b1..6a532d1a6 100644 --- a/cpp/README-zh.md +++ b/cpp/README-zh.md @@ -90,7 +90,15 @@ https://github.com/apache/tsfile/issues/94 ```bash sudo apt-get update -sudo apt-get install -y cmake make g++ clang-format libuuid-dev +sudo apt-get install -y cmake make g++ clang-format libuuid-dev dpkg-dev +``` + +在 RHEL/CentOS/Fedora 系统上,可使用 `yum` 或 `dnf` 安装对应依赖: + +```bash +sudo yum install -y cmake make gcc-c++ clang-tools-extra libuuid-devel rpm-build +# 或 +sudo dnf install -y cmake make gcc-c++ clang-tools-extra libuuid-devel rpm-build ``` 构建 tsfile: @@ -115,6 +123,58 @@ mvn package -P with-cpp clean verify 在向 GitHub 提交代码之前,请确保 `mvn` 编译通过。 +### 构建 Linux 安装包 + +C++ CMake 构建可以生成 Linux 发行版可安装包: + +- Debian/Ubuntu:`libtsfile`、`libtsfile-dev`、`tsfile-cli` DEB 包 +- RHEL/CentOS/Fedora:`libtsfile`、`libtsfile-devel`、`tsfile-cli` RPM 包 + +在仓库根目录下,Maven 会先构建 C++ 模块,然后调用 CPack: + +```bash +./mvnw package -P with-cpp +``` + +如果只需要快速生成安装包、不运行 C++ 测试: + +```bash +./mvnw package -P with-cpp -Dbuild.test=OFF -DskipTests +``` + +也可以在 `cpp/` 目录下直接调用 CMake: + +```bash +cmake -S . -B build/package -DCMAKE_BUILD_TYPE=Release +cmake --build build/package --target package +``` + +如果只需要生成其中一种包格式,可以在构建目录下直接运行 `cpack`: + +```bash +cd build/package +cpack -G DEB +cpack -G RPM +``` + +使用 `apt` 安装生成的 DEB 包: + +```bash +sudo apt install ./libtsfile_*.deb ./libtsfile-dev_*.deb ./tsfile-cli_*.deb +``` + +使用 `yum` 或 `dnf` 安装生成的 RPM 包: + +```bash +sudo yum install ./libtsfile-*.rpm ./libtsfile-devel-*.rpm ./tsfile-cli-*.rpm +# 或 +sudo dnf install ./libtsfile-*.rpm ./libtsfile-devel-*.rpm ./tsfile-cli-*.rpm +``` + +安装包会把共享库安装到系统库目录,头文件安装到 `/usr/include/tsfile`, +CMake 包配置安装到 `/usr/lib/cmake/tsfile` 或 `/usr/lib64/cmake/tsfile`, +命令行工具安装为 `/usr/bin/tsfile-cli`。 + --- ### Windows 下 MinGW 编译问题 diff --git a/cpp/README.md b/cpp/README.md index 639aa38f7..ea74d3d35 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -93,7 +93,16 @@ TsFile C++ supports three toolchains: **Linux (GCC/Clang):** ```bash sudo apt-get update -sudo apt-get install -y cmake make g++ clang-format libuuid-dev +sudo apt-get install -y cmake make g++ clang-format libuuid-dev dpkg-dev +``` + +On RHEL/CentOS/Fedora systems, install the equivalent packages with `yum` or +`dnf`: + +```bash +sudo yum install -y cmake make gcc-c++ clang-tools-extra libuuid-devel rpm-build +# or +sudo dnf install -y cmake make gcc-c++ clang-tools-extra libuuid-devel rpm-build ``` **Windows (MSVC):** @@ -136,6 +145,59 @@ Then you can find the shared library at `./cpp/target/build/lib`. Before you submit your code to GitHub, please ensure that the compilation is correct. +### Build Linux Packages + +The C++ CMake build can generate installable packages for Linux distributions: + +- Debian/Ubuntu: `libtsfile`, `libtsfile-dev`, `tsfile-cli` DEB packages +- RHEL/CentOS/Fedora: `libtsfile`, `libtsfile-devel`, `tsfile-cli` RPM packages + +From the repository root, Maven builds the C++ module and then invokes CPack: + +```bash +./mvnw package -P with-cpp +``` + +For a faster package-only build without running C++ tests: + +```bash +./mvnw package -P with-cpp -Dbuild.test=OFF -DskipTests +``` + +To invoke CMake directly from the `cpp/` directory: + +```bash +cmake -S . -B build/package -DCMAKE_BUILD_TYPE=Release +cmake --build build/package --target package +``` + +To generate only one package format, run `cpack` from the build directory: + +```bash +cd build/package +cpack -G DEB +cpack -G RPM +``` + +Install the generated DEB packages with `apt`: + +```bash +sudo apt install ./libtsfile_*.deb ./libtsfile-dev_*.deb ./tsfile-cli_*.deb +``` + +Install the generated RPM packages with `yum` or `dnf`: + +```bash +sudo yum install ./libtsfile-*.rpm ./libtsfile-devel-*.rpm ./tsfile-cli-*.rpm +# or +sudo dnf install ./libtsfile-*.rpm ./libtsfile-devel-*.rpm ./tsfile-cli-*.rpm +``` + +The packages install the shared library under the system library directory, +headers under `/usr/include/tsfile`, CMake package files under +`/usr/lib/cmake/tsfile` or `/usr/lib64/cmake/tsfile`, and the CLI as +`/usr/bin/tsfile-cli`. + ### configure the cross-compilation toolchain Modify the Toolchain File `cmake/ToolChain.cmake`, define the following variables: diff --git a/cpp/cmake/TsFileCPack.cmake b/cpp/cmake/TsFileCPack.cmake new file mode 100644 index 000000000..f816c5324 --- /dev/null +++ b/cpp/cmake/TsFileCPack.cmake @@ -0,0 +1,97 @@ +#[[ +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 + + https://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. +]] + +set(TSFILE_ROOT_DIR ${CMAKE_SOURCE_DIR}/..) +set(TSFILE_DOC_FILES "") +foreach(doc_file LICENSE NOTICE) + if (EXISTS ${TSFILE_ROOT_DIR}/${doc_file}) + list(APPEND TSFILE_DOC_FILES ${TSFILE_ROOT_DIR}/${doc_file}) + endif() +endforeach() + +if (TSFILE_DOC_FILES) + install(FILES ${TSFILE_DOC_FILES} + DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/libtsfile + COMPONENT runtime) + install(FILES ${TSFILE_DOC_FILES} + DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/libtsfile-dev + COMPONENT development) + install(FILES ${TSFILE_DOC_FILES} + DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/tsfile-cli + COMPONENT tools) +endif() + +set(CPACK_PACKAGE_NAME "apache-tsfile") +set(CPACK_PACKAGE_VENDOR "Apache Software Foundation") +set(CPACK_PACKAGE_CONTACT "Apache TsFile Developers ") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://tsfile.apache.org/") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Apache TsFile C++ library and command-line tools") +set(CPACK_PACKAGE_VERSION ${TsFile_CPP_VERSION}) +if (TsFile_CPP_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") + set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2}) + set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3}) +endif() +set(CPACK_PACKAGE_FILE_NAME + "apache-tsfile-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +if (EXISTS ${TSFILE_ROOT_DIR}/LICENSE) + set(CPACK_RESOURCE_FILE_LICENSE ${TSFILE_ROOT_DIR}/LICENSE) +endif() + +set(CPACK_COMPONENTS_ALL runtime development tools) +set(CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "libtsfile") +set(CPACK_COMPONENT_RUNTIME_DESCRIPTION "Apache TsFile shared library.") +set(CPACK_COMPONENT_DEVELOPMENT_DISPLAY_NAME "libtsfile development files") +set(CPACK_COMPONENT_DEVELOPMENT_DESCRIPTION + "Apache TsFile C/C++ headers and CMake package files.") +set(CPACK_COMPONENT_DEVELOPMENT_DEPENDS runtime) +set(CPACK_COMPONENT_TOOLS_DISPLAY_NAME "tsfile-cli") +set(CPACK_COMPONENT_TOOLS_DESCRIPTION "Apache TsFile command-line tool.") +set(CPACK_COMPONENT_TOOLS_DEPENDS runtime) + +set(CPACK_GENERATOR "TGZ") +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + list(APPEND CPACK_GENERATOR "DEB" "RPM") +endif() +set(CPACK_PACKAGING_INSTALL_PREFIX "/usr") + +set(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS ON) +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT}) +set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME "libtsfile") +set(CPACK_DEBIAN_RUNTIME_PACKAGE_SECTION "libs") +set(CPACK_DEBIAN_RUNTIME_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_NAME "libtsfile-dev") +set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_SECTION "libdevel") +set(CPACK_DEBIAN_TOOLS_PACKAGE_NAME "tsfile-cli") +set(CPACK_DEBIAN_TOOLS_PACKAGE_SECTION "database") + +set(CPACK_RPM_COMPONENT_INSTALL ON) +set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") +set(CPACK_RPM_PACKAGE_LICENSE "Apache-2.0") +set(CPACK_RPM_PACKAGE_VENDOR ${CPACK_PACKAGE_VENDOR}) +set(CPACK_RPM_RUNTIME_PACKAGE_NAME "libtsfile") +set(CPACK_RPM_RUNTIME_PACKAGE_GROUP "System Environment/Libraries") +set(CPACK_RPM_DEVELOPMENT_PACKAGE_NAME "libtsfile-devel") +set(CPACK_RPM_DEVELOPMENT_PACKAGE_GROUP "Development/Libraries") +set(CPACK_RPM_TOOLS_PACKAGE_NAME "tsfile-cli") +set(CPACK_RPM_TOOLS_PACKAGE_GROUP "Applications/Databases") + +include(CPack) diff --git a/cpp/cmake/TsFileConfig.cmake.in b/cpp/cmake/TsFileConfig.cmake.in new file mode 100644 index 000000000..08b2f2d48 --- /dev/null +++ b/cpp/cmake/TsFileConfig.cmake.in @@ -0,0 +1,25 @@ +#[[ +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 + + https://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. +]] + +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(Threads) + +include("${CMAKE_CURRENT_LIST_DIR}/TsFileTargets.cmake") diff --git a/cpp/pom.xml b/cpp/pom.xml index 153e75dc2..62a776826 100644 --- a/cpp/pom.xml +++ b/cpp/pom.xml @@ -119,6 +119,23 @@ ${build.type} + + + cmake-package + package + + compile + + + + ${build.type} + package + + cmake-run-tests diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 895c1ddba..e72538425 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -56,32 +56,57 @@ endif() set(PROJECT_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src ) +set(TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS "") if (ENABLE_SNAPPY) - list(APPEND PROJECT_INCLUDE_DIR + set(TSFILE_SNAPPY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE}/google_snappy ${CMAKE_SOURCE_DIR}/third_party/google_snappy ) + list(APPEND PROJECT_INCLUDE_DIR + ${TSFILE_SNAPPY_INCLUDE_DIRS} + ) + list(APPEND TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS + ${TSFILE_SNAPPY_INCLUDE_DIRS} + ) endif() if (ENABLE_LZ4) - list(APPEND PROJECT_INCLUDE_DIR + set(TSFILE_LZ4_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/third_party/lz4 ) + list(APPEND PROJECT_INCLUDE_DIR + ${TSFILE_LZ4_INCLUDE_DIRS} + ) + list(APPEND TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS + ${TSFILE_LZ4_INCLUDE_DIRS} + ) endif() if (ENABLE_LZOKAY) - list(APPEND PROJECT_INCLUDE_DIR + set(TSFILE_LZOKAY_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/third_party/lzokay ) + list(APPEND PROJECT_INCLUDE_DIR + ${TSFILE_LZOKAY_INCLUDE_DIRS} + ) + list(APPEND TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS + ${TSFILE_LZOKAY_INCLUDE_DIRS} + ) endif() if (ENABLE_ZLIB) + set(TSFILE_ZLIB_INCLUDE_DIRS + ${CMAKE_SOURCE_DIR}/third_party/zlib-1.3.1 + ${THIRD_PARTY_INCLUDE}/zlib-1.3.1 + ) list(APPEND PROJECT_INCLUDE_DIR # zlib.h ships in the source tree; zconf.h is generated into the # build tree by zlib's own CMake, so both directories are needed. - ${CMAKE_SOURCE_DIR}/third_party/zlib-1.3.1 - ${THIRD_PARTY_INCLUDE}/zlib-1.3.1 + ${TSFILE_ZLIB_INCLUDE_DIRS} + ) + list(APPEND TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS + ${TSFILE_ZLIB_INCLUDE_DIRS} ) endif() @@ -151,6 +176,12 @@ target_link_libraries(read_obj ${COMPRESSION_LIBS}) target_link_libraries(write_obj ${COMPRESSION_LIBS}) add_library(tsfile SHARED) +target_include_directories(tsfile PUBLIC + $ + $) +foreach(include_dir IN LISTS TSFILE_PUBLIC_THIRD_PARTY_INCLUDE_DIRS) + target_include_directories(tsfile PUBLIC $) +endforeach() if (${COV_ENABLED}) message("Enable code cov...") @@ -162,16 +193,16 @@ if (${COV_ENABLED}) set(COV_LINK_LIB -lgcov) endif() if (ENABLE_ANTLR4) - target_link_libraries(tsfile common_obj compress_obj cwrapper_obj file_obj read_obj write_obj parser_obj ${COV_LINK_LIB}) + target_link_libraries(tsfile PRIVATE common_obj compress_obj cwrapper_obj file_obj read_obj write_obj parser_obj ${COV_LINK_LIB}) else() - target_link_libraries(tsfile common_obj compress_obj cwrapper_obj file_obj read_obj write_obj ${COV_LINK_LIB}) + target_link_libraries(tsfile PRIVATE common_obj compress_obj cwrapper_obj file_obj read_obj write_obj ${COV_LINK_LIB}) endif() else() message("Disable code cov...") if (ENABLE_ANTLR4) - target_link_libraries(tsfile common_obj compress_obj cwrapper_obj file_obj read_obj write_obj parser_obj) + target_link_libraries(tsfile PRIVATE common_obj compress_obj cwrapper_obj file_obj read_obj write_obj parser_obj) else() - target_link_libraries(tsfile common_obj compress_obj cwrapper_obj file_obj read_obj write_obj) + target_link_libraries(tsfile PRIVATE common_obj compress_obj cwrapper_obj file_obj read_obj write_obj) endif() endif() @@ -184,8 +215,37 @@ set_target_properties(tsfile PROPERTIES SOVERSION ${LIBTSFILE_SO_VERSION}) # On Windows a SHARED library produces a .dll (RUNTIME) plus an import .lib # (ARCHIVE); on Unix it produces a .so (LIBRARY). Cover all three so the -# install step works for every platform. +# install step works for every platform and for CPack-based system packages. install(TARGETS tsfile - RUNTIME DESTINATION ${LIBRARY_OUTPUT_PATH} - LIBRARY DESTINATION ${LIBRARY_OUTPUT_PATH} - ARCHIVE DESTINATION ${LIBRARY_OUTPUT_PATH}) + EXPORT TsFileTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT runtime + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT development) + +install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tsfile + COMPONENT development + FILES_MATCHING PATTERN "*.h") + +include(CMakePackageConfigHelpers) +set(TSFILE_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/tsfile) +configure_package_config_file( + ${CMAKE_SOURCE_DIR}/cmake/TsFileConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/TsFileConfig.cmake + INSTALL_DESTINATION ${TSFILE_CMAKE_INSTALL_DIR}) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/TsFileConfigVersion.cmake + VERSION ${TsFile_CPP_VERSION} + COMPATIBILITY SameMajorVersion) +install(EXPORT TsFileTargets + NAMESPACE TsFile:: + DESTINATION ${TSFILE_CMAKE_INSTALL_DIR} + COMPONENT development) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/TsFileConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/TsFileConfigVersion.cmake + DESTINATION ${TSFILE_CMAKE_INSTALL_DIR} + COMPONENT development) diff --git a/cpp/test/CMakeLists.txt b/cpp/test/CMakeLists.txt index 066e5accb..ee641b7aa 100644 --- a/cpp/test/CMakeLists.txt +++ b/cpp/test/CMakeLists.txt @@ -169,6 +169,7 @@ if (ENABLE_LZOKAY) endif() if (ENABLE_ZLIB) + include_directories(${CMAKE_SOURCE_DIR}/third_party/zlib-1.3.1) include_directories(${THIRD_PARTY_INCLUDE}/zlib-1.3.1) endif() diff --git a/cpp/third_party/CMakeLists.txt b/cpp/third_party/CMakeLists.txt index 4ba94fc0b..f48f13b28 100755 --- a/cpp/third_party/CMakeLists.txt +++ b/cpp/third_party/CMakeLists.txt @@ -23,29 +23,31 @@ if (ENABLE_ANTLR4) # pre-seeding it in the cache makes its option() call a no-op. set(WITH_STATIC_CRT OFF CACHE BOOL "Link the ANTLR4 runtime against the dynamic CRT" FORCE) - add_subdirectory(antlr4-cpp-runtime-4) + add_subdirectory(antlr4-cpp-runtime-4 EXCLUDE_FROM_ALL) message("ANTLR4 runtime is enabled") else() message("ANTLR4 runtime is disabled") endif() if (ENABLE_SNAPPY) - add_subdirectory(google_snappy) + set(SNAPPY_INSTALL OFF CACHE BOOL "Install Snappy's header and library" FORCE) + add_subdirectory(google_snappy EXCLUDE_FROM_ALL) endif() if (ENABLE_LZ4) - add_subdirectory(lz4) + add_subdirectory(lz4 EXCLUDE_FROM_ALL) endif() if (ENABLE_LZOKAY) - add_subdirectory(lzokay) + add_subdirectory(lzokay EXCLUDE_FROM_ALL) endif() if (ENABLE_ZLIB) - add_subdirectory(zlib-1.3.1) + set(SKIP_INSTALL_ALL ON CACHE BOOL "Skip bundled zlib install rules" FORCE) + add_subdirectory(zlib-1.3.1 EXCLUDE_FROM_ALL) endif() if (ENABLE_SIMD) - add_subdirectory(simde-0.8.4-rc3) + add_subdirectory(simde-0.8.4-rc3 EXCLUDE_FROM_ALL) endif() -set(CMAKE_POSITION_INDEPENDENT_CODE ON) \ No newline at end of file +set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/cpp/tools/CMakeLists.txt b/cpp/tools/CMakeLists.txt index 70fbcf8ed..f0f5cb15d 100644 --- a/cpp/tools/CMakeLists.txt +++ b/cpp/tools/CMakeLists.txt @@ -51,4 +51,6 @@ set_target_properties(tsfile_cli PROPERTIES OUTPUT_NAME tsfile-cli RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) -install(TARGETS tsfile_cli RUNTIME DESTINATION bin) +install(TARGETS tsfile_cli + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT tools)