diff --git a/.github/workflows/cmake-flatcc.yaml b/.github/workflows/cmake-flatcc.yaml new file mode 100644 index 000000000..251135bae --- /dev/null +++ b/.github/workflows/cmake-flatcc.yaml @@ -0,0 +1,62 @@ +# 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. + +name: cmake-flatcc + +on: + push: + branches: [main] + pull_request: + paths: + - 'CMakeLists.txt' + - 'examples/cmake-flatcc/**' + - '.github/workflows/cmake-flatcc.yaml' + - 'src/nanoarrow/**' + - 'thirdparty/flatcc/**' + +permissions: + contents: read + +jobs: + external-flatcc: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + cmake: ['latest'] + include: + - os: ubuntu-latest + cmake: '3.18.4.post1' + - os: ubuntu-latest + cmake: '3.23.3' + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-python@v7 + with: + python-version: '3.11' + - name: Install CMake + shell: bash + run: | + if [ "${{ matrix.cmake }}" = "latest" ]; then + python -m pip install --upgrade cmake + else + python -m pip install "cmake==${{ matrix.cmake }}" + fi + - name: Test external flatcc discovery and linking + shell: bash + run: examples/cmake-flatcc/build.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 919da6b46..eb3008c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ # under the License. message(STATUS "Building using CMake version: ${CMAKE_VERSION}") -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.18) set(NANOARROW_VERSION "0.10.0-SNAPSHOT") string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" NANOARROW_BASE_VERSION @@ -37,7 +37,7 @@ option(NANOARROW_IPC "Build IPC extension" OFF) option(NANOARROW_FLATCC_ROOT_DIR "Root directory for flatcc include and lib directories" OFF) option(NANOARROW_FLATCC_INCLUDE_DIR "Include directory for flatcc includes" OFF) -option(NANOARROW_FLATCC_LIB_DIR "Library directory that contains libflatccrt.a" OFF) +option(NANOARROW_FLATCC_LIB_DIR "Library directory that contains the flatcc runtime" OFF) option(NANOARROW_IPC_WITH_ZSTD "Build nanoarrow with ZSTD compression support built in" OFF) option(NANOARROW_IPC_WITH_LZ4 "Build nanoarrow with LZ4 compression support built in" OFF) @@ -95,8 +95,8 @@ if(NANOARROW_CODE_COVERAGE) endif() # Avoids a warning about timestamps on downloaded files (prefer new policy -# if available)) -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.23") +# if available). +if(POLICY CMP0135) cmake_policy(SET CMP0135 NEW) endif() @@ -241,6 +241,8 @@ if(NANOARROW_IPC) find_library(NANOARROW_FLATCC_LIBRARY_DEBUG NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}flatccrt_d${CMAKE_STATIC_LIBRARY_SUFFIX}" flatccrt_d + "${CMAKE_STATIC_LIBRARY_PREFIX}flatccrt${CMAKE_STATIC_LIBRARY_SUFFIX}" + flatccrt PATHS "${NANOARROW_FLATCC_ROOT_DIR}/debug/lib" NO_DEFAULT_PATH) add_library(flatccrt UNKNOWN IMPORTED) diff --git a/examples/cmake-flatcc/README.md b/examples/cmake-flatcc/README.md new file mode 100644 index 000000000..592fba16b --- /dev/null +++ b/examples/cmake-flatcc/README.md @@ -0,0 +1,37 @@ + + +# CMake External flatcc Examples + +This example builds nanoarrow IPC against external flatcc runtimes and runs a +small IPC consumer. It checks static and shared runtimes, static preference when +both are available, Debug and Release discovery, root and separate-directory +options, and configuration failure when the runtime is missing. It exercises +build-time linking; package exports are covered separately by `cmake-scenarios`. + +Run from this directory with Bash, CMake 3.18 or newer, and a C compiler: + +```bash +./build.sh +``` + +The script can also be invoked from any working directory. It builds in a +temporary directory and removes it on exit. On Windows, run it with Git Bash; +the combined static/shared layout is skipped because static and import libraries +use the same filename. diff --git a/examples/cmake-flatcc/build.sh b/examples/cmake-flatcc/build.sh new file mode 100755 index 000000000..145cc7933 --- /dev/null +++ b/examples/cmake-flatcc/build.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# +# 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. + +set -exuo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source_dir="$(cd "${script_dir}/../.." && pwd)" +root="$(mktemp -d "${TMPDIR:-/tmp}/nanoarrow-flatcc-XXXXXX")" +trap 'rm -rf "${root}"' EXIT + +# CMake needs native paths in cache variables when running from Git Bash. +cmake_path() { + if [[ "${OSTYPE}" == msys* || "${OSTYPE}" == cygwin* ]]; then + cygpath -m "$1" + else + printf '%s\n' "$1" + fi +} + +source_dir="$(cmake_path "${source_dir}")" +layouts=(static shared) +# On Windows static and import libraries have the same filename. +if [[ "${OSTYPE}" != msys* && "${OSTYPE}" != cygwin* ]]; then + layouts+=(both) +fi + +for layout in "${layouts[@]}"; do + prefix="${root}/${layout}" + postfix="_d" + expect_static=ON + case "${layout}" in + static) types=(STATIC) ;; + shared) + types=(SHARED) + postfix="" + expect_static=OFF + ;; + both) types=(SHARED STATIC) ;; + esac + + for kind in "${types[@]}"; do + for config in Release Debug; do + build="${root}/fixture-${layout}-${kind}-${config}" + cmake -S "$(cmake_path "${script_dir}/fixture")" -B "$(cmake_path "${build}")" \ + "-DNANOARROW_SOURCE=${source_dir}" \ + "-DCMAKE_BUILD_TYPE=${config}" \ + "-DRUNTIME_TYPE=${kind}" \ + "-DRUNTIME_DEBUG_POSTFIX=${postfix}" \ + "-DCMAKE_INSTALL_PREFIX=$(cmake_path "${prefix}")" + cmake --build "$(cmake_path "${build}")" --config "${config}" --parallel 2 + cmake --install "$(cmake_path "${build}")" --config "${config}" + done + done + + for mode in root dirs; do + for config in Release Debug; do + build="${root}/consumer-${layout}-${mode}-${config}" + libdir="${prefix}/lib" + bindir="${prefix}/bin" + if [ "${config}" = Debug ]; then + libdir="${prefix}/debug/lib" + bindir="${prefix}/debug/bin" + fi + + options=("-DNANOARROW_FLATCC_ROOT_DIR=$(cmake_path "${prefix}")") + expect_debug=ON + if [ "${mode}" = dirs ]; then + # Separate-directory discovery uses the unsuffixed name. + if [ "${config}" = Debug ] && [ -n "${postfix}" ]; then + continue + fi + options=( + "-DNANOARROW_FLATCC_INCLUDE_DIR=$(cmake_path "${prefix}/include")" + "-DNANOARROW_FLATCC_LIB_DIR=$(cmake_path "${libdir}")" + ) + expect_debug=OFF + fi + + cmake -S "$(cmake_path "${script_dir}/consumer")" -B "$(cmake_path "${build}")" \ + "-DNANOARROW_SOURCE=${source_dir}" \ + "-DCMAKE_BUILD_TYPE=${config}" \ + "-DEXPECT_DEBUG=${expect_debug}" \ + "-DEXPECT_STATIC=${expect_static}" \ + "${options[@]}" + cmake --build "$(cmake_path "${build}")" --config "${config}" \ + --target consumer nanoarrow_ipc_shared --parallel 2 + # --test-dir was added after the supported CMake minimum. + ( + cd "${build}" + PATH="${bindir}:${PATH}" ctest -C "${config}" --output-on-failure + ) + done + done +done + +mkdir "${root}/missing" +if cmake -S "${source_dir}" -B "$(cmake_path "${root}/missing-build")" \ + -DNANOARROW_IPC=ON \ + "-DNANOARROW_FLATCC_INCLUDE_DIR=${source_dir}/thirdparty/flatcc/include" \ + "-DNANOARROW_FLATCC_LIB_DIR=$(cmake_path "${root}/missing")" \ + > "${root}/missing.log" 2>&1; then + cat "${root}/missing.log" + echo "Expected missing-runtime configuration failure" >&2 + exit 1 +fi +if ! grep -q NANOARROW_FLATCC_LIBRARY "${root}/missing.log"; then + cat "${root}/missing.log" + echo "Configuration failed for a reason other than a missing runtime" >&2 + exit 1 +fi + +echo "External flatcc discovery checks passed." diff --git a/examples/cmake-flatcc/consumer/CMakeLists.txt b/examples/cmake-flatcc/consumer/CMakeLists.txt new file mode 100644 index 000000000..32d7406f9 --- /dev/null +++ b/examples/cmake-flatcc/consumer/CMakeLists.txt @@ -0,0 +1,39 @@ +# 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 3.18) +project(flatcc_consumer C) +set(NANOARROW_IPC + ON + CACHE BOOL "") +add_subdirectory("${NANOARROW_SOURCE}" nanoarrow) +# Verify discovery as well as linking: a Release fallback can otherwise hide a +# missed unsuffixed Debug library. +if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND EXPECT_DEBUG) + if(NOT NANOARROW_FLATCC_LIBRARY_DEBUG MATCHES "/debug/lib/") + message(FATAL_ERROR "Did not select the external Debug runtime") + endif() +endif() +if(EXPECT_STATIC AND NOT WIN32) + if(NOT NANOARROW_FLATCC_LIBRARY MATCHES "[.]a$") + message(FATAL_ERROR "Did not prefer the static runtime") + endif() +endif() +add_executable(consumer main.c) +target_link_libraries(consumer PRIVATE nanoarrow::nanoarrow_ipc) +enable_testing() +add_test(NAME ipc-runtime COMMAND consumer) diff --git a/examples/cmake-flatcc/consumer/main.c b/examples/cmake-flatcc/consumer/main.c new file mode 100644 index 000000000..a8915226e --- /dev/null +++ b/examples/cmake-flatcc/consumer/main.c @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#include +int main(void) { + struct ArrowIpcDecoder decoder; + if (ArrowIpcDecoderInit(&decoder)) return 1; + ArrowIpcDecoderReset(&decoder); + return 0; +} diff --git a/examples/cmake-flatcc/fixture/CMakeLists.txt b/examples/cmake-flatcc/fixture/CMakeLists.txt new file mode 100644 index 000000000..4cce145ec --- /dev/null +++ b/examples/cmake-flatcc/fixture/CMakeLists.txt @@ -0,0 +1,39 @@ +# 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 3.18) +project(flatcc_fixture C) +add_library(flatccrt + ${RUNTIME_TYPE} + "${NANOARROW_SOURCE}/thirdparty/flatcc/src/runtime/builder.c" + "${NANOARROW_SOURCE}/thirdparty/flatcc/src/runtime/emitter.c" + "${NANOARROW_SOURCE}/thirdparty/flatcc/src/runtime/verifier.c" + "${NANOARROW_SOURCE}/thirdparty/flatcc/src/runtime/refmap.c") +target_include_directories(flatccrt + PRIVATE "${NANOARROW_SOURCE}/thirdparty/flatcc/include") +set_target_properties(flatccrt + PROPERTIES POSITION_INDEPENDENT_CODE ON + WINDOWS_EXPORT_ALL_SYMBOLS ON + DEBUG_POSTFIX "${RUNTIME_DEBUG_POSTFIX}") +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(subdir "debug/") +endif() +install(TARGETS flatccrt + ARCHIVE DESTINATION "${subdir}lib" + LIBRARY DESTINATION "${subdir}lib" + RUNTIME DESTINATION "${subdir}bin") +install(DIRECTORY "${NANOARROW_SOURCE}/thirdparty/flatcc/include/" DESTINATION include)