From f143b124e5f2808fb4e3bc1f77b6dc56a7778481 Mon Sep 17 00:00:00 2001
From: Denis Kudelin <15978569+denis-kudelin@users.noreply.github.com>
Date: Sun, 27 Apr 2025 13:45:31 +0300
Subject: [PATCH 1/4] CI: enable multi-RID build and automated NuGet
pack/publish (#1)
---
.github/workflows/multi-rid-build.yml | 259 ++++++++++++++++++
.github/workflows/nuget.yml | 204 ++++++++++++++
nuget/SimpleCpp.Native.csproj | 37 +++
nuget/buildTransitive/SimpleCpp.Native.props | 26 ++
.../buildTransitive/SimpleCpp.Native.targets | 13 +
5 files changed, 539 insertions(+)
create mode 100644 .github/workflows/multi-rid-build.yml
create mode 100644 .github/workflows/nuget.yml
create mode 100644 nuget/SimpleCpp.Native.csproj
create mode 100644 nuget/buildTransitive/SimpleCpp.Native.props
create mode 100644 nuget/buildTransitive/SimpleCpp.Native.targets
diff --git a/.github/workflows/multi-rid-build.yml b/.github/workflows/multi-rid-build.yml
new file mode 100644
index 00000000..a66092d8
--- /dev/null
+++ b/.github/workflows/multi-rid-build.yml
@@ -0,0 +1,259 @@
+name: multi-rid-build
+on: [pull_request, workflow_dispatch]
+
+env:
+ PROJECT_NAME: simplecpp
+ BUILD_TARGETS: "simplecpp"
+ BUILD_TESTING: OFF
+ DEBUG_SYMBOLS: true
+ CMAKE_BUILD_TYPE: Release
+ CMAKE_CXX_STANDARD: 17
+ CMAKE_CXX_STANDARD_REQUIRED: ON
+ C_FLAGS_COMMON: "-w -fexceptions"
+ CXX_FLAGS_COMMON: "-w -fexceptions"
+ CMAKE_EXTRA_ARGS: ""
+
+jobs:
+ windows:
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ arch:
+ - x64
+ - ARM64
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: prepare-dirs
+ shell: pwsh
+ run: New-Item -ItemType Directory -Force -Path artifacts
+
+ - name: install dlfcn-win32
+ shell: pwsh
+ run: |
+ $triplet = ("${{ matrix.arch }}-windows").ToLower()
+ vcpkg install dlfcn-win32 --triplet $triplet
+
+ "VCPKG_INSTALLATION_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
+ "VCPKG_TRIPLET=$triplet" | Out-File -FilePath $env:GITHUB_ENV -Append
+ "VCPKG_INCLUDE=$env:VCPKG_INSTALLATION_ROOT\installed\$triplet\include" | Out-File -FilePath $env:GITHUB_ENV -Append
+ "VCPKG_LIB=$env:VCPKG_INSTALLATION_ROOT\installed\$triplet\lib" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - id: detect-mingw
+ shell: pwsh
+ run: |
+ if (
+ (Test-Path 'C:\msys64\usr\bin\bash.exe') -and
+ (Get-ChildItem -Recurse 'C:\msys64' -Filter llvm-objcopy.exe | Select-Object -First 1) -and
+ (Get-ChildItem -Recurse 'C:\msys64' -Filter clang.exe | Select-Object -First 1)
+ ) {
+ "full=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
+ } else {
+ "full=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
+ }
+
+ - name: build-mingw
+ if: steps.detect-mingw.outputs.full == 'true'
+ run: |
+ C:\msys64\usr\bin\bash.exe -lc '
+ set -euo pipefail
+ export PATH="$PATH:/c/Program Files/CMake/bin:/c/msys64/usr/bin:/c/msys64/mingw64/bin:/c/msys64/clang-arm64/bin:/c/msys64/ucrt64/bin"
+ mkdir -p artifacts
+ cmake -S . -B build/mingw/${{ matrix.arch }} -G Ninja \
+ -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake \
+ -DVCPKG_TARGET_TRIPLET=$VCPKG_TRIPLET \
+ -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
+ -DCMAKE_C_COMPILER=clang \
+ -DCMAKE_CXX_COMPILER=clang++ \
+ -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
+ -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
+ -DCMAKE_INCLUDE_PATH="$VCPKG_INCLUDE" \
+ -DCMAKE_LIBRARY_PATH="$VCPKG_LIB" \
+ -DCMAKE_C_FLAGS="$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g") ${{ env.C_FLAGS_COMMON }} -I$VCPKG_INCLUDE" \
+ -DCMAKE_CXX_FLAGS="$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g") ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }} -I$VCPKG_INCLUDE" \
+ -DCMAKE_EXE_LINKER_FLAGS="-L$VCPKG_LIB -ldlfcn-win32" \
+ -DCMAKE_SHARED_LINKER_FLAGS="-L$VCPKG_LIB -ldlfcn-win32" \
+ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
+ ${{ env.CMAKE_EXTRA_ARGS }}
+ for tgt in ${{ env.BUILD_TARGETS }}; do
+ cmake --build build/mingw/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
+ done
+ if [ "${{ env.DEBUG_SYMBOLS }}" = "true" ]; then
+ OBJCOPY=$(command -v llvm-objcopy || command -v objcopy)
+ for f in artifacts/*.dll; do
+ [ -f "$f" ] && "$OBJCOPY" --only-keep-debug "$f" "$f.debug" && "$OBJCOPY" --strip-debug "$f"
+ done
+ fi
+ '
+
+ - name: check-lib-files
+ if: steps.detect-mingw.outputs.full == 'false'
+ shell: pwsh
+ run: |
+ Write-Host "Library files in VCPKG_LIB directory:"
+ Get-ChildItem -Path $env:VCPKG_LIB -Filter "*.lib" | Select-Object -ExpandProperty Name
+
+ - name: configure-vs
+ if: steps.detect-mingw.outputs.full == 'false'
+ shell: pwsh
+ run: |
+ $out = "$(Get-Location)\artifacts"
+ $dbg = if ($env:DEBUG_SYMBOLS -eq 'true') { '/Zi' } else { '' }
+ $linker = if ($env:DEBUG_SYMBOLS -eq 'true') { '/DEBUG' } else { '' }
+ $defs = '/D_CRT_DECLARE_NONSTDC_NAMES=1 /D_CRT_NONSTDC_NO_DEPRECATE=1 /D_CRT_SECURE_NO_WARNINGS=1 /Dpopen=_popen /Dpclose=_pclose'
+
+ $dlfcnLib = "$env:VCPKG_LIB\dlfcn-win32.lib"
+ if (-not (Test-Path $dlfcnLib)) {
+ $dlfcnLib = (Get-ChildItem -Path $env:VCPKG_LIB -Filter "dlfcn*.lib" | Select-Object -First 1).FullName
+ if (-not $dlfcnLib) {
+ $dlfcnLib = (Get-ChildItem -Path $env:VCPKG_LIB -Filter "*.lib" | Select-Object -First 1).FullName
+ }
+ }
+
+ cmake -S . -B build/${{ matrix.arch }} -G "Visual Studio 17 2022" -A ${{ matrix.arch }} -T ClangCL `
+ -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" `
+ -DVCPKG_TARGET_TRIPLET="$env:VCPKG_TRIPLET" `
+ -DCMAKE_PREFIX_PATH="$env:VCPKG_INSTALLATION_ROOT\installed\$env:VCPKG_TRIPLET" `
+ -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} `
+ -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} `
+ -DCMAKE_INCLUDE_PATH="$env:VCPKG_INCLUDE" `
+ -DCMAKE_LIBRARY_PATH="$env:VCPKG_LIB" `
+ -DCMAKE_C_FLAGS="/w /EHsc $dbg $defs /I$env:VCPKG_INCLUDE" `
+ -DCMAKE_CXX_FLAGS="/w /EHsc $dbg /std:c++${{ env.CMAKE_CXX_STANDARD }} $defs /I$env:VCPKG_INCLUDE" `
+ -DCMAKE_EXE_LINKER_FLAGS="/LIBPATH:$env:VCPKG_LIB $dlfcnLib $linker" `
+ -DCMAKE_SHARED_LINKER_FLAGS="/LIBPATH:$env:VCPKG_LIB $dlfcnLib $linker" `
+ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE="$out" `
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE="$out" `
+ -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE="$out" `
+ -DBUILD_TESTING=${{ env.BUILD_TESTING }} `
+ -DVCPKG_APPLOCAL_DEPS=ON `
+ ${{ env.CMAKE_EXTRA_ARGS }}
+
+ - name: build-vs
+ if: steps.detect-mingw.outputs.full == 'false'
+ shell: pwsh
+ run: |
+ foreach ($t in $env:BUILD_TARGETS.Split()) {
+ cmake --build build/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $t
+ }
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.PROJECT_NAME }}-win-${{ matrix.arch }}
+ path: artifacts/**
+
+ linux:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ triple:
+ - x86_64-linux-gnu
+ - aarch64-linux-gnu
+ steps:
+ - uses: actions/checkout@v4
+ - uses: mlugg/setup-zig@v1
+ with:
+ version: 0.12.0
+ use-cache: true
+ - name: create-ccc
+ run: |
+ mkdir -p $HOME/bin
+ printf '#!/bin/sh\nexec zig cc "$@"\n' > $HOME/bin/zigcc
+ printf '#!/bin/sh\nexec zig c++ "$@"\n' > $HOME/bin/zigcxx
+ chmod +x $HOME/bin/zigcc $HOME/bin/zigcxx
+ echo "$HOME/bin" >> $GITHUB_PATH
+ - name: configure
+ run: |
+ set -euo pipefail
+ mkdir -p artifacts
+ DBG=$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g" || echo "-g0")
+ export CFLAGS="-O2 $DBG -ffunction-sections -fdata-sections ${{ env.C_FLAGS_COMMON }}"
+ export CXXFLAGS="-O2 $DBG -ffunction-sections -fdata-sections ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }}"
+ cmake -S . -B build/${{ matrix.triple }} -G Ninja \
+ -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
+ -DCMAKE_C_COMPILER=zigcc \
+ -DCMAKE_CXX_COMPILER=zigcxx \
+ -DCMAKE_C_COMPILER_TARGET=${{ matrix.triple }} \
+ -DCMAKE_CXX_COMPILER_TARGET=${{ matrix.triple }} \
+ -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
+ -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
+ -DCMAKE_EXE_LINKER_FLAGS="-Wl,-z,origin,-rpath,'$$ORIGIN'" \
+ -DCMAKE_INSTALL_RPATH="$$ORIGIN" \
+ -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
+ -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--gc-sections" \
+ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
+ -DDISABLE_CPP03_SYNTAX_CHECK=ON
+ ${{ env.CMAKE_EXTRA_ARGS }}
+ - name: build
+ run: |
+ for tgt in ${{ env.BUILD_TARGETS }}; do
+ cmake --build build/${{ matrix.triple }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
+ done
+ - name: split-debug
+ if: env.DEBUG_SYMBOLS == 'true'
+ run: |
+ set -euo pipefail
+ shopt -s nullglob globstar
+ OBJCOPY=$(command -v llvm-objcopy-18 || command -v llvm-objcopy || command -v objcopy)
+ for lib in **/*.so; do
+ "$OBJCOPY" --only-keep-debug "$lib" "$lib.debug"
+ "$OBJCOPY" --add-gnu-debuglink="$lib.debug" "$lib"
+ done
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.PROJECT_NAME }}-linux-${{ matrix.triple }}
+ path: artifacts/**
+
+ macos:
+ runs-on: macos-latest
+ strategy:
+ matrix:
+ arch:
+ - x86_64
+ - arm64
+ steps:
+ - uses: actions/checkout@v4
+ - name: configure
+ run: |
+ set -euo pipefail
+ mkdir -p artifacts
+ DBG=$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g" || echo "-g0")
+ cmake -S . -B build/${{ matrix.arch }} -G Ninja \
+ -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
+ -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \
+ -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
+ -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
+ -DCMAKE_C_FLAGS="$DBG ${{ env.C_FLAGS_COMMON }}" \
+ -DCMAKE_CXX_FLAGS="$DBG ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }}" \
+ -DCMAKE_MACOSX_RPATH=ON \
+ -DCMAKE_INSTALL_RPATH="@loader_path" \
+ -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
+ -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
+ -DCMAKE_EXE_LINKER_FLAGS="-Wl,-rpath,@loader_path" \
+ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
+ -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
+ ${{ env.CMAKE_EXTRA_ARGS }}
+ - name: build
+ run: |
+ for tgt in ${{ env.BUILD_TARGETS }}; do
+ cmake --build build/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
+ done
+ - name: dsym
+ if: env.DEBUG_SYMBOLS == 'true'
+ run: |
+ shopt -s nullglob
+ for dylib in artifacts/*.dylib; do
+ dsymutil "$dylib"
+ done
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.PROJECT_NAME }}-osx-${{ matrix.arch }}
+ path: artifacts/**
\ No newline at end of file
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
new file mode 100644
index 00000000..56f0e0e1
--- /dev/null
+++ b/.github/workflows/nuget.yml
@@ -0,0 +1,204 @@
+# NuGet package publishing workflow
+name: nuget
+on:
+ workflow_run:
+ workflows: [multi-rid-build]
+ types: [completed]
+ workflow_dispatch:
+
+env:
+ NUGET_SOURCE: https://api.nuget.org/v3/index.json
+ CSPROJ_NAME: SimpleCpp.Native.csproj
+ ARTIFACT_PREFIX: simplecpp
+
+jobs:
+ pack:
+ if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Set project path
+ run: echo "CSPROJ_PATH=nuget/${{ env.CSPROJ_NAME }}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: determine artifact run id
+ id: run_id
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+ RID=$(gh api "/repos/${{ github.repository }}/actions/workflows/multi-rid-build.yml/runs?status=success&per_page=1" --jq '.workflow_runs[0].id')
+ if [ -z "$RID" ]; then
+ echo "::error::No successful multi-rid-build runs found"
+ RID="none"
+ fi
+ else
+ RID=${{ github.event.workflow_run.id }}
+ fi
+ echo "run_id=$RID" >> $GITHUB_OUTPUT
+ echo "Using artifacts from run ID: $RID"
+
+ - uses: actions/download-artifact@v4
+ if: steps.run_id.outputs.run_id != 'none'
+ continue-on-error: true
+ with:
+ path: artifacts
+ run-id: ${{ steps.run_id.outputs.run_id }}
+ github-token: ${{ github.token }}
+
+ - name: Create artifacts directory if it doesn't exist
+ run: mkdir -p artifacts
+
+ - name: Validate artifacts
+ id: validate_artifacts
+ run: |
+ ARTIFACT_COUNT=$(find artifacts -type f | wc -l)
+ if [ "$ARTIFACT_COUNT" -eq 0 ]; then
+ echo "::error::No artifacts found from the build"
+ exit 1
+ fi
+ echo "has_artifacts=true" >> $GITHUB_OUTPUT
+
+ - name: Check version change
+ id: version_check
+ continue-on-error: true
+ run: |
+ if [ ! -f "${{ env.CSPROJ_PATH }}" ]; then
+ echo "::error::Project file not found at ${{ env.CSPROJ_PATH }}"
+ echo "is_master=false" >> $GITHUB_OUTPUT
+ echo "can_publish=false" >> $GITHUB_OUTPUT
+ echo "version_specified=false" >> $GITHUB_OUTPUT
+ exit 1
+ fi
+ CURRENT_VERSION=$(grep -o '.*' ${{ env.CSPROJ_PATH }} | sed 's/\(.*\)<\/Version>/\1/')
+ if [ -z "$CURRENT_VERSION" ]; then
+ echo "::warning::Version tag not found in csproj file"
+ echo "can_publish=false" >> $GITHUB_OUTPUT
+ echo "version_specified=false" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+ echo "version_specified=true" >> $GITHUB_OUTPUT
+ echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
+ if [[ "${{ github.ref_name }}" == "master" || "${{ github.ref_name }}" == "main" ]]; then
+ echo "is_master=true" >> $GITHUB_OUTPUT
+ git fetch origin
+ if ! git ls-remote --exit-code --quiet origin refs/heads/master || ! git cat-file -e origin/master:${{ env.CSPROJ_PATH }} 2>/dev/null; then
+ echo "version_changed=true" >> $GITHUB_OUTPUT
+ echo "can_publish=true" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+ PREV_VERSION=$(git show origin/master:${{ env.CSPROJ_PATH }} 2>/dev/null | grep -o '.*' | sed 's/\(.*\)<\/Version>/\1/' || echo "")
+ if [ -z "$PREV_VERSION" ] || [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
+ echo "version_changed=true" >> $GITHUB_OUTPUT
+ else
+ echo "version_changed=false" >> $GITHUB_OUTPUT
+ fi
+ if [ -n "${{ secrets.NUGET_API_KEY }}" ] && [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
+ echo "api_key_available=true" >> $GITHUB_OUTPUT
+ echo "can_publish=true" >> $GITHUB_OUTPUT
+ else
+ echo "api_key_available=false" >> $GITHUB_OUTPUT
+ echo "can_publish=false" >> $GITHUB_OUTPUT
+ fi
+ else
+ echo "is_master=false" >> $GITHUB_OUTPUT
+ echo "can_publish=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: prepare
+ run: |
+ set -e
+ shopt -s nullglob
+ mkdir -p pkg/runtimes
+ mkdir -p pkg/buildTransitive
+ prefix="${{ env.ARTIFACT_PREFIX }}"
+ map() {
+ case "$1" in
+ ${prefix}-linux-aarch64*) echo linux-arm64 ;;
+ ${prefix}-linux-x86_64*) echo linux-x64 ;;
+ ${prefix}-osx-arm64*) echo osx-arm64 ;;
+ ${prefix}-osx-x86_64*) echo osx-x64 ;;
+ ${prefix}-win-*ARM64*) echo win-arm64 ;;
+ ${prefix}-win-*x64*) echo win-x64 ;;
+ *) return 1;;
+ esac
+ }
+ if [ -d "artifacts" ]; then
+ for dir in artifacts/*; do
+ [ -d "$dir" ] || continue
+ rid=$(map "$(basename "$dir")") || continue
+ native="pkg/runtimes/$rid/native"
+ mkdir -p "$native"
+ if [ -d "$dir/Release" ]; then
+ cp -R "$dir/Release"/. "$native/"
+ else
+ cp -R "$dir"/. "$native/"
+ fi
+ done
+ fi
+ cp ${{ env.CSPROJ_PATH }} pkg/ 2>/dev/null || echo "Project file not found"
+ cp LICENSE pkg/ 2>/dev/null || echo "LICENSE not found"
+ cp README.md pkg/ 2>/dev/null || echo "README.md not found"
+ if [ -d "docs" ]; then
+ mkdir -p pkg/docs
+ cp -R docs/* pkg/docs/ 2>/dev/null || echo "docs not found or empty"
+ fi
+ if [ -d "nuget/buildTransitive" ]; then
+ cp nuget/buildTransitive/*.props pkg/buildTransitive/ 2>/dev/null || echo "Props files not found"
+ cp nuget/buildTransitive/*.targets pkg/buildTransitive/ 2>/dev/null || echo "Targets files not found"
+ fi
+
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.x
+
+ - name: pack
+ working-directory: pkg
+ run: |
+ if [ ! -f ${{ env.CSPROJ_NAME }} ]; then
+ echo "::error::Project file not copied to package directory"
+ exit 1
+ fi
+ dotnet pack -c Release -o ../out
+
+ - name: Publish to NuGet
+ if: >-
+ steps.version_check.outputs.can_publish == 'true' &&
+ steps.version_check.outputs.is_master == 'true' &&
+ steps.version_check.outputs.version_changed == 'true' &&
+ steps.version_check.outputs.api_key_available == 'true' &&
+ steps.version_check.outputs.version_specified == 'true'
+ run: |
+ set -e
+ if [ -d "out" ] && [ "$(ls -A out 2>/dev/null)" ]; then
+ for pkg in out/*.nupkg; do
+ echo "Publishing package: $pkg"
+ dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source ${{ env.NUGET_SOURCE }} --skip-duplicate
+ done
+ else
+ echo "::error::No packages found to publish"
+ exit 1
+ fi
+
+ - name: Report publish skip reason
+ if: steps.version_check.outputs.can_publish != 'true'
+ run: |
+ if [ "${{ steps.version_check.outputs.version_specified }}" != "true" ]; then
+ echo "::warning::Publish skipped: version not specified"
+ elif [ "${{ steps.version_check.outputs.is_master }}" != "true" ]; then
+ echo "::warning::Publish skipped: not on master/main branch"
+ elif [ "${{ steps.version_check.outputs.version_changed }}" != "true" ]; then
+ echo "::warning::Publish skipped: version unchanged"
+ elif [ "${{ steps.version_check.outputs.api_key_available }}" != "true" ]; then
+ echo "::warning::Publish skipped: NuGet API key missing"
+ else
+ echo "::warning::Publish skipped: can_publish flag is false"
+ fi
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.ARTIFACT_PREFIX }}-nuget-packages
+ path: out/*.nupkg
\ No newline at end of file
diff --git a/nuget/SimpleCpp.Native.csproj b/nuget/SimpleCpp.Native.csproj
new file mode 100644
index 00000000..1bd2e513
--- /dev/null
+++ b/nuget/SimpleCpp.Native.csproj
@@ -0,0 +1,37 @@
+
+
+ SimpleCpp.Native
+ netstandard2.0
+ 1.3.2.0
+ Cross-platform native binaries for SimpleCpp.
+ Denis Kudelin
+ LICENSE
+ https://github.com/Itexoft/simplecpp
+ https://github.com/Itexoft/simplecpp
+ git
+ README.md
+ true
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/buildTransitive/SimpleCpp.Native.props b/nuget/buildTransitive/SimpleCpp.Native.props
new file mode 100644
index 00000000..135caeb7
--- /dev/null
+++ b/nuget/buildTransitive/SimpleCpp.Native.props
@@ -0,0 +1,26 @@
+
+
+
+ <_SimpleCpp_Rid Condition="'$(RuntimeIdentifier)' != ''">$(RuntimeIdentifier)
+
+
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$(OS)'=='Windows_NT' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='X64'">win-x64
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$(OS)'=='Windows_NT' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='Arm64'">win-arm64
+
+
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='X64'">linux-x64
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='Arm64'">linux-arm64
+
+
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='X64'">osx-x64
+ <_SimpleCpp_Rid Condition="'$(_SimpleCpp_Rid)'=='' and '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' and '$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)'=='Arm64'">osx-arm64
+
+
+ <_SimpleCpp_NativeRelativeLibPath>runtimes\$(_SimpleCpp_Rid)\native
+ <_SimpleCpp_NativeLibPath>$(MSBuildThisFileDirectory)\..\$(_SimpleCpp_NativeRelativeLibPath)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/buildTransitive/SimpleCpp.Native.targets b/nuget/buildTransitive/SimpleCpp.Native.targets
new file mode 100644
index 00000000..8939efbb
--- /dev/null
+++ b/nuget/buildTransitive/SimpleCpp.Native.targets
@@ -0,0 +1,13 @@
+
+
+ <_SimpleCpp_NativeLibs Include="$(_SimpleCpp_NativeLibPath)\*" />
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 410e716b84438357cee808125e964228f6878b7c Mon Sep 17 00:00:00 2001
From: Denis Kudelin <15978569+denis-kudelin@users.noreply.github.com>
Date: Mon, 28 Apr 2025 05:36:20 +0300
Subject: [PATCH 2/4] CI: enable multi-RID build and automated NuGet
pack/publish - fix nuget version
---
.github/workflows/nuget.yml | 54 +++++++++++++++++++----------------
nuget/SimpleCpp.Native.csproj | 2 +-
2 files changed, 30 insertions(+), 26 deletions(-)
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
index 56f0e0e1..8ad039d8 100644
--- a/.github/workflows/nuget.yml
+++ b/.github/workflows/nuget.yml
@@ -64,7 +64,8 @@ jobs:
- name: Check version change
id: version_check
- continue-on-error: true
+ env:
+ BRANCH_NAME: ${{ github.ref_name }}
run: |
if [ ! -f "${{ env.CSPROJ_PATH }}" ]; then
echo "::error::Project file not found at ${{ env.CSPROJ_PATH }}"
@@ -73,39 +74,42 @@ jobs:
echo "version_specified=false" >> $GITHUB_OUTPUT
exit 1
fi
+
CURRENT_VERSION=$(grep -o '.*' ${{ env.CSPROJ_PATH }} | sed 's/\(.*\)<\/Version>/\1/')
if [ -z "$CURRENT_VERSION" ]; then
- echo "::warning::Version tag not found in csproj file"
- echo "can_publish=false" >> $GITHUB_OUTPUT
echo "version_specified=false" >> $GITHUB_OUTPUT
+ echo "can_publish=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "version_specified=true" >> $GITHUB_OUTPUT
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
- if [[ "${{ github.ref_name }}" == "master" || "${{ github.ref_name }}" == "main" ]]; then
- echo "is_master=true" >> $GITHUB_OUTPUT
- git fetch origin
- if ! git ls-remote --exit-code --quiet origin refs/heads/master || ! git cat-file -e origin/master:${{ env.CSPROJ_PATH }} 2>/dev/null; then
- echo "version_changed=true" >> $GITHUB_OUTPUT
- echo "can_publish=true" >> $GITHUB_OUTPUT
- exit 0
- fi
- PREV_VERSION=$(git show origin/master:${{ env.CSPROJ_PATH }} 2>/dev/null | grep -o '.*' | sed 's/\(.*\)<\/Version>/\1/' || echo "")
- if [ -z "$PREV_VERSION" ] || [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
- echo "version_changed=true" >> $GITHUB_OUTPUT
- else
- echo "version_changed=false" >> $GITHUB_OUTPUT
- fi
- if [ -n "${{ secrets.NUGET_API_KEY }}" ] && [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
- echo "api_key_available=true" >> $GITHUB_OUTPUT
- echo "can_publish=true" >> $GITHUB_OUTPUT
- else
- echo "api_key_available=false" >> $GITHUB_OUTPUT
- echo "can_publish=false" >> $GITHUB_OUTPUT
- fi
- else
+
+ if [ "$BRANCH_NAME" != "master" ]; then
echo "is_master=false" >> $GITHUB_OUTPUT
echo "can_publish=false" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+ echo "is_master=true" >> $GITHUB_OUTPUT
+
+ git fetch --quiet
+ if git cat-file -e HEAD~1:${{ env.CSPROJ_PATH }} 2>/dev/null; then
+ PREV_VERSION=$(git show HEAD~1:${{ env.CSPROJ_PATH }} | grep -o '.*' | sed 's/\(.*\)<\/Version>/\1/')
+ else
+ PREV_VERSION=""
+ fi
+
+ if [ -z "$PREV_VERSION" ] || [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
+ echo "version_changed=true" >> $GITHUB_OUTPUT
+ else
+ echo "version_changed=false" >> $GITHUB_OUTPUT
+ fi
+
+ if [ -n "${{ secrets.NUGET_API_KEY }}" ] && [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
+ echo "api_key_available=true" >> $GITHUB_OUTPUT
+ echo "can_publish=true" >> $GITHUB_OUTPUT
+ else
+ echo "api_key_available=false" >> $GITHUB_OUTPUT
+ echo "can_publish=false" >> $GITHUB_OUTPUT
fi
- name: prepare
diff --git a/nuget/SimpleCpp.Native.csproj b/nuget/SimpleCpp.Native.csproj
index 1bd2e513..8262be9d 100644
--- a/nuget/SimpleCpp.Native.csproj
+++ b/nuget/SimpleCpp.Native.csproj
@@ -2,7 +2,7 @@
SimpleCpp.Native
netstandard2.0
- 1.3.2.0
+ 1.3.2.1
Cross-platform native binaries for SimpleCpp.
Denis Kudelin
LICENSE
From ea398010260cb9b909101b8c49fd753f5826c86e Mon Sep 17 00:00:00 2001
From: Denis Kudelin <15978569+denis-kudelin@users.noreply.github.com>
Date: Mon, 28 Apr 2025 09:19:53 +0300
Subject: [PATCH 3/4] build refactoring
---
.github/workflows/build-artifacts.yml | 13 ++
.github/workflows/multi-rid-build.yml | 259 --------------------------
.github/workflows/nuget-artifacts.yml | 20 ++
.github/workflows/nuget.yml | 208 ---------------------
4 files changed, 33 insertions(+), 467 deletions(-)
create mode 100644 .github/workflows/build-artifacts.yml
delete mode 100644 .github/workflows/multi-rid-build.yml
create mode 100644 .github/workflows/nuget-artifacts.yml
delete mode 100644 .github/workflows/nuget.yml
diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml
new file mode 100644
index 00000000..bc05c482
--- /dev/null
+++ b/.github/workflows/build-artifacts.yml
@@ -0,0 +1,13 @@
+name: build-artifacts
+
+on:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ build:
+ uses: Itexoft/DevOpsKit/.github/workflows/cpp-multi-rid-build.yml@master
+ with:
+ project_name: simplecpp
+ build_targets: simplecpp
+ cmake_cxx_standard: "17"
\ No newline at end of file
diff --git a/.github/workflows/multi-rid-build.yml b/.github/workflows/multi-rid-build.yml
deleted file mode 100644
index a66092d8..00000000
--- a/.github/workflows/multi-rid-build.yml
+++ /dev/null
@@ -1,259 +0,0 @@
-name: multi-rid-build
-on: [pull_request, workflow_dispatch]
-
-env:
- PROJECT_NAME: simplecpp
- BUILD_TARGETS: "simplecpp"
- BUILD_TESTING: OFF
- DEBUG_SYMBOLS: true
- CMAKE_BUILD_TYPE: Release
- CMAKE_CXX_STANDARD: 17
- CMAKE_CXX_STANDARD_REQUIRED: ON
- C_FLAGS_COMMON: "-w -fexceptions"
- CXX_FLAGS_COMMON: "-w -fexceptions"
- CMAKE_EXTRA_ARGS: ""
-
-jobs:
- windows:
- runs-on: windows-latest
- strategy:
- matrix:
- arch:
- - x64
- - ARM64
- steps:
- - uses: actions/checkout@v4
-
- - name: prepare-dirs
- shell: pwsh
- run: New-Item -ItemType Directory -Force -Path artifacts
-
- - name: install dlfcn-win32
- shell: pwsh
- run: |
- $triplet = ("${{ matrix.arch }}-windows").ToLower()
- vcpkg install dlfcn-win32 --triplet $triplet
-
- "VCPKG_INSTALLATION_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
- "VCPKG_TRIPLET=$triplet" | Out-File -FilePath $env:GITHUB_ENV -Append
- "VCPKG_INCLUDE=$env:VCPKG_INSTALLATION_ROOT\installed\$triplet\include" | Out-File -FilePath $env:GITHUB_ENV -Append
- "VCPKG_LIB=$env:VCPKG_INSTALLATION_ROOT\installed\$triplet\lib" | Out-File -FilePath $env:GITHUB_ENV -Append
-
- - id: detect-mingw
- shell: pwsh
- run: |
- if (
- (Test-Path 'C:\msys64\usr\bin\bash.exe') -and
- (Get-ChildItem -Recurse 'C:\msys64' -Filter llvm-objcopy.exe | Select-Object -First 1) -and
- (Get-ChildItem -Recurse 'C:\msys64' -Filter clang.exe | Select-Object -First 1)
- ) {
- "full=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
- } else {
- "full=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
- }
-
- - name: build-mingw
- if: steps.detect-mingw.outputs.full == 'true'
- run: |
- C:\msys64\usr\bin\bash.exe -lc '
- set -euo pipefail
- export PATH="$PATH:/c/Program Files/CMake/bin:/c/msys64/usr/bin:/c/msys64/mingw64/bin:/c/msys64/clang-arm64/bin:/c/msys64/ucrt64/bin"
- mkdir -p artifacts
- cmake -S . -B build/mingw/${{ matrix.arch }} -G Ninja \
- -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake \
- -DVCPKG_TARGET_TRIPLET=$VCPKG_TRIPLET \
- -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
- -DCMAKE_C_COMPILER=clang \
- -DCMAKE_CXX_COMPILER=clang++ \
- -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
- -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
- -DCMAKE_INCLUDE_PATH="$VCPKG_INCLUDE" \
- -DCMAKE_LIBRARY_PATH="$VCPKG_LIB" \
- -DCMAKE_C_FLAGS="$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g") ${{ env.C_FLAGS_COMMON }} -I$VCPKG_INCLUDE" \
- -DCMAKE_CXX_FLAGS="$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g") ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }} -I$VCPKG_INCLUDE" \
- -DCMAKE_EXE_LINKER_FLAGS="-L$VCPKG_LIB -ldlfcn-win32" \
- -DCMAKE_SHARED_LINKER_FLAGS="-L$VCPKG_LIB -ldlfcn-win32" \
- -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
- ${{ env.CMAKE_EXTRA_ARGS }}
- for tgt in ${{ env.BUILD_TARGETS }}; do
- cmake --build build/mingw/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
- done
- if [ "${{ env.DEBUG_SYMBOLS }}" = "true" ]; then
- OBJCOPY=$(command -v llvm-objcopy || command -v objcopy)
- for f in artifacts/*.dll; do
- [ -f "$f" ] && "$OBJCOPY" --only-keep-debug "$f" "$f.debug" && "$OBJCOPY" --strip-debug "$f"
- done
- fi
- '
-
- - name: check-lib-files
- if: steps.detect-mingw.outputs.full == 'false'
- shell: pwsh
- run: |
- Write-Host "Library files in VCPKG_LIB directory:"
- Get-ChildItem -Path $env:VCPKG_LIB -Filter "*.lib" | Select-Object -ExpandProperty Name
-
- - name: configure-vs
- if: steps.detect-mingw.outputs.full == 'false'
- shell: pwsh
- run: |
- $out = "$(Get-Location)\artifacts"
- $dbg = if ($env:DEBUG_SYMBOLS -eq 'true') { '/Zi' } else { '' }
- $linker = if ($env:DEBUG_SYMBOLS -eq 'true') { '/DEBUG' } else { '' }
- $defs = '/D_CRT_DECLARE_NONSTDC_NAMES=1 /D_CRT_NONSTDC_NO_DEPRECATE=1 /D_CRT_SECURE_NO_WARNINGS=1 /Dpopen=_popen /Dpclose=_pclose'
-
- $dlfcnLib = "$env:VCPKG_LIB\dlfcn-win32.lib"
- if (-not (Test-Path $dlfcnLib)) {
- $dlfcnLib = (Get-ChildItem -Path $env:VCPKG_LIB -Filter "dlfcn*.lib" | Select-Object -First 1).FullName
- if (-not $dlfcnLib) {
- $dlfcnLib = (Get-ChildItem -Path $env:VCPKG_LIB -Filter "*.lib" | Select-Object -First 1).FullName
- }
- }
-
- cmake -S . -B build/${{ matrix.arch }} -G "Visual Studio 17 2022" -A ${{ matrix.arch }} -T ClangCL `
- -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" `
- -DVCPKG_TARGET_TRIPLET="$env:VCPKG_TRIPLET" `
- -DCMAKE_PREFIX_PATH="$env:VCPKG_INSTALLATION_ROOT\installed\$env:VCPKG_TRIPLET" `
- -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} `
- -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} `
- -DCMAKE_INCLUDE_PATH="$env:VCPKG_INCLUDE" `
- -DCMAKE_LIBRARY_PATH="$env:VCPKG_LIB" `
- -DCMAKE_C_FLAGS="/w /EHsc $dbg $defs /I$env:VCPKG_INCLUDE" `
- -DCMAKE_CXX_FLAGS="/w /EHsc $dbg /std:c++${{ env.CMAKE_CXX_STANDARD }} $defs /I$env:VCPKG_INCLUDE" `
- -DCMAKE_EXE_LINKER_FLAGS="/LIBPATH:$env:VCPKG_LIB $dlfcnLib $linker" `
- -DCMAKE_SHARED_LINKER_FLAGS="/LIBPATH:$env:VCPKG_LIB $dlfcnLib $linker" `
- -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE="$out" `
- -DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE="$out" `
- -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE="$out" `
- -DBUILD_TESTING=${{ env.BUILD_TESTING }} `
- -DVCPKG_APPLOCAL_DEPS=ON `
- ${{ env.CMAKE_EXTRA_ARGS }}
-
- - name: build-vs
- if: steps.detect-mingw.outputs.full == 'false'
- shell: pwsh
- run: |
- foreach ($t in $env:BUILD_TARGETS.Split()) {
- cmake --build build/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $t
- }
-
- - uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-win-${{ matrix.arch }}
- path: artifacts/**
-
- linux:
- runs-on: ubuntu-latest
- strategy:
- matrix:
- triple:
- - x86_64-linux-gnu
- - aarch64-linux-gnu
- steps:
- - uses: actions/checkout@v4
- - uses: mlugg/setup-zig@v1
- with:
- version: 0.12.0
- use-cache: true
- - name: create-ccc
- run: |
- mkdir -p $HOME/bin
- printf '#!/bin/sh\nexec zig cc "$@"\n' > $HOME/bin/zigcc
- printf '#!/bin/sh\nexec zig c++ "$@"\n' > $HOME/bin/zigcxx
- chmod +x $HOME/bin/zigcc $HOME/bin/zigcxx
- echo "$HOME/bin" >> $GITHUB_PATH
- - name: configure
- run: |
- set -euo pipefail
- mkdir -p artifacts
- DBG=$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g" || echo "-g0")
- export CFLAGS="-O2 $DBG -ffunction-sections -fdata-sections ${{ env.C_FLAGS_COMMON }}"
- export CXXFLAGS="-O2 $DBG -ffunction-sections -fdata-sections ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }}"
- cmake -S . -B build/${{ matrix.triple }} -G Ninja \
- -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
- -DCMAKE_C_COMPILER=zigcc \
- -DCMAKE_CXX_COMPILER=zigcxx \
- -DCMAKE_C_COMPILER_TARGET=${{ matrix.triple }} \
- -DCMAKE_CXX_COMPILER_TARGET=${{ matrix.triple }} \
- -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
- -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
- -DCMAKE_EXE_LINKER_FLAGS="-Wl,-z,origin,-rpath,'$$ORIGIN'" \
- -DCMAKE_INSTALL_RPATH="$$ORIGIN" \
- -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
- -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--gc-sections" \
- -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
- -DDISABLE_CPP03_SYNTAX_CHECK=ON
- ${{ env.CMAKE_EXTRA_ARGS }}
- - name: build
- run: |
- for tgt in ${{ env.BUILD_TARGETS }}; do
- cmake --build build/${{ matrix.triple }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
- done
- - name: split-debug
- if: env.DEBUG_SYMBOLS == 'true'
- run: |
- set -euo pipefail
- shopt -s nullglob globstar
- OBJCOPY=$(command -v llvm-objcopy-18 || command -v llvm-objcopy || command -v objcopy)
- for lib in **/*.so; do
- "$OBJCOPY" --only-keep-debug "$lib" "$lib.debug"
- "$OBJCOPY" --add-gnu-debuglink="$lib.debug" "$lib"
- done
- - uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-linux-${{ matrix.triple }}
- path: artifacts/**
-
- macos:
- runs-on: macos-latest
- strategy:
- matrix:
- arch:
- - x86_64
- - arm64
- steps:
- - uses: actions/checkout@v4
- - name: configure
- run: |
- set -euo pipefail
- mkdir -p artifacts
- DBG=$([ "${{ env.DEBUG_SYMBOLS }}" = "true" ] && echo "-g" || echo "-g0")
- cmake -S . -B build/${{ matrix.arch }} -G Ninja \
- -DCMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
- -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \
- -DCMAKE_CXX_STANDARD=${{ env.CMAKE_CXX_STANDARD }} \
- -DCMAKE_CXX_STANDARD_REQUIRED=${{ env.CMAKE_CXX_STANDARD_REQUIRED }} \
- -DCMAKE_C_FLAGS="$DBG ${{ env.C_FLAGS_COMMON }}" \
- -DCMAKE_CXX_FLAGS="$DBG ${{ env.CXX_FLAGS_COMMON }} -std=c++${{ env.CMAKE_CXX_STANDARD }}" \
- -DCMAKE_MACOSX_RPATH=ON \
- -DCMAKE_INSTALL_RPATH="@loader_path" \
- -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
- -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
- -DCMAKE_EXE_LINKER_FLAGS="-Wl,-rpath,@loader_path" \
- -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=$(pwd)/artifacts \
- -DBUILD_TESTING=${{ env.BUILD_TESTING }} \
- ${{ env.CMAKE_EXTRA_ARGS }}
- - name: build
- run: |
- for tgt in ${{ env.BUILD_TARGETS }}; do
- cmake --build build/${{ matrix.arch }} --parallel --config ${{ env.CMAKE_BUILD_TYPE }} --target $tgt
- done
- - name: dsym
- if: env.DEBUG_SYMBOLS == 'true'
- run: |
- shopt -s nullglob
- for dylib in artifacts/*.dylib; do
- dsymutil "$dylib"
- done
- - uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PROJECT_NAME }}-osx-${{ matrix.arch }}
- path: artifacts/**
\ No newline at end of file
diff --git a/.github/workflows/nuget-artifacts.yml b/.github/workflows/nuget-artifacts.yml
new file mode 100644
index 00000000..d596f8ad
--- /dev/null
+++ b/.github/workflows/nuget-artifacts.yml
@@ -0,0 +1,20 @@
+name: nuget-artifacts
+
+on:
+ workflow_run:
+ workflows: [build-artifacts]
+ types: [completed]
+ workflow_dispatch:
+
+jobs:
+ pack:
+ if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
+ uses: Itexoft/DevOpsKit/.github/workflows/nuget-package-publish.yml@master
+ secrets: inherit
+ with:
+ project_name: simplecpp
+ csproj_path: nuget/SimpleCpp.Native.csproj
+ build_workflow: build-artifacts
+ extra_paths: docs
+ publish_branch: master
+ publish: false
\ No newline at end of file
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
deleted file mode 100644
index 8ad039d8..00000000
--- a/.github/workflows/nuget.yml
+++ /dev/null
@@ -1,208 +0,0 @@
-# NuGet package publishing workflow
-name: nuget
-on:
- workflow_run:
- workflows: [multi-rid-build]
- types: [completed]
- workflow_dispatch:
-
-env:
- NUGET_SOURCE: https://api.nuget.org/v3/index.json
- CSPROJ_NAME: SimpleCpp.Native.csproj
- ARTIFACT_PREFIX: simplecpp
-
-jobs:
- pack:
- if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
- runs-on: ubuntu-latest
-
- steps:
- - name: Set project path
- run: echo "CSPROJ_PATH=nuget/${{ env.CSPROJ_NAME }}" >> $GITHUB_ENV
-
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: determine artifact run id
- id: run_id
- env:
- GH_TOKEN: ${{ github.token }}
- run: |
- if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
- RID=$(gh api "/repos/${{ github.repository }}/actions/workflows/multi-rid-build.yml/runs?status=success&per_page=1" --jq '.workflow_runs[0].id')
- if [ -z "$RID" ]; then
- echo "::error::No successful multi-rid-build runs found"
- RID="none"
- fi
- else
- RID=${{ github.event.workflow_run.id }}
- fi
- echo "run_id=$RID" >> $GITHUB_OUTPUT
- echo "Using artifacts from run ID: $RID"
-
- - uses: actions/download-artifact@v4
- if: steps.run_id.outputs.run_id != 'none'
- continue-on-error: true
- with:
- path: artifacts
- run-id: ${{ steps.run_id.outputs.run_id }}
- github-token: ${{ github.token }}
-
- - name: Create artifacts directory if it doesn't exist
- run: mkdir -p artifacts
-
- - name: Validate artifacts
- id: validate_artifacts
- run: |
- ARTIFACT_COUNT=$(find artifacts -type f | wc -l)
- if [ "$ARTIFACT_COUNT" -eq 0 ]; then
- echo "::error::No artifacts found from the build"
- exit 1
- fi
- echo "has_artifacts=true" >> $GITHUB_OUTPUT
-
- - name: Check version change
- id: version_check
- env:
- BRANCH_NAME: ${{ github.ref_name }}
- run: |
- if [ ! -f "${{ env.CSPROJ_PATH }}" ]; then
- echo "::error::Project file not found at ${{ env.CSPROJ_PATH }}"
- echo "is_master=false" >> $GITHUB_OUTPUT
- echo "can_publish=false" >> $GITHUB_OUTPUT
- echo "version_specified=false" >> $GITHUB_OUTPUT
- exit 1
- fi
-
- CURRENT_VERSION=$(grep -o '.*' ${{ env.CSPROJ_PATH }} | sed 's/\(.*\)<\/Version>/\1/')
- if [ -z "$CURRENT_VERSION" ]; then
- echo "version_specified=false" >> $GITHUB_OUTPUT
- echo "can_publish=false" >> $GITHUB_OUTPUT
- exit 0
- fi
- echo "version_specified=true" >> $GITHUB_OUTPUT
- echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
-
- if [ "$BRANCH_NAME" != "master" ]; then
- echo "is_master=false" >> $GITHUB_OUTPUT
- echo "can_publish=false" >> $GITHUB_OUTPUT
- exit 0
- fi
- echo "is_master=true" >> $GITHUB_OUTPUT
-
- git fetch --quiet
- if git cat-file -e HEAD~1:${{ env.CSPROJ_PATH }} 2>/dev/null; then
- PREV_VERSION=$(git show HEAD~1:${{ env.CSPROJ_PATH }} | grep -o '.*' | sed 's/\(.*\)<\/Version>/\1/')
- else
- PREV_VERSION=""
- fi
-
- if [ -z "$PREV_VERSION" ] || [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
- echo "version_changed=true" >> $GITHUB_OUTPUT
- else
- echo "version_changed=false" >> $GITHUB_OUTPUT
- fi
-
- if [ -n "${{ secrets.NUGET_API_KEY }}" ] && [ "$PREV_VERSION" != "$CURRENT_VERSION" ]; then
- echo "api_key_available=true" >> $GITHUB_OUTPUT
- echo "can_publish=true" >> $GITHUB_OUTPUT
- else
- echo "api_key_available=false" >> $GITHUB_OUTPUT
- echo "can_publish=false" >> $GITHUB_OUTPUT
- fi
-
- - name: prepare
- run: |
- set -e
- shopt -s nullglob
- mkdir -p pkg/runtimes
- mkdir -p pkg/buildTransitive
- prefix="${{ env.ARTIFACT_PREFIX }}"
- map() {
- case "$1" in
- ${prefix}-linux-aarch64*) echo linux-arm64 ;;
- ${prefix}-linux-x86_64*) echo linux-x64 ;;
- ${prefix}-osx-arm64*) echo osx-arm64 ;;
- ${prefix}-osx-x86_64*) echo osx-x64 ;;
- ${prefix}-win-*ARM64*) echo win-arm64 ;;
- ${prefix}-win-*x64*) echo win-x64 ;;
- *) return 1;;
- esac
- }
- if [ -d "artifacts" ]; then
- for dir in artifacts/*; do
- [ -d "$dir" ] || continue
- rid=$(map "$(basename "$dir")") || continue
- native="pkg/runtimes/$rid/native"
- mkdir -p "$native"
- if [ -d "$dir/Release" ]; then
- cp -R "$dir/Release"/. "$native/"
- else
- cp -R "$dir"/. "$native/"
- fi
- done
- fi
- cp ${{ env.CSPROJ_PATH }} pkg/ 2>/dev/null || echo "Project file not found"
- cp LICENSE pkg/ 2>/dev/null || echo "LICENSE not found"
- cp README.md pkg/ 2>/dev/null || echo "README.md not found"
- if [ -d "docs" ]; then
- mkdir -p pkg/docs
- cp -R docs/* pkg/docs/ 2>/dev/null || echo "docs not found or empty"
- fi
- if [ -d "nuget/buildTransitive" ]; then
- cp nuget/buildTransitive/*.props pkg/buildTransitive/ 2>/dev/null || echo "Props files not found"
- cp nuget/buildTransitive/*.targets pkg/buildTransitive/ 2>/dev/null || echo "Targets files not found"
- fi
-
- - uses: actions/setup-dotnet@v4
- with:
- dotnet-version: 8.x
-
- - name: pack
- working-directory: pkg
- run: |
- if [ ! -f ${{ env.CSPROJ_NAME }} ]; then
- echo "::error::Project file not copied to package directory"
- exit 1
- fi
- dotnet pack -c Release -o ../out
-
- - name: Publish to NuGet
- if: >-
- steps.version_check.outputs.can_publish == 'true' &&
- steps.version_check.outputs.is_master == 'true' &&
- steps.version_check.outputs.version_changed == 'true' &&
- steps.version_check.outputs.api_key_available == 'true' &&
- steps.version_check.outputs.version_specified == 'true'
- run: |
- set -e
- if [ -d "out" ] && [ "$(ls -A out 2>/dev/null)" ]; then
- for pkg in out/*.nupkg; do
- echo "Publishing package: $pkg"
- dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source ${{ env.NUGET_SOURCE }} --skip-duplicate
- done
- else
- echo "::error::No packages found to publish"
- exit 1
- fi
-
- - name: Report publish skip reason
- if: steps.version_check.outputs.can_publish != 'true'
- run: |
- if [ "${{ steps.version_check.outputs.version_specified }}" != "true" ]; then
- echo "::warning::Publish skipped: version not specified"
- elif [ "${{ steps.version_check.outputs.is_master }}" != "true" ]; then
- echo "::warning::Publish skipped: not on master/main branch"
- elif [ "${{ steps.version_check.outputs.version_changed }}" != "true" ]; then
- echo "::warning::Publish skipped: version unchanged"
- elif [ "${{ steps.version_check.outputs.api_key_available }}" != "true" ]; then
- echo "::warning::Publish skipped: NuGet API key missing"
- else
- echo "::warning::Publish skipped: can_publish flag is false"
- fi
-
- - uses: actions/upload-artifact@v4
- with:
- name: ${{ env.ARTIFACT_PREFIX }}-nuget-packages
- path: out/*.nupkg
\ No newline at end of file
From 7d9aa0cb7e260ad08cd59bf832bb1382be048220 Mon Sep 17 00:00:00 2001
From: Denis Kudelin <15978569+denis-kudelin@users.noreply.github.com>
Date: Thu, 1 May 2025 05:49:42 +0300
Subject: [PATCH 4/4] add capi-bundle
---
.github/workflows/build-shim.yml | 43 ++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 .github/workflows/build-shim.yml
diff --git a/.github/workflows/build-shim.yml b/.github/workflows/build-shim.yml
new file mode 100644
index 00000000..3f225f44
--- /dev/null
+++ b/.github/workflows/build-shim.yml
@@ -0,0 +1,43 @@
+name: capi-bundle
+on:
+ workflow_run:
+ workflows: ["nuget-artifacts"]
+ types: [completed]
+
+jobs:
+ bundle:
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
+ runs-on: ubuntu-latest
+ env:
+ CAPI_BUNDLE_DIR: capi-bundle
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/download-artifact@v4
+ with:
+ path: _all_artifacts
+
+ - name: assemble
+ shell: bash
+ run: |
+ set -euo pipefail
+ root="$CAPI_BUNDLE_DIR"
+ mkdir -p "$root/include"
+ cp -r include/. "$root/include/"
+ find _all_artifacts -name 'compile_commands.json' | while read json; do
+ rid=$(basename "$(dirname "$json")")
+ cp "$json" "$root/${rid}-compile_commands.json"
+ jq -r '.[].file' "$json" | grep -E '\.(h|hpp)$' | while read hdr; do
+ [ -f "$hdr" ] || continue
+ abs=$(realpath "$hdr")
+ rel=${abs#$(pwd)/}
+ mkdir -p "$root/include/$(dirname "$rel")"
+ cp -f "$abs" "$root/include/$rel"
+ done
+ done
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: capi-bundle
+ path: ${{ env.CAPI_BUNDLE_DIR }}/**
\ No newline at end of file