From ab8025b42c4f3513986a8d2808cf376c3a286120 Mon Sep 17 00:00:00 2001 From: Justin Nolan Date: Fri, 17 Jul 2026 17:17:46 +0200 Subject: [PATCH] Replace SCons buildsystem with CMake --- .github/actions/openvic-dl-build/action.yml | 113 ++++++----- .github/changed-files.yml | 14 +- .github/workflows/build-matrix.yml | 74 ++----- .github/workflows/builds.yml | 1 - .github/workflows/releases.yml | 29 +-- .gitignore | 16 +- .gitmodules | 26 --- .pre-commit-config.yaml | 4 +- .vscode/launch.json | 24 +-- .vscode/tasks.json | 30 +-- CMakeLists.txt | 179 +++++++++++++++++ CMakePresets.json | 183 +++++++++++++++++ README.md | 21 +- SConstruct | 178 ---------------- deps/SCsub | 212 -------------------- deps/dryad | 1 - deps/fmt | 1 - deps/lexy | 1 - deps/range-v3 | 1 - deps/vmcontainer | 1 - pyproject.toml | 7 - scripts | 1 - tests/CMakeLists.txt | 33 +++ tests/SCsub | 58 ------ tests/deps/SCsub | 204 ------------------- tests/deps/snitch | 1 - 26 files changed, 537 insertions(+), 876 deletions(-) delete mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json delete mode 100644 SConstruct delete mode 100644 deps/SCsub delete mode 160000 deps/dryad delete mode 160000 deps/fmt delete mode 160000 deps/lexy delete mode 160000 deps/range-v3 delete mode 160000 deps/vmcontainer delete mode 160000 scripts create mode 100644 tests/CMakeLists.txt delete mode 100644 tests/SCsub delete mode 100644 tests/deps/SCsub delete mode 160000 tests/deps/snitch diff --git a/.github/actions/openvic-dl-build/action.yml b/.github/actions/openvic-dl-build/action.yml index 9f1c398..2fa9dd2 100644 --- a/.github/actions/openvic-dl-build/action.yml +++ b/.github/actions/openvic-dl-build/action.yml @@ -1,65 +1,65 @@ name: Build OpenVic-Dataloader -description: Setup and Build OpenVic-Dataloader with the provided options +description: Configure, build, and test OpenVic-Dataloader with CMake inputs: identifier: - description: Identifier of this build - target: - description: Target type to build for - required: true - platform: - description: Platform to build for + description: Identifier of this build (artifact name) + preset: + description: CMake configure preset required: true - arch: - description: Architecture to build for + configuration: + description: Build configuration (Debug, Release, RelWithDebInfo) required: true - scons-flags: - description: Additional flags to send to SCons - default: '' - build-library: - description: Whether to build the library file - default: 'true' + target: + description: Godot target flavor (template_debug, template_release, editor) + default: 'template_debug' compliance-type: description: Type of Unicode compliance for the dataloader to support (error, error_replace, loose) default: 'loose' - cache-base-branch: - description: Branch to base the cache upon - default: 'master' - disable-cache: - description: Whether to disable the build cache - default: 'false' + cmake-args: + description: Additional -D flags passed to the CMake configure step + default: '' + run-tests: + description: Whether to run the unit tests after building + default: 'true' runs: using: composite steps: - - name: Setup build cache - uses: OpenVicProject/openvic-cache@master - if: ${{ inputs.disable-cache != 'true' }} - with: - cache-name: ${{ inputs.identifier }} - base-branch: ${{ inputs.cache-base-branch }} - continue-on-error: true - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: "3.x" + - name: Setup MSVC environment + if: ${{ runner.os == 'Windows' }} + shell: pwsh + run: | + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vsPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + Import-Module (Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll") + Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -host_arch=x64' + Get-ChildItem env: | ForEach-Object { Add-Content -Path $env:GITHUB_ENV -Value "$($_.Name)=$($_.Value)" } - - name: Set up SCons + - name: Setup Ninja shell: bash run: | - python -c "import sys; print(sys.version)" - python -m pip install scons - scons --version + # Ninja is preinstalled on GitHub-hosted images; fall back to the + # image's package manager if a future image drops it. + if ! command -v ninja >/dev/null 2>&1; then + if [ "$RUNNER_OS" = "macOS" ]; then + brew install ninja + elif [ "$RUNNER_OS" = "Windows" ]; then + choco install ninja -y + else + sudo apt-get update -y && sudo apt-get install -y ninja-build + fi + fi + ninja --version - name: Install APT dependencies - if: ${{ inputs.platform == 'linux' }} - uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # v1.6.1 + if: ${{ runner.os == 'Linux' }} + uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3 with: packages: build-essential pkg-config libtbb-dev - name: Install and Set g++ to version 13 - if: ${{ inputs.platform == 'linux' }} + if: ${{ runner.os == 'Linux' }} shell: sh run: | g++ --version @@ -70,29 +70,38 @@ runs: sudo update-alternatives --set g++ /usr/bin/g++-13 g++ --version - - name: Compile with SCons - uses: OpenVicProject/openvic-build@master - with: - platform: ${{ inputs.platform }} - target: ${{ inputs.target }} - sconsflags: arch=${{ inputs.arch }} ${{ inputs.build-library && 'build_ovdl_library=yes' }} compliance_type=${{ inputs.compliance-type }} ${{ inputs.scons-flags }} + - name: Configure + shell: bash + run: | + cmake --preset ${{ inputs.preset }} \ + -DGODOTCPP_TARGET=${{ inputs.target }} \ + -DOPENVIC_DATALOADER_COMPLIANCE=${{ inputs.compliance-type }} \ + ${{ inputs.cmake-args }} - - name: Delete compilation files - if: ${{ inputs.platform == 'windows' }} - shell: pwsh + - name: Build + shell: bash + run: | + CONFIG_LOWER=$(echo "${{ inputs.configuration }}" | tr '[:upper:]' '[:lower:]') + cmake --build --preset ${{ inputs.preset }}-$CONFIG_LOWER + + - name: Run tests + if: ${{ inputs.run-tests == 'true' }} + shell: bash run: | - Remove-Item bin/* -Include *.exp,*.pdb -Force + CONFIG_LOWER=$(echo "${{ inputs.configuration }}" | tr '[:upper:]' '[:lower:]') + ctest --preset ${{ inputs.preset }}-$CONFIG_LOWER - name: Upload library artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ github.event.repository.name }}-${{ inputs.identifier }}-library path: | - ${{ github.workspace }}/bin/libopenvic-dataloader.* + ${{ github.workspace }}/out/build/${{ inputs.preset }}/bin/${{ inputs.configuration }}/libopenvic-dataloader.a + ${{ github.workspace }}/out/build/${{ inputs.preset }}/bin/${{ inputs.configuration }}/openvic-dataloader.lib - name: Upload executable artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ github.event.repository.name }}-${{ inputs.identifier }}-executable path: | - ${{ github.workspace }}/bin/openvic-dataloader.headless.* + ${{ github.workspace }}/out/build/${{ inputs.preset }}/bin/${{ inputs.configuration }}/openvic-dataloader.headless* diff --git a/.github/changed-files.yml b/.github/changed-files.yml index f8fb543..af5e3df 100644 --- a/.github/changed-files.yml +++ b/.github/changed-files.yml @@ -4,22 +4,18 @@ everything: &everything - "**" # Determines if build actions should occur after static checks are ran. Broadly speaking, these -# files changing would result in SCons rebuilding the engine, or are otherwise pertinent to the +# files changing would result in CMake rebuilding, or are otherwise pertinent to the # buildsystem itself. sources: - .github/{actions/*,workflows}/*.yml - - "**/{SConstruct,SCsub,*.py}" + - "**/CMakeLists.txt" + - "**/*.cmake" + - "**/CMakePresets.json" + - "**/*.py" - "**/*.{hpp,cpp,inc}" - - scripts - - deps/** - - tests/** pre-commit: - *everything - - '!scripts/**' - - '!deps/*/**' - - '!tests/deps/*/**' - - '!tests/benchmarks/deps/*/**' # Determines which files are appropriate for running clangd-tidy checks on. clangd: diff --git a/.github/workflows/build-matrix.yml b/.github/workflows/build-matrix.yml index 23cbe7c..db5b0e9 100644 --- a/.github/workflows/build-matrix.yml +++ b/.github/workflows/build-matrix.yml @@ -17,118 +17,88 @@ jobs: - identifier: windows-debug os: windows-latest name: 🏁 Windows Debug + preset: windows-x64-md + configuration: Debug target: template_debug - platform: windows - arch: x86_64 - test-bin-suffix: .md.exe - - - identifier: windows-debug-mingw - os: windows-latest - name: 🏁 Windows Debug (MinGW) - target: template_debug - platform: windows - arch: x86_64 - mingw: true - test-bin-suffix: .md.exe - identifier: windows-debug-replace os: windows-latest name: 🏁 Windows Debug (Replace Error UTF Compliance) + preset: windows-x64-md + configuration: Debug target: template_debug - platform: windows - arch: x86_64 compliance_type: error_replace - test-bin-suffix: .md.exe - identifier: windows-release os: windows-latest name: 🏁 Windows Release + preset: windows-x64-md + configuration: Release target: template_release - platform: windows - arch: x86_64 - test-bin-suffix: .md.exe - - - identifier: windows-release-mingw - os: windows-latest - name: 🏁 Windows Release (MinGW) - target: template_release - platform: windows - arch: x86_64 - mingw: true - test-bin-suffix: .md.exe - identifier: macos-debug os: macos-latest name: 🍎 macOS (universal) Debug + preset: macos-universal + configuration: Debug target: template_debug - platform: macos - arch: universal - identifier: macos-debug-replace os: macos-latest name: 🍎 macOS (universal) Debug (Replace Error UTF Compliance) + preset: macos-universal + configuration: Debug target: template_debug - platform: macos compliance_type: error_replace - arch: universal - identifier: macos-release os: macos-latest name: 🍎 macOS (universal) Release + preset: macos-universal + configuration: Release target: template_release - platform: macos - arch: universal - identifier: linux-debug os: ubuntu-22.04 name: 🐧 Linux Debug + preset: linux-x64 + configuration: Debug target: template_debug - platform: linux - arch: x86_64 - identifier: linux-debug-replace os: ubuntu-22.04 name: 🐧 Linux Debug (Replace Error UTF Compliance) + preset: linux-x64 + configuration: Debug target: template_debug - platform: linux compliance_type: error_replace - arch: x86_64 - identifier: linux-debug-error os: ubuntu-22.04 name: 🐧 Linux Debug (Build Error UTF Compliance) + preset: linux-x64 + configuration: Debug target: template_debug - platform: linux compliance_type: error - arch: x86_64 - identifier: linux-release os: ubuntu-22.04 name: 🐧 Linux Release + preset: linux-x64 + configuration: Release target: template_release - platform: linux - arch: x86_64 steps: - name: Checkout project uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - submodules: recursive persist-credentials: false - - name: Setup MinGW for Windows/MinGW build - if: matrix.platform == 'windows' && (matrix.mingw || false) - uses: egor-tensin/setup-mingw@0ea9f5370e9405e1b4cc436a2668226b02450eb2 - - name: Build uses: ./.github/actions/openvic-dl-build with: identifier: ${{ matrix.identifier }} + preset: ${{ matrix.preset }} + configuration: ${{ matrix.configuration }} target: ${{ matrix.target }} - platform: ${{ matrix.platform }} - arch: ${{ matrix.arch }} compliance-type: ${{ matrix.compliance_type || 'loose' }} - - - name: Run tests - run: | - ./tests/bin/openvic-dataloader.tests.${{ matrix.platform }}.${{ matrix.target }}.${{ matrix.arch }}${{ matrix.test-bin-suffix || '' }} diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 1e28255..8467dc8 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -25,7 +25,6 @@ jobs: - name: Checkout project uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - submodules: recursive fetch-depth: 0 # Treeless clone. Slightly less performant than a shallow clone, but makes finding diffs instantaneous. filter: tree:0 # See: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/ persist-credentials: false diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index b591e62..49e96c7 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -60,44 +60,37 @@ jobs: - identifier: windows-release os: windows-latest name: 🏁 Build Windows - target: template_release - platform: windows - arch: x86_64 - scons-flags: '' + preset: windows-x64-md + cmake-args: '' - identifier: macos-release os: macos-latest name: 🍎 Build macOS - target: template_release - platform: macos - arch: universal - scons-flags: lto=full + preset: macos-universal + cmake-args: -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON - identifier: linux-release os: ubuntu-latest name: 🐧 Build Linux runner: ubuntu-22.04 - target: template_release - platform: linux - arch: x86_64 - scons-flags: lto=full use_static_cpp=yes + preset: linux-x64 + cmake-args: -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON steps: - name: Checkout project uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - submodules: recursive persist-credentials: false - name: Build uses: ./.github/actions/openvic-dl-build with: identifier: ${{ matrix.identifier }} - target: ${{ matrix.target }} - platform: ${{ matrix.platform }} - arch: ${{ matrix.arch }} - disable-cache: true - scons-flags: use_hot_reload=no build_ovdl_tests=no ${{ matrix.scons-flags }} + preset: ${{ matrix.preset }} + configuration: Release + target: template_release + run-tests: false + cmake-args: -DOPENVIC_DL_BUILD_TESTS=OFF ${{ matrix.cmake-args }} publish-release: name: Publish Release diff --git a/.gitignore b/.gitignore index 00cc4b5..7263263 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,6 @@ *.o *.obj -# Precompiled Headers -*.gch -*.pch - # Compiled Dynamic libraries *.so *.dylib @@ -45,7 +41,6 @@ # Godot 4+ specific ignores .godot/ game/bin/openvic/* -.sconsign*.dblite # Binaries *.o @@ -54,7 +49,6 @@ game/bin/openvic/* *.obj *.bc *.pyc -*.dblite *.pdb *.lib bin/* @@ -66,11 +60,6 @@ bin/* *.idb *.exp -tests/bin/* - -# Build configuarion. -/custom.py - # MacOS stuff .DS_Store @@ -79,5 +68,6 @@ tests/bin/* compile_commands.json -# Out-of-source build directory -/build/ \ No newline at end of file +# CMake out-of-source build directory +out/ +CMakeUserPresets.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 27e9773..0000000 --- a/.gitmodules +++ /dev/null @@ -1,26 +0,0 @@ -[submodule "deps/lexy"] - path = deps/lexy - url = https://github.com/foonathan/lexy - ignore = dirty -[submodule "scripts"] - path = scripts - url = https://github.com/OpenVicProject/scripts -[submodule "deps/dryad"] - path = deps/dryad - url = https://github.com/Spartan322/dryad -[submodule "deps/fmt"] - path = deps/fmt - url = https://github.com/fmtlib/fmt - ignore = dirty -[submodule "deps/range-v3"] - path = deps/range-v3 - url = https://github.com/spartan322/range-v3 - ignore = dirty -[submodule "tests/deps/snitch"] - path = tests/deps/snitch - url = https://github.com/snitch-org/snitch - ignore = dirty -[submodule "deps/vmcontainer"] - path = deps/vmcontainer - url = https://github.com/spartan322/vmcontainer - ignore = dirty diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79dfe2f..9ef9582 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,10 +33,10 @@ repos: hooks: - id: ruff-check args: [--fix] - files: (\.py|SConstruct|SCsub)$ + files: \.py$ types_or: [text] - id: ruff-format - files: (\.py|SConstruct|SCsub)$ + files: \.py$ types_or: [text] - repo: https://github.com/crate-ci/typos diff --git a/.vscode/launch.json b/.vscode/launch.json index 5db6fd5..de224d1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,27 +8,27 @@ "type": "cppdbg", "request": "launch", "name": "Debug", - "program": "${workspaceFolder}/bin/openvic-dataloader.headless.linux.template_debug.dev.x86_64", + "program": "${workspaceFolder}/out/build/linux-x64/bin/Debug/openvic-dataloader.headless", "args": ["csv", "./output.csv"], - "cwd": "${workspaceFolder}/bin", - "preLaunchTask": "dev_build", + "cwd": "${workspaceFolder}/out/build/linux-x64/bin/Debug", + "preLaunchTask": "build", "windows": { - "type": "cppvsdb", + "type": "cppvsdbg", "request": "launch", "name": "Debug", - "program": "${workspaceFolder}\\bin\\openvic-dataloader.headless.windows.template_debug.dev.x86_64", + "program": "${workspaceFolder}\\out\\build\\windows-x64-md\\bin\\Debug\\openvic-dataloader.headless.exe", "args": ["csv", "./output.csv"], - "cwd": "${workspaceFolder}\\bin", - "preLaunchTask": "dev_build", + "cwd": "${workspaceFolder}\\out\\build\\windows-x64-md\\bin\\Debug", + "preLaunchTask": "build", }, "osx": { - "type": "cppvsdb", + "type": "cppdbg", "request": "launch", "name": "Debug", - "program": "", // TODO: Mac executable? - "args": [], - "cwd": "${workspaceFolder}\\game", - "preLaunchTask": "dev_build", + "program": "${workspaceFolder}/out/build/macos-universal/bin/Debug/openvic-dataloader.headless", + "args": ["csv", "./output.csv"], + "cwd": "${workspaceFolder}/out/build/macos-universal/bin/Debug", + "preLaunchTask": "build", } } ] diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 65e62ec..4a75a9d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,28 +4,28 @@ "version": "2.0.0", "tasks": [ { - "label": "build", + "label": "configure", "group": "build", "type": "shell", - "command": "scons", + "command": "cmake", "args": [ - // enable for debugging with breakpoints - //"dev_build=yes", + "--preset", + "windows-x64-md" ], "problemMatcher": "$msCompile" }, { - "label": "dev_build", + "label": "build", "group": "build", "type": "shell", - "command": "scons", + "command": "cmake", "args": [ - // enable for debugging with breakpoints - "dev_build=yes", - "debug_symbols=yes" + "--build", + "--preset", + "windows-x64-md-debug" ], "dependsOn": [ - "build" + "configure" ], "problemMatcher": "$msCompile" }, @@ -33,9 +33,13 @@ "label": "clean", "group": "build", "type": "shell", - "command": "scons", + "command": "cmake", "args": [ - "--clean" + "--build", + "--preset", + "windows-x64-md-debug", + "--target", + "clean" ], "problemMatcher": "$msCompile" }, @@ -50,4 +54,4 @@ "problemMatcher": "$msCompile" } ] -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8c5feed --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,179 @@ +cmake_minimum_required(VERSION 3.28) +project(openvic-dataloader LANGUAGES CXX) + +if(NOT COMMAND openvic_setup_base_flags) + # scripts is the shared build-tooling repo, fetched once as a pinned + # tarball (like the other third-party deps). In a composed build the + # outermost repo fetches + loads it first and this guard skips for the + # nested repos; a standalone repo fetches it itself. FetchContent also + # dedups by name, so either path yields exactly one fetch. + # + # Raw FetchContent (not openvic_declare_dep) on purpose: openvic_declare_dep + # lives INSIDE scripts (OpenVicDeps.cmake), so it isn't defined yet here. + # Local-dev escape hatch: -DFETCHCONTENT_SOURCE_DIR_OPENVIC_SCRIPTS= + # points this at a working-tree scripts checkout. + include(FetchContent) + FetchContent_Declare( + openvic_scripts + URL "https://github.com/OpenVicProject/scripts/archive/8f83cabf147de7d8a511b4aaefd137777c4eb9c8.tar.gz" + URL_HASH SHA256=5f9b1ff9e985e63be1b11fe8ba573023afb26c8e2811961f88c5ad2b8ac283da + ) + FetchContent_MakeAvailable(openvic_scripts) + include("${openvic_scripts_SOURCE_DIR}/cmake/OpenVicScripts.cmake") +endif() +openvic_setup_base_flags() +openvic_disable_rtti() + +set(OPENVIC_DATALOADER_COMPLIANCE + "loose" + CACHE STRING + "Type of encoding compliance to build with (loose|error_replace|error)" +) +set_property(CACHE OPENVIC_DATALOADER_COMPLIANCE PROPERTY STRINGS "loose;error_replace;error") + +# Third-party deps are fetched as pinned tarballs (see OpenVicDeps.cmake) with +# EXCLUDE_FROM_ALL so their install rules stay out of `cmake --install` +# (several of these projects have no off switch for their installs). +set(DRYAD_BUILD_TESTS OFF) +openvic_declare_dep(dryad + REPO Spartan322/dryad + SHA 0140ce828c1215f023d3c73651bc0aa4b02c67d6 + SHA256 9567df8b657e6461db48aefdd800382311956b2eda4921ae842450f65dcaed84 +) +FetchContent_MakeAvailable(dryad) +if(CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") + # clang + MSVC STL defines _MSC_VER, so dryad's builtin_clzll shim takes + # the MSVC branch, but DRYAD_FORCE_INLINE resolves to + # [[gnu::always_inline]] there -- an attribute with no inline linkage -> + # duplicate symbols at link. __forceinline carries linkage like cl.exe. + # (Upstream dryad bug; the macro is designed to be pre-definable.) + target_compile_definitions(dryad INTERFACE DRYAD_FORCE_INLINE=__forceinline) +endif() + +set(FMT_INSTALL OFF) +openvic_declare_dep(fmt + REPO fmtlib/fmt + SHA 40626af88bd7df9a5fb80be7b25ac85b122d6c21 + SHA256 992216a0605e03f0373984ecad11158f42d8569782f1b2c84035272da10f0ff1 +) +FetchContent_MakeAvailable(fmt) + +# lexy is declared under the same FetchContent name by lexy-vdf too; the first +# declaration wins globally (replacing the old `if(NOT TARGET lexy_file)` +# guard). In the composed build dataloader is added first, so its pin is used. +set(LEXY_ENABLE_INSTALL OFF) +openvic_declare_dep(lexy + REPO foonathan/lexy + SHA 34d2adf74a2b25b6bdd760a3bbb931f3fd5e60cd + SHA256 a45a706f15d565b900280f58e1bd3492020a7103b9d6abf7f54cd51509f8c859 +) +FetchContent_MakeAvailable(lexy) +# Build lexy's file.cpp with the unicode database enabled; upstream lexy only +# puts the define on the lexy_unicode INTERFACE target. +target_compile_definitions(lexy_file PRIVATE LEXY_HAS_UNICODE_DATABASE=1) + +set(RANGE_V3_TESTS OFF) +set(RANGE_V3_EXAMPLES OFF) +set(RANGE_V3_PERF OFF) +set(RANGE_V3_DOCS OFF) +openvic_declare_dep(range-v3 + REPO spartan322/range-v3 + SHA 96b8c210ca9c783caaac3a50bb508600e28c9247 + SHA256 fc8e9ce8e0baf54e68a7259e357674ace8d12c552c503ee9206434bfd0a1ea64 +) +FetchContent_MakeAvailable(range-v3) + +# vmcontainer's build lives in its lib/ subdir (SOURCE_SUBDIR); the repo root +# CMakeLists is not what we build. +openvic_declare_dep(vmcontainer + REPO spartan322/vmcontainer + SHA f40ae3d6a9385f59000457fb186e34e730baba03 + SHA256 13d35f7aa50f97f88413763fa644e08f5ec72450bd1c2f63709985a41d41824d + SOURCE_SUBDIR lib +) +FetchContent_MakeAvailable(vmcontainer) + +file(GLOB_RECURSE dataloader_sources CONFIGURE_DEPENDS src/openvic-dataloader/*.cpp) + +add_library(openvic-dataloader STATIC ${dataloader_sources}) +add_library(openvic::dataloader ALIAS openvic-dataloader) + +set(ovdl_gen_dir ${CMAKE_CURRENT_BINARY_DIR}/gen-include) +target_include_directories( + openvic-dataloader + PUBLIC include $ + PRIVATE src/openvic-dataloader +) + +# Compile-time project info headers, included as . +openvic_generate_commit_info( + TARGET openvic-dataloader + PREFIX ovdl + REPO_DIR ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT ${ovdl_gen_dir}/openvic-dataloader/gen/commit_info.gen.hpp +) +openvic_generate_license_info( + TARGET openvic-dataloader + PREFIX ovdl + COPYRIGHT ${CMAKE_CURRENT_SOURCE_DIR}/COPYRIGHT + LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE + OUTPUT ${ovdl_gen_dir}/openvic-dataloader/gen/license_info.gen.hpp +) +openvic_generate_author_info( + TARGET openvic-dataloader + PREFIX ovdl + AUTHORS ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS.md + OUTPUT ${ovdl_gen_dir}/openvic-dataloader/gen/author_info.gen.hpp + SECTIONS + "Senior Developers=AUTHORS_SENIOR_DEVELOPERS" + "Developers=AUTHORS_DEVELOPERS" + "Contributors=AUTHORS_CONTRIBUTORS" + "Consultants=AUTHORS_CONSULTANTS" +) +# PUBLIC deps appear in the public headers (dryad, fmt, range-v3, vmcontainer); +# lexy is an implementation detail and stays private. +target_link_libraries( + openvic-dataloader + PUBLIC foonathan::dryad fmt::fmt range-v3::range-v3 vmcontainer::vmcontainer + PRIVATE foonathan::lexy +) +if(APPLE) + # ParseHandler's system-encoding detection uses CoreFoundation and the GBK + # converter uses iconv. PUBLIC: executables linking this static library + # need them on their own link lines. + target_link_libraries(openvic-dataloader PUBLIC "-framework CoreFoundation" iconv) +endif() +set_target_properties(openvic-dataloader PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") + +if(OPENVIC_DATALOADER_COMPLIANCE STREQUAL "error_replace") + # PUBLIC: the unit tests (and any consumer) adjust their expectations to + # the compliance mode via this macro, so it must propagate. + target_compile_definitions(openvic-dataloader PUBLIC OPENVIC_DATALOADER_ENCODING_COMPLIANCE=1) +elseif(OPENVIC_DATALOADER_COMPLIANCE STREQUAL "error") + target_compile_definitions(openvic-dataloader PUBLIC OPENVIC_DATALOADER_ENCODING_COMPLIANCE=2) +endif() + +# Headless executable and unit tests: built by default only when +# openvic-dataloader is the top-level project (composed builds just want the +# library). +option(OPENVIC_DL_BUILD_HEADLESS "Build the openvic-dataloader headless executable" ${PROJECT_IS_TOP_LEVEL}) +option(OPENVIC_DL_BUILD_TESTS "Build the openvic-dataloader unit tests" ${PROJECT_IS_TOP_LEVEL}) + +if(OPENVIC_DL_BUILD_HEADLESS) + file(GLOB_RECURSE ovdl_headless_sources CONFIGURE_DEPENDS src/headless/*.cpp) + add_executable(openvic-dataloader-headless ${ovdl_headless_sources}) + target_compile_definitions(openvic-dataloader-headless PRIVATE OPENVIC_DATALOADER_HEADLESS) + target_include_directories(openvic-dataloader-headless PRIVATE src/headless) + target_link_libraries(openvic-dataloader-headless PRIVATE openvic::dataloader) + set_target_properties( + openvic-dataloader-headless + PROPERTIES + OUTPUT_NAME "openvic-dataloader.headless" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$" + ) +endif() + +if(OPENVIC_DL_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..54856a6 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,183 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 27 + }, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "generator": "Ninja Multi-Config", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_CONFIGURATION_TYPES": "Release;RelWithDebInfo;Debug" + } + }, + { + "name": "p-windows-x64", + "hidden": true, + "inherits": "base", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "architecture": { + "value": "x64", + "strategy": "external" + } + }, + { + "name": "windows-x64-md", + "inherits": "p-windows-x64", + "cacheVariables": { + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL" + } + }, + { + "name": "windows-x64-mt", + "inherits": "p-windows-x64", + "cacheVariables": { + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded" + } + }, + { + "name": "linux-x64", + "inherits": "base", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "cacheVariables": { + "CMAKE_CXX_COMPILER": "g++" + } + }, + { + "name": "macos-universal", + "inherits": "base", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "x86_64;arm64" + } + } + ], + "buildPresets": [ + { + "name": "windows-x64-md-release", + "configurePreset": "windows-x64-md", + "configuration": "Release" + }, + { + "name": "windows-x64-md-debug", + "configurePreset": "windows-x64-md", + "configuration": "Debug" + }, + { + "name": "windows-x64-md-relwithdebinfo", + "configurePreset": "windows-x64-md", + "configuration": "RelWithDebInfo" + }, + { + "name": "windows-x64-mt-release", + "configurePreset": "windows-x64-mt", + "configuration": "Release" + }, + { + "name": "windows-x64-mt-debug", + "configurePreset": "windows-x64-mt", + "configuration": "Debug" + }, + { + "name": "windows-x64-mt-relwithdebinfo", + "configurePreset": "windows-x64-mt", + "configuration": "RelWithDebInfo" + }, + { + "name": "linux-x64-release", + "configurePreset": "linux-x64", + "configuration": "Release" + }, + { + "name": "linux-x64-debug", + "configurePreset": "linux-x64", + "configuration": "Debug" + }, + { + "name": "linux-x64-relwithdebinfo", + "configurePreset": "linux-x64", + "configuration": "RelWithDebInfo" + }, + { + "name": "macos-universal-release", + "configurePreset": "macos-universal", + "configuration": "Release" + }, + { + "name": "macos-universal-debug", + "configurePreset": "macos-universal", + "configuration": "Debug" + }, + { + "name": "macos-universal-relwithdebinfo", + "configurePreset": "macos-universal", + "configuration": "RelWithDebInfo" + } + ], + "testPresets": [ + { + "name": "windows-x64-md-debug", + "configurePreset": "windows-x64-md", + "configuration": "Debug", + "output": { "outputOnFailure": true } + }, + { + "name": "windows-x64-md-release", + "configurePreset": "windows-x64-md", + "configuration": "Release", + "output": { "outputOnFailure": true } + }, + { + "name": "windows-x64-mt-debug", + "configurePreset": "windows-x64-mt", + "configuration": "Debug", + "output": { "outputOnFailure": true } + }, + { + "name": "windows-x64-mt-release", + "configurePreset": "windows-x64-mt", + "configuration": "Release", + "output": { "outputOnFailure": true } + }, + { + "name": "linux-x64-debug", + "configurePreset": "linux-x64", + "configuration": "Debug", + "output": { "outputOnFailure": true } + }, + { + "name": "linux-x64-release", + "configurePreset": "linux-x64", + "configuration": "Release", + "output": { "outputOnFailure": true } + }, + { + "name": "macos-universal-debug", + "configurePreset": "macos-universal", + "configuration": "Debug", + "output": { "outputOnFailure": true } + }, + { + "name": "macos-universal-release", + "configurePreset": "macos-universal", + "configuration": "Release", + "output": { "outputOnFailure": true } + } + ] +} diff --git a/README.md b/README.md index 1fd6f1f..0d9f945 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,16 @@ Repo of the OpenVic-Dataloader Library for [OpenVic](https://github.com/OpenVicP For detailed instructions, view the OpenVic Contributor Quickstart Guide [here](https://github.com/OpenVicProject/OpenVic/blob/master/docs/contribution-quickstart-guide.md) ## Required -* [scons](https://scons.org/) +* [CMake](https://cmake.org/) 3.28+ +* [Ninja](https://ninja-build.org/) ## Build Instructions -1. Install [scons](https://scons.org/) for your system. -2. Run the command `git submodule update --init --recursive` to retrieve all related submodules. -3. Run `scons build_ovdl_library=yes` in the project root, you should see a libopenvic-dataloader file in `bin`. +1. Pick a configure preset from `CMakePresets.json` (`windows-x64-md`, `windows-x64-mt`, `linux-x64`, `macos-universal`). +2. Run `cmake --preset ` in the project root (dependencies are fetched automatically; no submodules needed). +3. Run `cmake --build --preset -debug` (or `-release`). The static library, headless executable, and unit tests land in `out/build//bin//`. +4. Run the tests with `ctest --preset -debug`. -## Link Instructions -1. Call `ovdl_env = SConscript("openvic-dataloader/SConstruct")` -2. Use the values stored in the `ovdl_env.openvic_dataloader` to link and compile against: +The headless executable and tests are built by default in standalone builds; disable with `-DOPENVIC_DL_BUILD_HEADLESS=OFF` / `-DOPENVIC_DL_BUILD_TESTS=OFF`. Encoding compliance is selected with `-DOPENVIC_DATALOADER_COMPLIANCE=`. -| Variable Name | Description | Correlated ENV variable | -| --- | --- | --- | -| `LIBPATH` | Library path list | `env["LIBPATH"]` | -| `LIBS` | Library files names in the library paths | `env["LIBS"]` | -| `INCPATH` | Library include files | `env["CPPPATH"]` | +## Link Instructions +Use CMake: `add_subdirectory(openvic-dataloader)` and link against `openvic::dataloader`. diff --git a/SConstruct b/SConstruct deleted file mode 100644 index e760dbd..0000000 --- a/SConstruct +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python - -import os - -BINDIR = "bin" - -env = SConscript("scripts/SConstruct") - -env.PrependENVPath("PATH", os.getenv("PATH")) - -opts = env.SetupOptions() - -opts.Add(BoolVariable("build_ovdl_tests", "Build and run the openvic dataloader tests", env.is_standalone)) -opts.Add(BoolVariable("run_ovdl_tests", "Run the openvic dataloader tests", False)) -opts.Add( - BoolVariable( - "build_ovdl_library", - "Build the openvic dataloader library.", - env.get("build_ovdl_library", not env.is_standalone), - ) -) -opts.Add(BoolVariable("build_ovdl_headless", "Build the openvic dataloader headless executable", env.is_standalone)) -opts.Add( - EnumVariable( - "compliance_type", "Type of encoding compliance to build with", "loose", ("loose", "error_replace", "error") - ) -) - -env.FinalizeOptions() - -suffix = ".{}.{}".format(env["platform"], env["target"]) -if env.dev_build: - suffix += ".dev" -if env["precision"] == "double": - suffix += ".double" -suffix += "." + env["arch"] -if env["platform"] == "windows": - if env.get("debug_crt", False): - suffix += ".mdd" - elif env.get("use_static_cpp", False): - suffix += ".mt" - else: - suffix += ".md" -if env.get("use_asan", False): - suffix += ".san" -env["suffix"] = suffix - -build_dir = env.Dir("build/" + suffix.lstrip(".")).abspath.replace("\\", "/") -env["build_dir"] = build_dir - -env.exposed_includes = [] - -SConscript("deps/SCsub", "env") - -env.openvic_dataloader = {} - -# For the reference: -# - CCFLAGS are compilation flags shared between C and C++ -# - CFLAGS are for C-specific compilation flags -# - CXXFLAGS are for C++-specific compilation flags -# - CPPFLAGS are for pre-processor flags -# - CPPDEFINES are for pre-processor defines -# - LINKFLAGS are for linking flags - -# tweak this if you want to use different folders, or more folders, to store your source code in. -source_path = "src/openvic-dataloader" -include_path = "include" -# Out-of-source build: variant tree holds object files only, not copies of the -# source. Compile diagnostics therefore reference original source paths. -dataloader_variant = build_dir + "/" + source_path # forward slashes so VariantDir matches -dataloader_variant_parent = build_dir + "/" + include_path # variant of "src/" -env.VariantDir(dataloader_variant, source_path, duplicate=False) - -env.Append(CPPPATH=[[env.Dir(p) for p in [dataloader_variant, dataloader_variant_parent, source_path, include_path]]]) - -gen_commit_info = env.CommandNoCache( - dataloader_variant_parent + "/openvic-dataloader/gen/commit_info.gen.hpp", - env.Value(env.get_git_info("ovdl")), - env.Run(env.git_builder), - name_prefix="ovdl", -) -gen_license_info = env.CommandNoCache( - dataloader_variant_parent + "/openvic-dataloader/gen/license_info.gen.hpp", - ["COPYRIGHT", "LICENSE"], - env.Run(env.license_builder), - name_prefix="ovdl", -) -gen_author_info = env.CommandNoCache( - dataloader_variant_parent + "/openvic-dataloader/gen/author_info.gen.hpp", - "AUTHORS.md", - env.Run(env.author_builder), - name_prefix="ovdl", - sections={ - "Senior Developers": "AUTHORS_SENIOR_DEVELOPERS", - "Developers": "AUTHORS_DEVELOPERS", - "Contributors": "AUTHORS_CONTRIBUTORS", - "Consultants": "AUTHORS_CONSULTANTS", - }, -) -gen_files = gen_commit_info + gen_license_info + gen_author_info -Default(gen_commit_info, gen_license_info, gen_author_info) - -sources = env.GlobRecursiveVariant("*.cpp", source_path, dataloader_variant) -env.dataloader_sources = sources - -library = None -env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"] -library_name = "libopenvic-dataloader{}{}".format(suffix, env["LIBSUFFIX"]) - -default_args = [] - -match env["compliance_type"]: - case "error_replace": - env.Append(CPPDEFINES=[("OPENVIC_DATALOADER_ENCODING_COMPLIANCE", 1)]) - case "error": - env.Append(CPPDEFINES=[("OPENVIC_DATALOADER_ENCODING_COMPLIANCE", 2)]) - -if env["run_ovdl_tests"]: - env["build_ovdl_tests"] = True - -if env["build_ovdl_tests"]: - env["build_ovdl_library"] = True - -if env["build_ovdl_library"]: - library = env.StaticLibrary(target=os.path.join(BINDIR, library_name), source=sources) - default_args += [library] - - env.Append(LIBPATH=[env.Dir(BINDIR)]) - env.Prepend(LIBS=[library_name]) - - env.openvic_dataloader["LIBPATH"] = env["LIBPATH"] - env.openvic_dataloader["LIBS"] = env["LIBS"] - # Variant parent for generated headers (gen/*.gen.hpp); source parent for - # authored headers (MSVC's preprocessor needs both physically in -I). - env.openvic_dataloader["INCPATH"] = [ - env.Dir(dataloader_variant_parent), - env.Dir(include_path), - ] + env.exposed_includes - env.openvic_dataloader["GEN_FILES"] = gen_files - -headless_program = None -env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"] - -if env["build_ovdl_headless"]: - headless_name = "openvic-dataloader" - headless_env = env.Clone() - headless_src = "src/headless" - headless_variant = build_dir + "/" + headless_src - headless_env.VariantDir(headless_variant, headless_src, duplicate=False) - headless_env.Append(CPPDEFINES=["OPENVIC_DATALOADER_HEADLESS"]) - headless_env.Append(CPPPATH=[headless_env.Dir(headless_variant), headless_env.Dir(headless_src)]) - headless_env.headless_sources = env.GlobRecursiveVariant("*.cpp", headless_src, headless_variant) - if not env["build_ovdl_library"]: - headless_env.headless_sources += sources - headless_program = headless_env.Program( - target=os.path.join(BINDIR, headless_name), - source=headless_env.headless_sources, - PROGSUFFIX=".headless" + env["PROGSUFFIX"], - ) - default_args += [headless_program] - -if env["build_ovdl_tests"]: - tests_env = SConscript("tests/SCsub", "env") - - if env["run_ovdl_tests"]: - tests_env.RunUnitTest() - -# Add compiledb if the option is set -if env.get("compiledb", False): - default_args += ["compiledb"] - -Default(*default_args) - -if "env" in locals(): - # FIXME: This method mixes both cosmetic progress stuff and cache handling... - env.show_progress(env) - -Return("env") diff --git a/deps/SCsub b/deps/SCsub deleted file mode 100644 index 8d50a22..0000000 --- a/deps/SCsub +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env python - -Import("env") - - -def build_lexy(env): - env.Append(CPPDEFINES=["LEXY_HAS_UNICODE_DATABASE=1"]) - lexy_env = env.Clone() - - # Require C++20 - if lexy_env.get("is_msvc", False): - lexy_env.Append(CXXFLAGS=["/std:c++20"]) - - lexy_env.Append(CXXFLAGS=["/WX", "/W3", "/D", "_CRT_SECURE_NO_WARNINGS"]) - if not lexy_env.get("use_clang_cl"): - lexy_env.Append(CXXFLAGS=["/wd5105"]) - else: - lexy_env.Append(CXXFLAGS=["-std=c++20"]) - - lexy_env.Append( - CXXFLAGS=["-pedantic-errors", "-Werror", "-Wall", "-Wextra", "-Wconversion", "-Wsign-conversion"] - ) - if lexy_env["CXX"] == "clang++": - lexy_env.Append(CXXFLAGS=["-Wno-shift-op-parentheses", "-Wno-parentheses-equality"]) - else: - lexy_env.Append( - CXXFLAGS=[ - "-Wno-parentheses", - "-Wno-unused-local-typedefs", - "-Wno-array-bounds", # , "-Wno-maybe-uninitialized", "-Wno-restrict" - ] - ) - - include_path = "lexy/include" - source_path = "lexy/src" - lexy_env.Append(CPPPATH=[[lexy_env.Dir(p) for p in [source_path, include_path]]]) - # Mirror lexy's source tree into the per-config build dir. - build_root = (env.get("build_dir") or env.Dir("#").abspath).replace("\\", "/") - lexy_out = build_root + "/lexy/" + source_path - lexy_env.VariantDir(lexy_out, source_path, duplicate=True) - sources = env.GlobRecursive("*.cpp", [lexy_out]) - env.lexy_sources = sources - - library_name = "liblexy_file" + env.get("suffix", "") + env["LIBSUFFIX"] - library = lexy_env.StaticLibrary(target=lexy_out + "/" + library_name, source=sources) - Default(library) - - include_dir = lexy_env.Dir(include_path) - env.Append(CPPPATH=[include_dir]) - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"]) - else: - env.Append(CXXFLAGS=["-isystem", include_dir]) - env.Append(CXXFLAGS=[""]) - env.Append(LIBPATH=[lexy_env.Dir(lexy_out)]) - env.Prepend(LIBS=[library_name]) - - -def build_dryad(env): - include_path = "dryad/include" - include_dir = env.Dir(include_path) - env.dryad = {} - env.dryad["INCPATH"] = [include_dir] - env.Append(CPPPATH=env.dryad["INCPATH"]) - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"]) - else: - env.Append(CXXFLAGS=["-isystem", include_dir]) - - env.exposed_includes += env.dryad["INCPATH"] - - -def build_fmt(env): - fmt_env = env.Clone() - - # Require C++20 - if fmt_env.get("is_msvc", False): - fmt_env.Append(CXXFLAGS=["/std:c++20"]) - - fmt_env.Append(CXXFLAGS=["/WX", "/W3", "/D", "_CRT_SECURE_NO_WARNINGS"]) - else: - fmt_env.Append(CXXFLAGS=["-std=c++20"]) - - fmt_env.Append(CXXFLAGS=["-Werror", "-Wall", "-Wextra", "-pedantic", "-Wconversion", "-Wundef"]) - if fmt_env["CXX"] == "clang++": - fmt_env.Append(CXXFLAGS=["-Wweak-vtables", "-Wshadow", "-Wno-gnu-zero-variadic-macro-arguments"]) - else: - fmt_env.Append( - CXXFLAGS=[ - "-Wold-style-cast", - "-Wundef", - "-Wredundant-decls", - "-Wwrite-strings", - "-Wpointer-arith", - "-Wcast-qual", - "-Wformat=2", - "-Wmissing-include-dirs", - "-Wcast-align", - "-Wctor-dtor-privacy", - "-Wdisabled-optimization", - "-Winvalid-pch", - "-Woverloaded-virtual", - "-Wconversion", - "-Wundef", - "-Wno-ctor-dtor-privacy", - "-Wno-format-nonliteral", - "-Wno-dangling-else", - "-Wno-unused-local-typedefs", - "-Wdouble-promotion", - "-Wtrampolines", - "-Wzero-as-null-pointer-constant", - "-Wuseless-cast", - "-Wvector-operation-performance", - "-Wsized-deallocation", - "-Wshadow", - "-Wshift-overflow=2", - "-Wnull-dereference", - "-Wduplicated-cond", - ] - ) - - include_path = "fmt/include" - source_path = "fmt/src" - paths = [include_path, source_path] - fmt_env.Append(CPPPATH=[[fmt_env.Dir(p) for p in paths]]) - # Mirror fmt's source tree into the per-config build dir. - build_root = (env.get("build_dir") or env.Dir("#").abspath).replace("\\", "/") - fmt_out = build_root + "/fmt/" + source_path - fmt_env.VariantDir(fmt_out, source_path, duplicate=True) - sources = env.GlobRecursive("*.cc", [fmt_out], fmt_out + "/fmt.cc") - env.lexy_sources = sources - - library_name = "libfmt" + env.get("suffix", "") + env["LIBSUFFIX"] - library = fmt_env.StaticLibrary(target=fmt_out + "/" + library_name, source=sources) - Default(library) - - include_dir = fmt_env.Dir(include_path) - - env.fmt = {} - env.fmt["INCPATH"] = [include_dir] - - env.Append(CPPPATH=env.fmt["INCPATH"]) - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"]) - else: - env.Append(CXXFLAGS=["-isystem", include_dir]) - env.Append(CXXFLAGS=[""]) - env.Append(LIBPATH=[fmt_env.Dir(fmt_out)]) - env.Prepend(LIBS=[library_name]) - - env.exposed_includes += env.fmt["INCPATH"] - - -def build_range_v3(env): - include_path = "range-v3/include" - sources = env.GlobRecursive("*.cpp", [include_path]) - env.range_v3_sources = sources - - include_dir = env.Dir(include_path) - - env.range_v3 = {} - env.range_v3["INCPATH"] = [include_dir] - - env.Append(CPPPATH=env.range_v3["INCPATH"]) - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"]) - else: - env.Append(CXXFLAGS=["-isystem", include_dir]) - - env.exposed_includes += env.range_v3["INCPATH"] - - -def build_vmcontainer(env): - vmcontainer_env = env.Clone() - - include_path = "vmcontainer/lib/include" - source_path = "vmcontainer/lib/src" - paths = [include_path, source_path] - vmcontainer_env.Append(CPPPATH=[[vmcontainer_env.Dir(p) for p in paths]]) - # Mirror vmcontainer's source tree into the per-config build dir. - build_root = (env.get("build_dir") or env.Dir("#").abspath).replace("\\", "/") - vmcontainer_out = build_root + "/vmcontainer/" + source_path - vmcontainer_env.VariantDir(vmcontainer_out, source_path, duplicate=True) - sources = env.GlobRecursive("*.cpp", [vmcontainer_out]) - env.vmcontainer_sources = sources - - library_name = "libvmcontainer" + env.get("suffix", "") + env["LIBSUFFIX"] - library = vmcontainer_env.StaticLibrary(target=vmcontainer_out + "/" + library_name, source=sources) - Default(library) - - include_dir = vmcontainer_env.Dir(include_path) - - env.vmcontainer = {} - env.vmcontainer["INCPATH"] = [include_dir] - - env.Append(CPPPATH=env.vmcontainer["INCPATH"]) - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"]) - else: - env.Append(CXXFLAGS=["-isystem", include_dir]) - env.Append(CXXFLAGS=[""]) - env.Append(LIBPATH=[vmcontainer_env.Dir(vmcontainer_out)]) - env.Prepend(LIBS=[library_name]) - - env.exposed_includes += env.vmcontainer["INCPATH"] - - -build_dryad(env) -build_fmt(env) -build_lexy(env) -build_range_v3(env) -build_vmcontainer(env) diff --git a/deps/dryad b/deps/dryad deleted file mode 160000 index 0140ce8..0000000 --- a/deps/dryad +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0140ce828c1215f023d3c73651bc0aa4b02c67d6 diff --git a/deps/fmt b/deps/fmt deleted file mode 160000 index 40626af..0000000 --- a/deps/fmt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 40626af88bd7df9a5fb80be7b25ac85b122d6c21 diff --git a/deps/lexy b/deps/lexy deleted file mode 160000 index 34d2adf..0000000 --- a/deps/lexy +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 34d2adf74a2b25b6bdd760a3bbb931f3fd5e60cd diff --git a/deps/range-v3 b/deps/range-v3 deleted file mode 160000 index 96b8c21..0000000 --- a/deps/range-v3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 96b8c210ca9c783caaac3a50bb508600e28c9247 diff --git a/deps/vmcontainer b/deps/vmcontainer deleted file mode 160000 index f40ae3d..0000000 --- a/deps/vmcontainer +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f40ae3d6a9385f59000457fb186e34e730baba03 diff --git a/pyproject.toml b/pyproject.toml index 21af159..ca23eba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,6 @@ namespace_packages = true explicit_package_bases = true [tool.ruff] -extend-include = ["SConstruct", "SCsub"] line-length = 120 target-version = "py310" @@ -20,12 +19,6 @@ extend-select = [ "I", # isort ] -[tool.ruff.lint.per-file-ignores] -"{SConstruct,SCsub}" = [ - "E402", # Module level import not at top of file - "F821", # Undefined name -] - [tool.typos] files.extend-exclude = [".mailmap", "*.gitignore", "*.po", "*.pot", "*.rc"] default.extend-ignore-re = [ diff --git a/scripts b/scripts deleted file mode 160000 index 9f8318f..0000000 --- a/scripts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9f8318fb9f34fc49709ad8227577438e488dc88b diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..8e5bd8b --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,33 @@ +# snitch honors these as plain variables (CMP0077 NEW via +# openvic_setup_base_flags). Only deltas from upstream defaults are set; +# everything else (SNITCH_DEFINE_MAIN, timings, reporters, ...) already +# matches upstream. Exceptions are additionally forced off at compile time by +# snitch itself when _HAS_EXCEPTIONS=0 / -fno-exceptions is in effect. +set(SNITCH_WITH_EXCEPTIONS OFF) +set(SNITCH_WITH_MULTITHREADING OFF) +openvic_declare_dep(snitch + REPO snitch-org/snitch + SHA d6632123cc8d13bdbc5cd60fd6741b9e0f635e82 # v1.2.5+13 + SHA256 09fcd66cba6ab93cc9f43eee9b2d6c0988e6fb8791da9ab2eec612e951221db6 +) +FetchContent_MakeAvailable(snitch) + +file(GLOB_RECURSE ovdl_tests_sources CONFIGURE_DEPENDS src/*.cpp) + +add_executable(openvic-dataloader-tests ${ovdl_tests_sources}) +target_compile_definitions(openvic-dataloader-tests PRIVATE OPENVIC_DATALOADER_TESTS) +# Tests include private implementation headers (e.g. ), +# so add the library's src dir alongside the tests' own. +target_include_directories( + openvic-dataloader-tests + PRIVATE src "${CMAKE_CURRENT_SOURCE_DIR}/../src/openvic-dataloader" +) +target_link_libraries(openvic-dataloader-tests PRIVATE openvic::dataloader snitch::snitch) +set_target_properties( + openvic-dataloader-tests + PROPERTIES + OUTPUT_NAME "openvic-dataloader.tests" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$" +) + +add_test(NAME openvic-dataloader-tests COMMAND openvic-dataloader-tests) diff --git a/tests/SCsub b/tests/SCsub deleted file mode 100644 index 3b46107..0000000 --- a/tests/SCsub +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -import os -import subprocess - -from SCons.Script.SConscript import SConsEnvironment - - -def UnitTestPostAction(target=None, source=None, env=None): - print() - return subprocess.run([target[0].path]).returncode - - -def BuildUnitTest(env, **kwargs): - test = env.Program(**kwargs) - env.NoCache(test) - return test - - -def RunUnitTest(env): - unit_test_action = env.Action(UnitTestPostAction, None) - test_post_action = env.AddPostAction(env.unit_test, unit_test_action) - env.AlwaysBuild(test_post_action) - - -SConsEnvironment.BuildUnitTest = BuildUnitTest -SConsEnvironment.RunUnitTest = RunUnitTest - -Import("env") - -BINDIR = "bin" - -env.openvic_dataloader_tests = {} - -# For the reference: -# - CCFLAGS are compilation flags shared between C and C++ -# - CFLAGS are for C-specific compilation flags -# - CXXFLAGS are for C++-specific compilation flags -# - CPPFLAGS are for pre-processor flags -# - CPPDEFINES are for pre-processor defines -# - LINKFLAGS are for linking flags - -# tweak this if you want to use different folders, or more folders, to store your source code in. -source_path = "src" - -tests_name = "openvic-dataloader" -tests_env = env.Clone() -tests_env.Append(CPPDEFINES=["OPENVIC_DATALOADER_TESTS"]) -tests_env.Append(CPPPATH=[tests_env.Dir(source_path)]) -tests_env.tests_sources = env.GlobRecursive("*.cpp", [source_path]) - -SConscript("deps/SCsub", {"env": tests_env}) - -tests_env.unit_test = tests_env.BuildUnitTest( - source=tests_env.tests_sources, target=os.path.join(BINDIR, tests_name), PROGSUFFIX=".tests" + env["PROGSUFFIX"] -) -Default(tests_env.unit_test) - -Return("tests_env") diff --git a/tests/deps/SCsub b/tests/deps/SCsub deleted file mode 100644 index e4e1d73..0000000 --- a/tests/deps/SCsub +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/env python -import subprocess -from pathlib import Path - -Import("env") - - -def generate_snitch_config_header(target, source, env): - header = [] - - header.append("// THIS FILE IS GENERATED. EDITS WILL BE LOST.") - header.append("") - - header_file_path = Path(str(target[0])) - - include_gen_folder = Path(str(header_file_path.parent)) - include_gen_folder.mkdir(parents=True, exist_ok=True) - - header_guard = "SNITCH_CONFIG_HPP" - header.append(f"#ifndef {header_guard}") - header.append(f"#define {header_guard}") - header.append("") - header.append("#include // for C++ feature check macros") - - for key, val in env.config_data.items(): - header += ( - f""" -#if !defined({key}) -# define {key} {val} -#endif""" - ).split("\n") - - header += """ -#if defined(_MSC_VER) -# if defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) -# define SNITCH_EXCEPTIONS_NOT_AVAILABLE -# endif -#elif defined(__clang__) || defined(__GNUC__) -# if !defined(__EXCEPTIONS) -# define SNITCH_EXCEPTIONS_NOT_AVAILABLE -# endif -#endif - -#if defined(SNITCH_EXCEPTIONS_NOT_AVAILABLE) -# undef SNITCH_WITH_EXCEPTIONS -# define SNITCH_WITH_EXCEPTIONS 0 -#endif - -#if SNITCH_WITH_MULTITHREADING -# define SNITCH_THREAD_LOCAL thread_local -#else -# define SNITCH_THREAD_LOCAL -#endif - -#if !defined(__cpp_lib_bit_cast) -# undef SNITCH_CONSTEXPR_FLOAT_USE_BITCAST -# define SNITCH_CONSTEXPR_FLOAT_USE_BITCAST 0 -#endif - -#if (!defined(__cpp_lib_to_chars)) || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE <= 11) || \ - (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 14000) || \ - (defined(_MSC_VER) && _MSC_VER <= 1924) -# undef SNITCH_APPEND_TO_CHARS -# define SNITCH_APPEND_TO_CHARS 0 -#endif - -#if SNITCH_SHARED_LIBRARY -# if defined(_MSC_VER) -# if defined(SNITCH_EXPORTS) -# define SNITCH_EXPORT __declspec(dllexport) -# else -# define SNITCH_EXPORT __declspec(dllimport) -# endif -# elif defined(__clang__) || defined(__GNUC__) -# define SNITCH_EXPORT [[gnu::visibility("default")]] -# else -# define SNITCH_EXPORT -# endif -#else -# define SNITCH_EXPORT -#endif - """.split("\n") - - header.append("") - header.append(f"#endif // {header_guard}") - header.append("") - - with header_file_path.open("w+", encoding="utf-8") as header_file: - header_file.write("\n".join(header)) - - -def build_snitch(env): - major_version = 1 - minor_version = 2 - patch_version = 5 - git_run = subprocess.run(["git", "describe", "--tags", "--abbrev=0"], text=True, cwd="snitch/", capture_output=True) - if git_run.returncode == 0: - tag = git_run.stdout.strip().removeprefix("v").split(".") - major_version = tag[0] - minor_version = tag[1] - patch_version = tag[2] - - SHARED_BUILD = False - HEADER_ONLY = False - UNITY_BUILD = True - - SNITCH_VERSION = "{}.{}.{}".format(major_version, minor_version, patch_version) - - snitch_env = env.Clone() - - snitch_env.Append(BUILDERS={"GenerateSnitchConfig": snitch_env.Builder(action=generate_snitch_config_header)}) - - snitch_env.config_data = { - "SNITCH_MAX_TEST_CASES": 5000, # "Maximum number of test cases in a test application." - "SNITCH_MAX_NESTED_SECTIONS": 8, # "Maximum depth of nested sections in a test case." - "SNITCH_MAX_EXPR_LENGTH": 1024, # "Maximum length of a printed expression when reporting failure." - "SNITCH_MAX_MESSAGE_LENGTH": 1024, # "Maximum length of error or status messages." - "SNITCH_MAX_TEST_NAME_LENGTH": 1024, # "Maximum length of a test case name." - "SNITCH_MAX_TAG_LENGTH": 256, # "Maximum length of a test tag." - "SNITCH_MAX_CAPTURES": 8, # "Maximum number of captured expressions in a test case." - "SNITCH_MAX_CAPTURE_LENGTH": 256, # "Maximum length of a captured expression." - "SNITCH_MAX_UNIQUE_TAGS": 1024, # "Maximum number of unique tags in a test application." - "SNITCH_MAX_COMMAND_LINE_ARGS": 1024, # "Maximum number of command line arguments to a test application." - "SNITCH_MAX_REGISTERED_REPORTERS": 8, # "Maximum number of registered reporter that can be selected from the command line." - "SNITCH_MAX_PATH_LENGTH": 1024, # "Maximum length of a file path when writing output to file." - "SNITCH_MAX_REPORTER_SIZE_BYTES": 128, # "Maximum size (in bytes) of a reporter object." - "SNITCH_DEFINE_MAIN": 1, # "Define main() in snitch -- disable to provide your own main() function." - "SNITCH_WITH_EXCEPTIONS": 0, # "Use exceptions in snitch implementation -- will be forced OFF if exceptions are not available." - "SNITCH_WITH_MULTITHREADING": 0, # "Make the testing framework thread-safe -- disable if multithreading is not needed." - "SNITCH_WITH_TIMINGS": 1, # "Measure the time taken by each test case -- disable to speed up tests." - "SNITCH_WITH_SHORTHAND_MACROS": 1, # "Use short names for test macros -- disable if this causes conflicts." - "SNITCH_CONSTEXPR_FLOAT_USE_BITCAST": 1, # "Use std::bit_cast if available to implement exact constexpr float-to-string conversion." - "SNITCH_APPEND_TO_CHARS": 1, # "Use std::to_chars for string conversions -- disable for greater compatibility with a slight performance cost." - "SNITCH_DEFAULT_WITH_COLOR": 1, # "Enable terminal colors by default -- can also be controlled by command line interface." - "SNITCH_DECOMPOSE_SUCCESSFUL_ASSERTIONS": 0, # "Enable expression decomposition even for successful assertions -- more expensive." - "SNITCH_WITH_ALL_REPORTERS": 1, # "Allow all built-in reporters to be selected from the command line -- disable for faster compilation." - "SNITCH_WITH_TEAMCITY_REPORTER": 0, # "Allow the TeamCity reporter to be selected from the command line -- enable if needed." - "SNITCH_WITH_CATCH2_XML_REPORTER": 0, # "Allow the Catch2 XML reporter to be selected from the command line -- enable if needed." - "SNITCH_HEADER_ONLY": 0, # "Create a single-header header-only version of snitch." - "SNITCH_UNITY_BUILD": ( - "1" if UNITY_BUILD else "0" - ), # "Build sources as single file instead of separate files (faster full build)." - "SNITCH_DO_TEST": 1, # "Build tests." - } - - snitch_full_version = "" - git_run = subprocess.run(["git", "log", "-1", "--format=%h"], text=True, cwd="snitch/", capture_output=True) - if git_run.returncode == 0: - snitch_full_version = git_run.stdout.strip() - - snitch_full_version = SNITCH_VERSION + (".{}".format(snitch_full_version) if snitch_full_version else "") - - snitch_env.Append( - CPPDEFINES=[ - f'SNITCH_VERSION=\\"{SNITCH_VERSION}\\"', - f'SNITCH_FULL_VERSION=\\"{snitch_full_version}\\"', - f"SNITCH_VERSION_MAJOR={major_version}", - f"SNITCH_VERSION_MINOR={minor_version}", - f"SNITCH_VERSION_PATCH={patch_version}", - ] - ) - snitch_env.Append(CPPDEFINES=["SNITCH_SHARED_LIBRARY=" + ("1" if not HEADER_ONLY and SHARED_BUILD else "0")]) - - include_path = "snitch/include" - source_path = "snitch/src" - unity_source = "snitch.cpp" - - config = snitch_env.GenerateSnitchConfig( - snitch_env.File(Path(include_path) / "snitch" / "snitch_config.hpp"), "SCsub" - ) - - snitch_env.Append(CPPPATH=[[snitch_env.Dir(p) for p in [source_path, include_path]]]) - sources = snitch_env.GlobRecursive("*.cpp", [source_path], Path(source_path) / unity_source) - - if UNITY_BUILD: - sources = [snitch_env.File(Path(source_path) / unity_source)] - - env.snitch_sources = sources - - if not HEADER_ONLY: - library = None - project_name = "snitch" - library_name = "lib" + project_name + env["LIBSUFFIX"] - if SHARED_BUILD: - if snitch_env.get("is_msvc", False): - pass - else: - snitch_env.Append(CXXFLAGS=["-fvisibility=hidden", "-fvisibility-inlines-hidden"]) - - library = snitch_env.SharedLibrary(target=Path(source_path) / library_name, source=sources) - else: - library = snitch_env.StaticLibrary(target=Path(source_path) / library_name, source=sources) - env.Append(LIBPATH=[snitch_env.Dir(source_path)]) - env.Prepend(LIBS=[library_name]) - - Default([config, library]) - - env.Append(CPPPATH=[snitch_env.Dir(include_path)]) - else: - env.Append(CPPPATH=[[snitch_env.Dir(p) for p in [source_path, include_path]]]) - Default(config) - - -build_snitch(env) diff --git a/tests/deps/snitch b/tests/deps/snitch deleted file mode 160000 index d663212..0000000 --- a/tests/deps/snitch +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d6632123cc8d13bdbc5cd60fd6741b9e0f635e82