Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ on:
permissions:
contents: read

# New PR commits supersede older checks; keep every non-PR run independent.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# Bound compiler memory use while taking advantage of multiple runner cores.
CMAKE_BUILD_PARALLEL_LEVEL: "2"
CSV_FETCHCONTENT_BASE_DIR: ${{ github.workspace }}/.cache/fetchcontent

jobs:
Expand Down
18 changes: 11 additions & 7 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ on:
schedule:
- cron: '0 2 * * 0' # Weekly on Sunday at 2 AM UTC

# New PR commits supersede older checks; keep every non-PR run independent.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# Bound compiler memory use while taking advantage of multiple runner cores.
CMAKE_BUILD_PARALLEL_LEVEL: "2"

jobs:
analyze:
name: CodeQL C++
Expand All @@ -31,15 +40,10 @@ jobs:
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
language: ${{ matrix.language }}
languages: ${{ matrix.language }}
queries: security-and-quality
config-file: ./.github/codeql/codeql-config.yml

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake


- name: Configure CMake
run: |
mkdir -p build
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/compat-edge-cases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ name: Compatibility Edge Cases
permissions:
contents: read

# New PR commits supersede older checks; keep every non-PR run independent.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# Bound compiler memory use while taking advantage of multiple runner cores.
CMAKE_BUILD_PARALLEL_LEVEL: "2"
CSV_FETCHCONTENT_BASE_DIR: ${{ github.workspace }}/.cache/fetchcontent

on:
Expand All @@ -29,10 +36,8 @@ jobs:
runs-on: windows-latest

steps:
- name: Checkout repository and submodules
- name: Checkout repository
uses: actions/checkout@v5
with:
submodules: recursive

- name: Set up MSVC developer command prompt
uses: ilammy/msvc-dev-cmd@v1
Expand All @@ -43,18 +48,13 @@ jobs:
with:
run: "false"

- name: Cache CMake FetchContent dependencies
uses: actions/cache@v5
with:
path: ${{ env.CSV_FETCHCONTENT_BASE_DIR }}
key: fetchcontent-${{ runner.os }}-msvc-no-zc-${{ hashFiles('CMakeLists.txt', 'tests/CMakeLists.txt') }}

- name: Configure CMake (for single-header generation)
run: >
cmake -S ${{ github.workspace }}
-B ${{ github.workspace }}/build/no-zc-cplusplus
-DCSV_CXX_STANDARD=20
-DCSV_BUILD_PROGRAMS=OFF
-DCSV_BUILD_TESTS=OFF
-DBUILD_PYTHON=OFF
-DCSV_SINGLE_HEADER_EXECUTABLE="${{ steps.single-header.outputs.executable }}"

Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ permissions:
contents: read
pull-requests: write

# New PR commits supersede older checks; keep every non-PR run independent.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# Bound compiler memory use while taking advantage of multiple runner cores.
CMAKE_BUILD_PARALLEL_LEVEL: "2"
CSV_FETCHCONTENT_BASE_DIR: ${{ github.workspace }}/.cache/fetchcontent

jobs:
Expand Down
104 changes: 104 additions & 0 deletions .github/workflows/gcc-compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Older GCC compatibility

on:
push:
branches: [master]
paths:
- "include/**"
- "CMakeLists.txt"
- "cmake/**"
- "single_header.json"
- "tests/compatibility/gcc/**"
- ".github/workflows/gcc-compatibility.yml"
pull_request:
branches: [master]
paths:
- "include/**"
- "CMakeLists.txt"
- "cmake/**"
- "single_header.json"
- "tests/compatibility/gcc/**"
- ".github/workflows/gcc-compatibility.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
gcc:
name: GCC ${{ matrix.version }} / C++17
runs-on: ubuntu-24.04
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- version: "8.5.0"
image: gcc:8.5.0
- version: "9.5.0"
image: gcc:9.5.0-bullseye
- version: "10.5.0"
image: gcc:10.5.0-bullseye
# The first GCC 11 release covers the floating charconv boundary.
- version: "11.1.0"
image: gcc:11.1.0-bullseye
env:
GCC_IMAGE: ${{ matrix.image }}
GCC_VERSION: ${{ matrix.version }}
steps:
# Keep JavaScript actions on the host; old images may lack Node's glibc.
- uses: actions/checkout@v5

- name: Install single_header
id: single-header
uses: vincentlaucsb/single_header@0.1.0
with:
run: "false"

- name: Generate canonical single header
run: |
cmake -S . -B build/gcc-header -DCSV_CXX_STANDARD=17 \
-DCSV_BUILD_TESTS=OFF -DCSV_BUILD_PROGRAMS=OFF \
-DCSV_SINGLE_HEADER_EXECUTABLE="${{ steps.single-header.outputs.executable }}"
cmake --build build/gcc-header --target generate_single_header

- name: Prepare portable CMake and compiler
id: toolchain
run: |
mkdir -p "$RUNNER_TEMP/csv-cmake"
curl --fail --location --retry 3 \
https://cmake.org/files/v3.31/cmake-3.31.6-linux-x86_64.tar.gz \
--output "$RUNNER_TEMP/csv-cmake.tar.gz"
echo "5a1133ff103c71eb5120e2cc3de922733e7d8a26a98ae716397e8676adb367bf $RUNNER_TEMP/csv-cmake.tar.gz" | sha256sum --check
tar -xzf "$RUNNER_TEMP/csv-cmake.tar.gz" -C "$RUNNER_TEMP/csv-cmake" --strip-components=1
docker pull "$GCC_IMAGE"
docker run --rm "$GCC_IMAGE" g++ --version
test "$(docker run --rm "$GCC_IMAGE" g++ -dumpfullversion)" = "$GCC_VERSION"

