From d62bb4af660f5cb1703fed9c4748bbbb86733a36 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 17:43:07 -0800 Subject: [PATCH 1/8] Update CI/CD workflows to use Ubuntu 20.04 and enhance artifact installation process --- .github/workflows/highs-artifacts.yml | 2 +- .github/workflows/unix-build.yml | 33 ++++++++--------- .github/workflows/unix-ci.yml | 2 +- .github/workflows/unix-release.yml | 2 +- .github/workflows/win-build.yml | 23 +++++++----- CMakeLists.txt | 51 ++++++++++++++++++++++++--- 6 files changed, 80 insertions(+), 33 deletions(-) diff --git a/.github/workflows/highs-artifacts.yml b/.github/workflows/highs-artifacts.yml index 4d1d4b7..bbb14c0 100644 --- a/.github/workflows/highs-artifacts.yml +++ b/.github/workflows/highs-artifacts.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: include: - - os: ubuntu-latest + - os: ubuntu-20.04 arch: x64 platform_name: linux-x64 cmake_args: "-DOPENMP=OFF" diff --git a/.github/workflows/unix-build.yml b/.github/workflows/unix-build.yml index 6bb81a1..6749152 100644 --- a/.github/workflows/unix-build.yml +++ b/.github/workflows/unix-build.yml @@ -90,10 +90,11 @@ jobs: # --------------------------------------------------------- - name: Configure CMake run: | - # Point CMAKE_PREFIX_PATH to our downloaded HiGHS dir cmake -B build \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" + -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" \ + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/dist" \ + -DBUILD_SHARED_LIBS=OFF - name: Build Project run: cmake --build build --config Release @@ -104,6 +105,12 @@ jobs: - name: Run Tests run: ctest --test-dir build --output-on-failure -C Release + # --------------------------------------------------------- + # Install (Stage Files) + # --------------------------------------------------------- + - name: Stage Artifacts + run: cmake --install build --config Release + # --------------------------------------------------------- # Package binaries # --------------------------------------------------------- @@ -120,28 +127,22 @@ jobs: echo "SAFE_ARCH=$(sanitize "${{ inputs.arch }}")" >> $GITHUB_ENV - name: Set Asset Name - # Naming Convention: jres-solver-[version]-[platform]-[arch].tar.gz run: echo "ASSET_NAME=jres-solver-${{ env.SAFE_VERSION }}-${{ env.SAFE_PLATFORM }}-${{ env.SAFE_ARCH }}.${{ inputs.asset_ext }}" >> $GITHUB_ENV - name: Ad-hoc Sign Binary (macOS) if: startsWith(inputs.os, 'macos') run: | - # Use ad-hoc signature (-) - # Sign the re-named binaries (from OUTPUT_NAME property in CMake) - codesign --force --deep -s - build/jres_solver - codesign --force --deep -s - build/jres_formatter - codesign --force --deep -s - build/libjres_solver.dylib + # Sign staged binaries in the /dist folder + codesign --force --deep -s - dist/bin/jres_solver + codesign --force --deep -s - dist/bin/jres_formatter + # No need to sign .a static libs - name: Package (tar.gz) run: | - cd build - # Package commands and libs using the final filenames - tar -czvf "../${{ env.ASSET_NAME }}" \ - jres_solver \ - jres_formatter \ - libjres_solver.* \ - 2>/dev/null || true - + # Archive the entire 'dist' folder content (bin, include, lib) + cd dist + tar -czvf "../${{ env.ASSET_NAME }}" . + # --------------------------------------------------------- # Generate Signature (Checksum) # --------------------------------------------------------- diff --git a/.github/workflows/unix-ci.yml b/.github/workflows/unix-ci.yml index 2bcefd4..e53657f 100644 --- a/.github/workflows/unix-ci.yml +++ b/.github/workflows/unix-ci.yml @@ -27,7 +27,7 @@ jobs: name: "Linux (x64)" version: ${{ github.ref_name }} platform: "linux" - os: ubuntu-latest + os: ubuntu-20.04 arch: x64 asset_ext: tar.gz upload_assets: false diff --git a/.github/workflows/unix-release.yml b/.github/workflows/unix-release.yml index 5d317fc..4f51e65 100644 --- a/.github/workflows/unix-release.yml +++ b/.github/workflows/unix-release.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: include: - - { name: "Linux (x64)", platform: linux, os: ubuntu-latest, arch: x64, asset_ext: tar.gz } + - { name: "Linux (x64)", platform: linux, os: ubuntu-20.04, arch: x64, asset_ext: tar.gz } - { name: "macOS Intel (x64)", platform: darwin, os: macos-13, arch: x64, asset_ext: tar.gz } - { name: "macOS Apple Silicon (arm64)", platform: darwin, os: macos-14, arch: arm64, asset_ext: tar.gz } diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 4675b43..c783ceb 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -58,19 +58,16 @@ jobs: - name: Configure CMake (MSVC) shell: pwsh run: | - # Point CMAKE_PREFIX_PATH to our downloaded HiGHS dir - # This triggers "Strategy 1" in CMakeLists.txt cmake -B build ` -G "Visual Studio 17 2022" ` -DCMAKE_BUILD_TYPE=Release ` - -DCMAKE_PREFIX_PATH="$env:HIGHS_DIR" + -DCMAKE_PREFIX_PATH="$env:HIGHS_DIR" ` + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}\dist" - name: Build Libraries & Executables shell: pwsh run: | - cmake --build build --config Release --target jres_solver_lib - cmake --build build --config Release --target solver - cmake --build build --config Release --target formatter + cmake --build build --config Release - name: Add Build Dir to PATH shell: pwsh @@ -84,6 +81,13 @@ jobs: cmake --build build --config Release --target formatter_tests ctest --test-dir build --output-on-failure -C Release + # --------------------------------------------------------- + # Install (Stage Files) + # --------------------------------------------------------- + - name: Install Artifacts + shell: pwsh + run: cmake --install build --config Release + # --------------------------------------------------------- # Package binaries (Zip for Windows) # --------------------------------------------------------- @@ -106,10 +110,11 @@ jobs: shell: pwsh run: | $assetPath = "$env:ASSET_NAME" - $source = "${{ github.workspace }}\build\Release" - Write-Host "Zipping binaries from $source to $assetPath..." + $source = "${{ github.workspace }}\dist" + Write-Host "Zipping staged artifacts from $source..." - Get-ChildItem $source -Include *.exe, *.dll, *.lib -Recurse | Compress-Archive -DestinationPath $assetPath + # Compress the whole 'dist' folder structure (bin, lib, include) + Get-ChildItem $source -Recurse | Compress-Archive -DestinationPath $assetPath # --------------------------------------------------------- # Generate Signature (Checksum) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f76c14..ab5f591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,9 @@ project(JresSolver CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) +# Default to Shared libraries (Windows preference), but allow override +option(BUILD_SHARED_LIBS "Build shared libraries" ON) + # ============================================================================== # VERSION STRATEGY # ============================================================================== @@ -99,7 +102,7 @@ else() # HiGHS Build Options set(FAST_BUILD ON CACHE BOOL "" FORCE) - set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) # Always build HiGHS static set(BUILD_TESTING OFF CACHE BOOL "" FORCE) set(HIGHS_GPL OFF CACHE BOOL "" FORCE) @@ -151,8 +154,8 @@ target_include_directories(cxxopts INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/lib/cxx add_library(jres_utils STATIC src/utils/date_utils.cpp src/utils/zip_writer.cpp) target_include_directories(jres_utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) -# --- JRES Solver Core (Shared/DLL) --- -add_library(jres_solver_lib SHARED +# --- JRES Solver Core (Shared or Static) --- +add_library(jres_solver_lib src/jres_solver.cpp src/jres_solver_utils.cpp src/jres_standard_solver.cpp @@ -163,7 +166,10 @@ set_target_properties(jres_solver_lib PROPERTIES OUTPUT_NAME "jres_solver") if(WIN32) target_sources(jres_solver_lib PRIVATE ${VERSION_RC}) - target_compile_definitions(jres_solver_lib PRIVATE JRES_SOLVER_EXPORTS) + # Only export symbols if we are actually building shared + if(BUILD_SHARED_LIBS) + target_compile_definitions(jres_solver_lib PRIVATE JRES_SOLVER_EXPORTS) + endif() endif() target_include_directories(jres_solver_lib PUBLIC @@ -214,6 +220,41 @@ target_include_directories(formatter PRIVATE target_link_libraries(formatter PRIVATE jres_formatter_lib cxxopts) -# --- Tests --- +# ============================================================================== +# LINUX PORTABILITY +# ============================================================================== +if(UNIX AND NOT APPLE) + # Statically link C++ runtime to avoid "GLIBCXX_..." version errors on older distros + target_link_options(solver PRIVATE -static-libgcc -static-libstdc++) + target_link_options(formatter PRIVATE -static-libgcc -static-libstdc++) + target_link_options(jres_solver_lib PRIVATE -static-libgcc -static-libstdc++) +endif() + +# ============================================================================== +# INSTALLATION TARGETS +# ============================================================================== +include(GNUInstallDirs) + +# Install Libraries +install(TARGETS jres_solver_lib + EXPORT JresTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +# Install Executables +install(TARGETS solver formatter + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# Install Headers +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" +) + +# Install Tests enable_testing() add_subdirectory(test) From 7fb4a07b0891473936445908636ba77954d41ed8 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 18:05:54 -0800 Subject: [PATCH 2/8] fix windows test execution --- .github/workflows/win-build.yml | 8 ++++---- test/CMakeLists.txt | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index c783ceb..e8d9b17 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -64,15 +64,15 @@ jobs: -DCMAKE_PREFIX_PATH="$env:HIGHS_DIR" ` -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}\dist" - - name: Build Libraries & Executables + - name: Add Build Dir to PATH shell: pwsh run: | - cmake --build build --config Release + "${{ github.workspace }}\build\Release" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Add Build Dir to PATH + - name: Build Libraries & Executables shell: pwsh run: | - "${{ github.workspace }}\build\Release" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + cmake --build build --config Release - name: Run Tests shell: pwsh diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3a12f99..7d753d7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,13 @@ cmake_minimum_required(VERSION 3.15) # --- Find Dependencies --- # GoogleTest include(FetchContent) + +# FORCE STATIC GOOGLETEST +# We force Shared Libs OFF for GTest so we don't need to chase down gtest.dll +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Force static GTest" FORCE) +# We force Shared CRT ON so it links correctly with the rest of the MSVC project (/MD) +set(gtest_force_shared_crt ON CACHE BOOL "Force shared CRT" FORCE) + FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip From 1c9db64d42b40ea137b9c0706c8c9041b0734885 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 19:23:19 -0800 Subject: [PATCH 3/8] Split Unix workflows into Linux and macOS builds and releases allows support for docker based ubunty-20.04 builds --- .github/workflows/highs-artifacts-linux.yml | 67 +++++++ .github/workflows/highs-artifacts.yml | 6 +- .github/workflows/linux-build.yml | 174 ++++++++++++++++++ .github/workflows/linux-ci.yml | 33 ++++ .github/workflows/linux-release.yml | 26 +++ .../{unix-build.yml => macos-build.yml} | 6 +- .../workflows/{unix-ci.yml => macos-ci.yml} | 23 +-- .../{unix-release.yml => macos-release.yml} | 5 +- 8 files changed, 310 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/highs-artifacts-linux.yml create mode 100644 .github/workflows/linux-build.yml create mode 100644 .github/workflows/linux-ci.yml create mode 100644 .github/workflows/linux-release.yml rename .github/workflows/{unix-build.yml => macos-build.yml} (95%) rename .github/workflows/{unix-ci.yml => macos-ci.yml} (62%) rename .github/workflows/{unix-release.yml => macos-release.yml} (79%) diff --git a/.github/workflows/highs-artifacts-linux.yml b/.github/workflows/highs-artifacts-linux.yml new file mode 100644 index 0000000..2605c9a --- /dev/null +++ b/.github/workflows/highs-artifacts-linux.yml @@ -0,0 +1,67 @@ +name: Build HiGHS Static Artifacts (Linux) + +on: + workflow_dispatch: + +permissions: + contents: write + +env: + HIGHS_VERSION: v1.12.0 + RELEASE_TAG: highs-static-v1.12.0 + +jobs: + build-highs: + name: Build ${{ matrix.platform_name }} + runs-on: ubuntu-latest # Use the fast runner... + container: ubuntu:20.04 # ...but build inside the old OS environment + + strategy: + matrix: + include: + - arch: x64 + platform_name: linux-x64 + cmake_args: "-DOPENMP=OFF" + + steps: + - name: Install Build Tools + run: | + export DEBIAN_FRONTEND=noninteractive + export TZ=Etc/UTC + apt-get update + apt-get install -y cmake g++ git curl build-essential zip unzip + + - name: Checkout HiGHS + uses: actions/checkout@v4 + with: + repository: ERGO-Code/HiGHS + ref: ${{ env.HIGHS_VERSION }} + + - name: Configure CMake + run: | + cmake -B build \ + -DFAST_BUILD=ON \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_INSTALL_PREFIX="install" \ + -DCMAKE_BUILD_TYPE=Release \ + ${{ matrix.cmake_args }} + + - name: Build & Install + run: | + cmake --build build --config Release --parallel 4 + cmake --install build --config Release + + - name: Zip Artifacts + run: | + zipName="highs-${{ env.HIGHS_VERSION }}-${{ matrix.platform_name }}.zip" + cd install + zip -r "../$zipName" . + echo "ARTIFACT_NAME=$zipName" >> $GITHUB_ENV + + - name: Upload to Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ env.RELEASE_TAG }} + files: ${{ env.ARTIFACT_NAME }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/highs-artifacts.yml b/.github/workflows/highs-artifacts.yml index bbb14c0..617e74f 100644 --- a/.github/workflows/highs-artifacts.yml +++ b/.github/workflows/highs-artifacts.yml @@ -1,4 +1,4 @@ -name: Build HiGHS Static Artifacts +name: Build HiGHS Static Artifacts (MacOS & Windows) on: workflow_dispatch: @@ -17,10 +17,6 @@ jobs: strategy: matrix: include: - - os: ubuntu-20.04 - arch: x64 - platform_name: linux-x64 - cmake_args: "-DOPENMP=OFF" - os: macos-13 arch: x64 platform_name: macos-x64 diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml new file mode 100644 index 0000000..71793db --- /dev/null +++ b/.github/workflows/linux-build.yml @@ -0,0 +1,174 @@ +name: Linux [reusable] Build + +on: + workflow_call: + inputs: + version: + type: string + required: true + name: + type: string + required: true + platform: + type: string + required: true + arch: + type: string + required: true + asset_ext: + type: string + required: true + upload_assets: + type: boolean + required: true + upload_url: + type: string + required: false + +jobs: + build: + runs-on: ubuntu-latest + container: ubuntu:20.04 + + env: + HIGHS_TAG: highs-static-v1.12.0 + HIGHS_DIR: ${{ github.workspace }}/highs + + steps: + # --------------------------------------------------------- + # Debug Info + # --------------------------------------------------------- + - name: Print Build Info + run: | + echo "Version: ${{ inputs.version }}" + echo "Platform: ${{ inputs.platform }}" + echo "Arch: ${{ inputs.arch }}" + + # --------------------------------------------------------- + # Install Build Tools + # --------------------------------------------------------- + - name: Install Build Tools + run: | + export DEBIAN_FRONTEND=noninteractive + export TZ=Etc/UTC + apt-get update + apt-get install -y cmake g++ git curl build-essential zip unzip + + # --------------------------------------------------------- + # Checkout repo with submodules + # --------------------------------------------------------- + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + # --------------------------------------------------------- + # Download Pre-built HiGHS + # --------------------------------------------------------- + - name: Determine Artifact Name + id: artifact + run: | + if [ "${{ inputs.platform }}" = "linux" ] && [ "${{ inputs.arch }}" = "x64" ]; then + echo "zip_name=highs-v1.12.0-linux-x64.zip" >> "$GITHUB_OUTPUT" + else + echo "Error: Unsupported Platform/Arch combination: ${{ inputs.platform }} ${{ inputs.arch }}" + exit 1 + fi + + - name: Download HiGHS Artifact + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p ${{ env.HIGHS_DIR }} + echo "Downloading ${{ steps.artifact.outputs.zip_name }}..." + gh release download ${{ env.HIGHS_TAG }} \ + --pattern ${{ steps.artifact.outputs.zip_name }} \ + --output "${{ env.HIGHS_DIR }}/highs.zip" \ + --repo ${{ github.repository }} + + unzip "${{ env.HIGHS_DIR }}/highs.zip" -d ${{ env.HIGHS_DIR }} + + # --------------------------------------------------------- + # Build + # --------------------------------------------------------- + - name: Configure CMake + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" \ + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/dist" \ + -DBUILD_SHARED_LIBS=OFF + + - name: Build Project + run: cmake --build build --config Release + + - name: Build Tests + run: cmake --build build --config Release --target solver_tests + + - name: Run Tests + run: ctest --test-dir build --output-on-failure -C Release + + # --------------------------------------------------------- + # Install (Stage Files) + # --------------------------------------------------------- + - name: Stage Artifacts + run: cmake --install build --config Release + + # --------------------------------------------------------- + # Package binaries + # --------------------------------------------------------- + + - name: Sanitize Inputs + run: | + # Function to lowercase and replace invalid chars with _ + sanitize() { + echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/_/g' + } + + echo "SAFE_VERSION=$(sanitize "${{ inputs.version }}")" >> $GITHUB_ENV + echo "SAFE_PLATFORM=$(sanitize "${{ inputs.platform }}")" >> $GITHUB_ENV + echo "SAFE_ARCH=$(sanitize "${{ inputs.arch }}")" >> $GITHUB_ENV + + - name: Set Asset Name + run: echo "ASSET_NAME=jres-solver-${{ env.SAFE_VERSION }}-${{ env.SAFE_PLATFORM }}-${{ env.SAFE_ARCH }}.${{ inputs.asset_ext }}" >> $GITHUB_ENV + + - name: Package (tar.gz) + run: | + # Archive the entire 'dist' folder content (bin, include, lib) + cd dist + tar -czvf "../${{ env.ASSET_NAME }}" . + + # --------------------------------------------------------- + # Generate Signature (Checksum) + # --------------------------------------------------------- + - name: Generate Checksum + run: | + # Generate SHA256 checksum for the tarball + shasum -a 256 ${{ env.ASSET_NAME }} > ${{ env.ASSET_NAME }}.sha256 + cat ${{ env.ASSET_NAME }}.sha256 + + # --------------------------------------------------------- + # Upload Artifacts + # --------------------------------------------------------- + - name: Upload Release Asset (Binary) + if: inputs.upload_assets == true + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: ./${{ env.ASSET_NAME }} + asset_name: ${{ env.ASSET_NAME }} + asset_content_type: application/gzip + + - name: Upload Release Asset (Checksum) + if: inputs.upload_assets == true + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ inputs.upload_url }} + asset_path: ./${{ env.ASSET_NAME }}.sha256 + asset_name: ${{ env.ASSET_NAME }}.sha256 + asset_content_type: text/plain diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml new file mode 100644 index 0000000..b17c578 --- /dev/null +++ b/.github/workflows/linux-ci.yml @@ -0,0 +1,33 @@ +name: Linux CI + +on: + push: + branches: [ "main" ] + paths: + - '**.cpp' + - '**.hpp' + - '**/CMakeLists.txt' + - '.github/workflows/linux-*.yml' + pull_request: + branches: [ "main" ] + paths: + - '**.cpp' + - '**.hpp' + - '**/CMakeLists.txt' + - '.github/workflows/linux-*.yml' + +permissions: + contents: read + +jobs: + linux: + uses: ./.github/workflows/linux-build.yml + secrets: inherit + with: + name: "Linux (x64)" + version: ${{ github.ref_name }} + platform: "linux" + arch: x64 + asset_ext: tar.gz + upload_assets: false + upload_url: "" diff --git a/.github/workflows/linux-release.yml b/.github/workflows/linux-release.yml new file mode 100644 index 0000000..a3fc757 --- /dev/null +++ b/.github/workflows/linux-release.yml @@ -0,0 +1,26 @@ +name: Linux Release + +on: + release: + types: [created] + +permissions: + contents: write + +jobs: + build-all: + strategy: + matrix: + include: + - { name: "Linux (x64)", platform: linux, os: ubuntu-20.04, arch: x64, asset_ext: tar.gz } + + uses: ./.github/workflows/linux-build.yml + secrets: inherit + with: + version: ${{ github.ref_name }} + name: ${{ matrix.name }} + platform: ${{ matrix.platform }} + arch: ${{ matrix.arch }} + asset_ext: ${{ matrix.asset_ext }} + upload_assets: true + upload_url: ${{ github.event.release.upload_url }} diff --git a/.github/workflows/unix-build.yml b/.github/workflows/macos-build.yml similarity index 95% rename from .github/workflows/unix-build.yml rename to .github/workflows/macos-build.yml index 6749152..3f8c83c 100644 --- a/.github/workflows/unix-build.yml +++ b/.github/workflows/macos-build.yml @@ -1,4 +1,4 @@ -name: Unix [reusable] Build +name: MacOS [reusable] Build on: workflow_call: @@ -61,9 +61,7 @@ jobs: - name: Determine Artifact Name id: artifact run: | - if [[ "${{ inputs.platform }}" == "linux" && "${{ inputs.arch }}" == "x64" ]]; then - echo "zip_name=highs-v1.12.0-linux-x64.zip" >> $GITHUB_OUTPUT - elif [[ "${{ inputs.platform }}" == "darwin" && "${{ inputs.arch }}" == "x64" ]]; then + if [[ "${{ inputs.platform }}" == "darwin" && "${{ inputs.arch }}" == "x64" ]]; then echo "zip_name=highs-v1.12.0-macos-x64.zip" >> $GITHUB_OUTPUT elif [[ "${{ inputs.platform }}" == "darwin" && "${{ inputs.arch }}" == "arm64" ]]; then echo "zip_name=highs-v1.12.0-macos-arm64.zip" >> $GITHUB_OUTPUT diff --git a/.github/workflows/unix-ci.yml b/.github/workflows/macos-ci.yml similarity index 62% rename from .github/workflows/unix-ci.yml rename to .github/workflows/macos-ci.yml index e53657f..9ffce9b 100644 --- a/.github/workflows/unix-ci.yml +++ b/.github/workflows/macos-ci.yml @@ -1,4 +1,4 @@ -name: Unix CI +name: MacOS CI on: push: @@ -7,34 +7,21 @@ on: - '**.cpp' - '**.hpp' - '**/CMakeLists.txt' - - '.github/workflows/unix-*.yml' + - '.github/workflows/macos*.yml' pull_request: branches: [ "main" ] paths: - '**.cpp' - '**.hpp' - '**/CMakeLists.txt' - - '.github/workflows/unix-*.yml' + - '.github/workflows/macos*.yml' permissions: contents: read jobs: - linux: - uses: ./.github/workflows/unix-build.yml - secrets: inherit - with: - name: "Linux (x64)" - version: ${{ github.ref_name }} - platform: "linux" - os: ubuntu-20.04 - arch: x64 - asset_ext: tar.gz - upload_assets: false - upload_url: "" - macos-intel: - uses: ./.github/workflows/unix-build.yml + uses: ./.github/workflows/macos-build.yml secrets: inherit with: name: "macOS Intel (x64)" @@ -47,7 +34,7 @@ jobs: upload_url: "" macos-arm: - uses: ./.github/workflows/unix-build.yml + uses: ./.github/workflows/macos-build.yml secrets: inherit with: name: "macOS Apple Silicon (arm64)" diff --git a/.github/workflows/unix-release.yml b/.github/workflows/macos-release.yml similarity index 79% rename from .github/workflows/unix-release.yml rename to .github/workflows/macos-release.yml index 4f51e65..d0edca8 100644 --- a/.github/workflows/unix-release.yml +++ b/.github/workflows/macos-release.yml @@ -1,4 +1,4 @@ -name: Unix Release +name: MacOS Release on: release: @@ -12,11 +12,10 @@ jobs: strategy: matrix: include: - - { name: "Linux (x64)", platform: linux, os: ubuntu-20.04, arch: x64, asset_ext: tar.gz } - { name: "macOS Intel (x64)", platform: darwin, os: macos-13, arch: x64, asset_ext: tar.gz } - { name: "macOS Apple Silicon (arm64)", platform: darwin, os: macos-14, arch: arm64, asset_ext: tar.gz } - uses: ./.github/workflows/unix-build.yml + uses: ./.github/workflows/macos-build.yml secrets: inherit with: version: ${{ github.ref_name }} From d2ce0eb7c350c7f2cac9af5d59dce7413a7dda50 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 19:48:02 -0800 Subject: [PATCH 4/8] Enhance Linux build workflow: replace 'gh' with 'curl' for artifact download and add 'jq' for JSON parsing --- .github/workflows/linux-build.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 71793db..9cecd72 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -52,7 +52,7 @@ jobs: export DEBIAN_FRONTEND=noninteractive export TZ=Etc/UTC apt-get update - apt-get install -y cmake g++ git curl build-essential zip unzip + apt-get install -y cmake g++ git curl jq build-essential zip unzip # --------------------------------------------------------- # Checkout repo with submodules @@ -76,17 +76,28 @@ jobs: exit 1 fi + # No gh on Ubuntu:20.04 container so use curl - name: Download HiGHS Artifact env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | mkdir -p ${{ env.HIGHS_DIR }} + echo "Resolving asset URL for ${{ steps.artifact.outputs.zip_name }}..." + RELEASE_JSON=$(curl -sSL -H "Authorization: Bearer $GH_TOKEN" \ + "https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ env.HIGHS_TAG }}") + ASSET_URL=$(echo "$RELEASE_JSON" | jq -r \ + --arg NAME "${{ steps.artifact.outputs.zip_name }}" \ + '.assets[] | select(.name == $NAME) | .url') + if [ -z "$ASSET_URL" ] || [ "$ASSET_URL" = "null" ]; then + echo "Error: Could not find asset ${{ steps.artifact.outputs.zip_name }} in release ${{ env.HIGHS_TAG }}" + echo "$RELEASE_JSON" | jq -r '.assets[].name' || true + exit 1 + fi echo "Downloading ${{ steps.artifact.outputs.zip_name }}..." - gh release download ${{ env.HIGHS_TAG }} \ - --pattern ${{ steps.artifact.outputs.zip_name }} \ - --output "${{ env.HIGHS_DIR }}/highs.zip" \ - --repo ${{ github.repository }} - + curl -sSL -H "Authorization: Bearer $GH_TOKEN" \ + -H "Accept: application/octet-stream" \ + -o "${{ env.HIGHS_DIR }}/highs.zip" "$ASSET_URL" + unzip "${{ env.HIGHS_DIR }}/highs.zip" -d ${{ env.HIGHS_DIR }} # --------------------------------------------------------- From 32ae6f945c1859d4f4a6b8842ca008b3807bbbc6 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 19:58:52 -0800 Subject: [PATCH 5/8] get latest cmake in ubuntu:20.04 --- .github/workflows/linux-build.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9cecd72..e8edd13 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -45,14 +45,22 @@ jobs: echo "Arch: ${{ inputs.arch }}" # --------------------------------------------------------- - # Install Build Tools + # Install Build Tools (Modern CMake) # --------------------------------------------------------- - name: Install Build Tools run: | export DEBIAN_FRONTEND=noninteractive export TZ=Etc/UTC apt-get update - apt-get install -y cmake g++ git curl jq build-essential zip unzip + + # Install python3-pip to get modern CMake, remove old cmake from apt + apt-get install -y python3-pip g++ git curl jq build-essential zip unzip + + # Install latest CMake (3.20+) via pip to support FetchContent features + pip3 install cmake + + # Verify version (Should be 3.2x or higher) + cmake --version # --------------------------------------------------------- # Checkout repo with submodules From aa86142ec7e90af8984e4a47bbc953102803af7a Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 20:13:44 -0800 Subject: [PATCH 6/8] dist fix --- .github/workflows/linux-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index e8edd13..a426132 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -116,7 +116,6 @@ jobs: cmake -B build \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" \ - -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/dist" \ -DBUILD_SHARED_LIBS=OFF - name: Build Project @@ -132,7 +131,7 @@ jobs: # Install (Stage Files) # --------------------------------------------------------- - name: Stage Artifacts - run: cmake --install build --config Release + run: cmake --install build --config Release --prefix dist # --------------------------------------------------------- # Package binaries From 296ebb2a0b8e9451e1f5bfee0a77c18526224ceb Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 22:14:19 -0800 Subject: [PATCH 7/8] Enhance packaging process across Linux, macOS, and Windows workflows to include versioning and curated selection of artifacts --- .github/workflows/linux-build.yml | 26 ++++++++++++++++++---- .github/workflows/macos-build.yml | 28 ++++++++++++++++++----- .github/workflows/win-build.yml | 37 +++++++++++++++++++++++++------ 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index a426132..01dc7f4 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -116,7 +116,8 @@ jobs: cmake -B build \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" \ - -DBUILD_SHARED_LIBS=OFF + -DBUILD_SHARED_LIBS=OFF \ + -DJRES_VERSION="${{ inputs.version }}" - name: Build Project run: cmake --build build --config Release @@ -151,10 +152,27 @@ jobs: - name: Set Asset Name run: echo "ASSET_NAME=jres-solver-${{ env.SAFE_VERSION }}-${{ env.SAFE_PLATFORM }}-${{ env.SAFE_ARCH }}.${{ inputs.asset_ext }}" >> $GITHUB_ENV - - name: Package (tar.gz) + - name: Package (Curated Selection) run: | - # Archive the entire 'dist' folder content (bin, include, lib) - cd dist + mkdir -p package/bin + mkdir -p package/lib + mkdir -p package/include/jres_solver + + echo "Packaging Binary Artifacts..." + + # Executables + cp dist/bin/jres_solver package/bin/ + cp dist/bin/jres_formatter package/bin/ + + # Library (Grab .a or .so depending on build, likely .a) + # Using find/cp with wildcard to be robust against lib vs lib64 differences + find dist -name "libjres_solver.*" -exec cp {} package/lib/ \; + + # Specific Header + cp dist/include/jres_solver/jres_solver.hpp package/include/jres_solver/ + + # Archive the 'package' folder content + cd package tar -czvf "../${{ env.ASSET_NAME }}" . # --------------------------------------------------------- diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index 3f8c83c..80cf5e0 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -92,7 +92,8 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH="${{ env.HIGHS_DIR }}" \ -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/dist" \ - -DBUILD_SHARED_LIBS=OFF + -DBUILD_SHARED_LIBS=OFF \ + -DJRES_VERSION="${{ inputs.version }}" - name: Build Project run: cmake --build build --config Release @@ -130,15 +131,32 @@ jobs: - name: Ad-hoc Sign Binary (macOS) if: startsWith(inputs.os, 'macos') run: | - # Sign staged binaries in the /dist folder + # Sign staged binaries in the /dist folder before packaging codesign --force --deep -s - dist/bin/jres_solver codesign --force --deep -s - dist/bin/jres_formatter # No need to sign .a static libs - - name: Package (tar.gz) + - name: Package (Curated Selection) run: | - # Archive the entire 'dist' folder content (bin, include, lib) - cd dist + mkdir -p package/bin + mkdir -p package/lib + mkdir -p package/include/jres_solver + + echo "Packaging Binary Artifacts..." + + # Executables + cp dist/bin/jres_solver package/bin/ + cp dist/bin/jres_formatter package/bin/ + + # Library (Grab .dylib or .a) + # Using find/cp with wildcard to be robust + find dist -name "libjres_solver.*" -exec cp {} package/lib/ \; + + # Specific Header + cp dist/include/jres_solver/jres_solver.hpp package/include/jres_solver/ + + # Archive the 'package' folder content + cd package tar -czvf "../${{ env.ASSET_NAME }}" . # --------------------------------------------------------- diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index e8d9b17..40015a4 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -62,7 +62,8 @@ jobs: -G "Visual Studio 17 2022" ` -DCMAKE_BUILD_TYPE=Release ` -DCMAKE_PREFIX_PATH="$env:HIGHS_DIR" ` - -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}\dist" + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}\dist" ` + -DJRES_VERSION="${{ inputs.version }}" - name: Add Build Dir to PATH shell: pwsh @@ -106,15 +107,37 @@ jobs: $assetName = "jres-solver-${{ env.SAFE_VERSION }}-windows-${{ env.SAFE_ARCH }}.zip" echo "ASSET_NAME=$assetName" >> $env:GITHUB_ENV - - name: Create Release Zip + - name: Package (Curated Selection) shell: pwsh run: | - $assetPath = "$env:ASSET_NAME" - $source = "${{ github.workspace }}\dist" - Write-Host "Zipping staged artifacts from $source..." + $pkg = "package" + New-Item -ItemType Directory -Path "$pkg\bin" -Force | Out-Null + New-Item -ItemType Directory -Path "$pkg\lib" -Force | Out-Null + New-Item -ItemType Directory -Path "$pkg\include\jres_solver" -Force | Out-Null + + Write-Host "Packaging Binary Artifacts..." + + # Executables + Copy-Item "dist\bin\jres_solver.exe" -Destination "$pkg\bin\" + Copy-Item "dist\bin\jres_formatter.exe" -Destination "$pkg\bin\" - # Compress the whole 'dist' folder structure (bin, lib, include) - Get-ChildItem $source -Recurse | Compress-Archive -DestinationPath $assetPath + # Library (Handle DLLs and LIBs) + # Copy import libraries (.lib) to lib folder + if (Test-Path "dist\lib\jres_solver.lib") { + Copy-Item "dist\lib\jres_solver.lib" -Destination "$pkg\lib\" + } + # Copy runtime libraries (.dll) to bin folder (typical windows convention) + if (Test-Path "dist\bin\jres_solver.dll") { + Copy-Item "dist\bin\jres_solver.dll" -Destination "$pkg\bin\" + } + + # Specific Header + Copy-Item "dist\include\jres_solver\jres_solver.hpp" -Destination "$pkg\include\jres_solver\" + + # Zip the package folder + $assetPath = "$env:ASSET_NAME" + Write-Host "Zipping curated package to $assetPath..." + Get-ChildItem -Path $pkg | Compress-Archive -DestinationPath $assetPath # --------------------------------------------------------- # Generate Signature (Checksum) From c3032dc9882f82f5efed75b04dfee9d9b6b7a966 Mon Sep 17 00:00:00 2001 From: popmonkey Date: Wed, 26 Nov 2025 22:31:20 -0800 Subject: [PATCH 8/8] switch to static build for windows --- .github/workflows/win-build.yml | 8 ++------ CMakeLists.txt | 4 +++- include/jres_solver/jres_solver.hpp | 9 +++++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 40015a4..de46d4d 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -63,6 +63,7 @@ jobs: -DCMAKE_BUILD_TYPE=Release ` -DCMAKE_PREFIX_PATH="$env:HIGHS_DIR" ` -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}\dist" ` + -DBUILD_SHARED_LIBS=OFF ` -DJRES_VERSION="${{ inputs.version }}" - name: Add Build Dir to PATH @@ -121,15 +122,10 @@ jobs: Copy-Item "dist\bin\jres_solver.exe" -Destination "$pkg\bin\" Copy-Item "dist\bin\jres_formatter.exe" -Destination "$pkg\bin\" - # Library (Handle DLLs and LIBs) - # Copy import libraries (.lib) to lib folder + # Library (static) if (Test-Path "dist\lib\jres_solver.lib") { Copy-Item "dist\lib\jres_solver.lib" -Destination "$pkg\lib\" } - # Copy runtime libraries (.dll) to bin folder (typical windows convention) - if (Test-Path "dist\bin\jres_solver.dll") { - Copy-Item "dist\bin\jres_solver.dll" -Destination "$pkg\bin\" - } # Specific Header Copy-Item "dist\include\jres_solver\jres_solver.hpp" -Destination "$pkg\include\jres_solver\" diff --git a/CMakeLists.txt b/CMakeLists.txt index ab5f591..bd0fdf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,9 +166,11 @@ set_target_properties(jres_solver_lib PROPERTIES OUTPUT_NAME "jres_solver") if(WIN32) target_sources(jres_solver_lib PRIVATE ${VERSION_RC}) - # Only export symbols if we are actually building shared + if(BUILD_SHARED_LIBS) target_compile_definitions(jres_solver_lib PRIVATE JRES_SOLVER_EXPORTS) + else() + target_compile_definitions(jres_solver_lib PUBLIC JRES_STATIC) endif() endif() diff --git a/include/jres_solver/jres_solver.hpp b/include/jres_solver/jres_solver.hpp index b3bd946..8b329e0 100644 --- a/include/jres_solver/jres_solver.hpp +++ b/include/jres_solver/jres_solver.hpp @@ -13,10 +13,15 @@ #define JRES_SOLVER_HPP #if defined(_WIN32) - // Windows/MSVC: Use __declspec(dllexport/dllimport) - #ifdef JRES_SOLVER_EXPORTS + // Windows/MSVC: Handle DLL exports, imports, AND static builds + #if defined(JRES_STATIC) + // Static build: No special attributes needed + #define JRES_SOLVER_API + #elif defined(JRES_SOLVER_EXPORTS) + // Building the DLL: Export symbols #define JRES_SOLVER_API __declspec(dllexport) #else + // Using the DLL: Import symbols #define JRES_SOLVER_API __declspec(dllimport) #endif #else