Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/cmake-flatcc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 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'
- 'ci/scripts/test_cmake_flatcc.py'
- '.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
run: python ci/scripts/test_cmake_flatcc.py
10 changes: 6 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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)
Expand Down
190 changes: 190 additions & 0 deletions ci/scripts/test_cmake_flatcc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# 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.

"""Build IPC against external flatcc runtimes without exercising package exports."""

import os
import subprocess
import tempfile
from pathlib import Path


def run(*args, **kwargs):
subprocess.run([str(arg) for arg in args], check=True, **kwargs)


def main():
source = Path(__file__).resolve().parents[2]
with tempfile.TemporaryDirectory(prefix="nanoarrow-flatcc-") as tmp:
root = Path(tmp)
fixture = root / "fixture"
fixture.mkdir()
(fixture / "CMakeLists.txt").write_text(
"""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)
""",
encoding="utf-8",
)
consumer = root / "consumer"
consumer.mkdir()
(consumer / "CMakeLists.txt").write_text(
"""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)
""",
encoding="utf-8",
)
(consumer / "main.c").write_text(
"""#include <nanoarrow/nanoarrow_ipc.h>
int main(void) {
struct ArrowIpcDecoder decoder;
if (ArrowIpcDecoderInit(&decoder)) return 1;
ArrowIpcDecoderReset(&decoder);
return 0;
}
""",
encoding="utf-8",
)
# On Windows static and import libraries have the same filename.
layouts = [("static", ["STATIC"], "_d"), ("shared", ["SHARED"], "")]
if os.name != "nt":
layouts.append(("both", ["SHARED", "STATIC"], "_d"))
for name, types, postfix in layouts:
prefix = root / name
for kind in types:
for config in ("Release", "Debug"):
build = root / f"fixture-{name}-{kind}-{config}"
run(
"cmake",
"-S",
fixture,
"-B",
build,
f"-DNANOARROW_SOURCE={source.as_posix()}",
f"-DCMAKE_BUILD_TYPE={config}",
f"-DRUNTIME_TYPE={kind}",
f"-DRUNTIME_DEBUG_POSTFIX={postfix}",
f"-DCMAKE_INSTALL_PREFIX={prefix.as_posix()}",
)
run(
"cmake", "--build", build, "--config", config, "--parallel", "2"
)
run("cmake", "--install", build, "--config", config)
for mode in ("root", "dirs"):
for config in ("Release", "Debug"):
build = root / f"consumer-{name}-{mode}-{config}"
options = [f"-DNANOARROW_FLATCC_ROOT_DIR={prefix.as_posix()}"]
if mode == "dirs":
libdir = prefix / ("debug/lib" if config == "Debug" else "lib")
# Separate-directory discovery uses the unsuffixed name.
if config == "Debug" and postfix:
continue
include = (prefix / "include").as_posix()
options = [
f"-DNANOARROW_FLATCC_INCLUDE_DIR={include}",
f"-DNANOARROW_FLATCC_LIB_DIR={libdir.as_posix()}",
]
run(
"cmake",
"-S",
consumer,
"-B",
build,
f"-DNANOARROW_SOURCE={source.as_posix()}",
f"-DCMAKE_BUILD_TYPE={config}",
f"-DEXPECT_DEBUG={'ON' if mode == 'root' else 'OFF'}",
f"-DEXPECT_STATIC={'ON' if 'STATIC' in types else 'OFF'}",
*options,
)
run(
"cmake",
"--build",
build,
"--config",
config,
"--target",
"consumer",
"nanoarrow_ipc_shared",
"--parallel",
"2",
)
env = os.environ.copy()
bindir = prefix / ("debug/bin" if config == "Debug" else "bin")
env["PATH"] = os.pathsep.join([str(bindir), env["PATH"]])
# --test-dir was added after the supported CMake minimum.
run(
"ctest", "-C", config, "--output-on-failure", cwd=build, env=env
)
missing = root / "missing"
missing.mkdir()
result = subprocess.run(
[
"cmake",
"-S",
str(source),
"-B",
str(root / "missing-build"),
"-DNANOARROW_IPC=ON",
f"-DNANOARROW_FLATCC_INCLUDE_DIR={source}/thirdparty/flatcc/include",
f"-DNANOARROW_FLATCC_LIB_DIR={missing}",
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
)
if result.returncode == 0 or "NANOARROW_FLATCC_LIBRARY" not in result.stdout:
raise RuntimeError(
f"Expected missing-runtime configuration failure: {result.stdout}"
)
print("External flatcc discovery checks passed.")


if __name__ == "__main__":
main()
Loading