- name: Build and run CMake library consumers
run: |
docker run --rm --user "$(id -u):$(id -g)" \
-v "$GITHUB_WORKSPACE:/src" -v "$RUNNER_TEMP/csv-cmake:/cmake:ro" \
-w /src "$GCC_IMAGE" bash -euc '
/cmake/bin/cmake -S tests/compatibility/gcc -B build/gcc-linked -DCMAKE_BUILD_TYPE=Release
/cmake/bin/cmake --build build/gcc-linked --parallel 2
/cmake/bin/ctest --test-dir build/gcc-linked --output-on-failure
'

- name: Build and run standalone generated header consumers
# Preserve independent diagnostics even if the linked-library check fails.
if: ${{ !cancelled() && steps.toolchain.outcome == 'success' }}
run: |
docker run --rm --user "$(id -u):$(id -g)" \
-v "$GITHUB_WORKSPACE:/src" -v "$RUNNER_TEMP/csv-cmake:/cmake:ro" \
-w /src "$GCC_IMAGE" bash -euc '
/cmake/bin/cmake -S tests/compatibility/gcc -B build/gcc-generated \
-DCMAKE_BUILD_TYPE=Release \
-DCSV_COMPAT_SINGLE_HEADER_DIR=/src/build/gcc-header/single_include_generated
/cmake/bin/cmake --build build/gcc-generated --parallel 2
/cmake/bin/ctest --test-dir build/gcc-generated --output-on-failure
'
12 changes: 7 additions & 5 deletions .github/workflows/sanitizers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ on:
permissions:
contents: read

# New PR commits supersede older checks; keep every non-PR run independent.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# Bound compiler memory use while taking advantage of multiple runner cores.
CMAKE_BUILD_PARALLEL_LEVEL: "2"
CSV_FETCHCONTENT_BASE_DIR: ${{ github.workspace }}/.cache/fetchcontent

jobs:
Expand Down Expand Up @@ -54,11 +61,6 @@ jobs:
path: ${{ env.CSV_FETCHCONTENT_BASE_DIR }}
key: fetchcontent-${{ runner.os }}-sanitizer-${{ matrix.sanitizer }}-std${{ matrix.cxx_standard }}-${{ hashFiles('CMakeLists.txt', 'tests/CMakeLists.txt') }}

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake

- name: Configure CMake with ${{ matrix.name }}
run: |
mkdir -p build
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.6.0
GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(Catch2)
Expand Down
34 changes: 34 additions & 0 deletions tests/compatibility/gcc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.15)
project(csv_gcc_compatibility LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
enable_testing()

function(add_float_smoke name)
add_executable(${name} smoke.cpp)
add_test(NAME ${name} COMMAND ${name})
endfunction()

if(CSV_COMPAT_SINGLE_HEADER_DIR)
# Standalone consumers deliberately inherit no csv target definitions.
find_package(Threads REQUIRED)
foreach(name generated_float_smoke generated_float_optout)
add_float_smoke(${name})
target_include_directories(${name} PRIVATE "${CSV_COMPAT_SINGLE_HEADER_DIR}")
target_link_libraries(${name} PRIVATE Threads::Threads)
endforeach()
target_compile_definitions(generated_float_optout PRIVATE
CLASSIFY_SCALAR_DISABLE_STD_FLOAT_FROM_CHARS=1
CSV_COMPAT_EXPECT_FLOAT_OPTOUT=1)
else()
set(CSV_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(CSV_BUILD_PROGRAMS OFF CACHE BOOL "" FORCE)
set(BUILD_PYTHON OFF CACHE BOOL "" FORCE)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../.." csv-library)
foreach(library csv csv_no_simd)
add_float_smoke(${library}_float_smoke)
target_link_libraries(${library}_float_smoke PRIVATE ${library})
endforeach()
endif()
26 changes: 26 additions & 0 deletions tests/compatibility/gcc/smoke.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "csv.hpp"

#include <cmath>
#include <iostream>

#if defined(CSV_COMPAT_EXPECT_FLOAT_OPTOUT) && defined(CLASSIFY_SCALAR_HAS_STD_FLOAT_FROM_CHARS)
#error "The explicit floating-point from_chars opt-out was ignored"
#endif

int main() {
// Exercise field conversion and linking on old libstdc++ versions without
// involving reader/chunk behavior, which is covered by the main suite.
const char* inputs[] = { "1.25", "-42.5", "6.25e2", "1.5e-3" };
const double expected[] = { 1.25, -42.5, 625.0, 0.0015 };
for (unsigned i = 0; i < sizeof(inputs) / sizeof(inputs[0]); ++i) {
csv::CSVField field(inputs[i]);
const double actual = field.get<double>();
if (!field.is_float() || !std::isfinite(actual)
|| std::abs(actual - expected[i]) > 1e-12) {
std::cerr << "Incorrect floating-point conversion for " << inputs[i]
<< ": " << actual << '\n';
return 1;
}
}
return 0;
}
Loading