diff --git a/.github/workflows/test-build-workflow.yml b/.github/workflows/test-build-workflow.yml new file mode 100644 index 0000000..7bce5a0 --- /dev/null +++ b/.github/workflows/test-build-workflow.yml @@ -0,0 +1,315 @@ +name: Test Build Workflow + +on: + schedule: + - cron: '0 0 * * *' # Run daily at midnight + workflow_dispatch: + push: + branches: [ master ] + tags: + - 'v1' + - 'v1-test' + paths: + - 'action.yml' + - '.github/workflows/test-build-workflow.yml' + pull_request: + branches: [ master ] + paths: + - 'action.yml' + - '.github/workflows/test-build-workflow.yml' + +jobs: + test-binary-build: + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: i686-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + use-pgo: true # x64 host to aarch64 simulated guest via cross + use-cross: true + - os: ubuntu-latest + target: armv7-unknown-linux-gnueabihf + use-pgo: true # x64 host to armv7 simulated guest via cross + use-cross: true + - os: windows-latest + target: x86_64-pc-windows-msvc + use-pgo: true + use-cross: false + - os: windows-latest + target: i686-pc-windows-msvc + use-pgo: true + use-cross: false + - os: windows-latest + target: aarch64-pc-windows-msvc + use-pgo: false # no virtualization support (proprietary OS) + use-cross: false + - os: macos-13 # x86 + target: x86_64-apple-darwin + use-pgo: true + use-cross: false + - os: macos-14 # M1 + target: aarch64-apple-darwin + use-pgo: true + use-cross: false + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Binary Build + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + target: ${{ matrix.target }} + use-pgo: ${{ matrix.use-pgo }} + use-cross: ${{ matrix.use-cross }} + rust-project-path: "tools/cli" + crate-name: "prs-rs-cli" + upload-artifacts: false + + test-library-build: + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: i686-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + use-pgo: true # x64 host to aarch64 simulated guest via cross + use-cross: true + - os: ubuntu-latest + target: armv7-unknown-linux-gnueabihf + use-pgo: true # x64 host to armv7 simulated guest via cross + use-cross: true + - os: windows-latest + target: x86_64-pc-windows-msvc + use-pgo: true + use-cross: false + - os: windows-latest + target: i686-pc-windows-msvc + use-pgo: true + use-cross: false + # No native host to run tests and proprietary compiler. + #- os: windows-latest + # target: aarch64-pc-windows-msvc + # use-pgo: false # no virtualization support (proprietary OS) + # use-cross: false + - os: macos-13 # x86 + target: x86_64-apple-darwin + use-pgo: true + use-cross: false + - os: macos-14 # M1 + target: aarch64-apple-darwin + use-pgo: true + use-cross: false + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Library Build + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: ${{ matrix.target }} + use-pgo: ${{ matrix.use-pgo }} + use-cross: ${{ matrix.use-cross }} + features: "c-exports" + build-library: true + upload-artifacts: false + run-tests-and-coverage: true + upload-coverage-to-codecov: false + + # This tests gathering PGO data on a host, and building for a different target. + test-pgo-with-cross-compile: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test PGO with Cross-Compilation (Binary) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + rust-project-path: tools/cli + pgo-project-path: . + crate-name: prs-rs-cli + target: aarch64-unknown-linux-gnu # x64 host to aarch64 simulated guest + use-pgo: true + use-cross: true + pgo-benchmark-name: my_benchmark + upload-artifacts: false + - name: Test PGO with Cross-Compilation (Library) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: aarch64-unknown-linux-gnu # x64 host to to aarch64 simulated guest + use-pgo: true + use-cross: true + pgo-benchmark-name: my_benchmark + upload-artifacts: false + build-library: true + + test-library-feature-build: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Library Feature Build + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + features: c-exports,std + upload-artifacts: false + build-library: true + + test-library-no-default-features: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Library No Default Features + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + no-default-features: true + features: std + upload-artifacts: false + build-library: true + + test-binary-pgo-with-library: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Binary PGO with Library + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + rust-project-path: tools/cli + pgo-project-path: . + crate-name: prs-rs-cli + target: x86_64-unknown-linux-gnu + use-pgo: true + pgo-benchmark-name: my_benchmark + upload-artifacts: false + + test-library-pgo: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Library PGO + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + use-pgo: true + pgo-benchmark-name: my_benchmark + upload-artifacts: false + build-library: true + + test-custom-rustflags: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + - name: Test Custom RUSTFLAGS (Binary) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + rust-project-path: tools/cli + crate-name: prs-rs-cli + target: x86_64-unknown-linux-gnu + additional-rustflags: -C opt-level=3 + upload-artifacts: false + - name: Test Custom RUSTFLAGS (Library) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + additional-rustflags: -C opt-level=3 + upload-artifacts: false + build-library: true + + test-artifact-upload: + runs-on: ubuntu-latest + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: 149060527e685360687d7332742ac016b39af8a7 + + - name: Test Artifact Upload (Binary) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + rust-project-path: tools/cli + crate-name: prs-rs-cli + target: x86_64-unknown-linux-gnu + + - name: Download Binary Artifact + uses: actions/download-artifact@v4 + with: + name: prs-rs-cli-x86_64-unknown-linux-gnu- + + - name: Assert Binary Artifact + shell: bash + run: | + if [ ! -f prs-rs-cli ]; then + echo "Binary artifact not found" + exit 1 + fi + + - name: Test Artifact Upload (Library) + uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + build-library: true + + - name: Download Library Artifact + uses: actions/download-artifact@v4 + with: + name: C-Library-x86_64-unknown-linux-gnu- + + - name: Assert Library Artifact + shell: bash + run: | + if [ ! -f libprs_rs.a ] || [ ! -f libprs_rs.so ]; then + echo "Library artifacts not found" + exit 1 + fi \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a91fae5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2023 Sewer56 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..68b0f70 --- /dev/null +++ b/README.MD @@ -0,0 +1,254 @@ +
+ +This is a GitHub Action that can be used to build an optimized, lightweight binary (or C library) +from a Rust project. + +This action is used to build binaries with the following properties: + +- **Self-Built std**: Reduces binary size and improves optimizations. +- **Abort on Panic**: Reduces binary size. Can be disabled if needed. +- **Profile Guided Optimization (PGO)**: Improves performance by optimizing based on usage patterns. +- **Cross-Compilation**: Supports cross-compilation using `cross-rs`. +- **Nightly Rust**: Uses the nightly Rust toolchain for building and running. +- **Tests and Coverage**: Optionally run tests and generate coverage reports using the `devops-rust-test-and-coverage` action. + +It can be used to build both binaries and C libraries. + +## Example Usage + +As a single job/step of a workflow: + +```yaml +test-binary-build: + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: i686-unknown-linux-gnu + use-pgo: true + use-cross: false + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + use-pgo: false # no native runner + use-cross: true + - os: ubuntu-latest + target: armv7-unknown-linux-gnueabihf + use-pgo: false # no native runner + use-cross: true + - os: windows-latest + target: x86_64-pc-windows-msvc + use-pgo: true + use-cross: false + - os: windows-latest + target: i686-pc-windows-msvc + use-pgo: true + use-cross: false + - os: windows-latest + target: aarch64-pc-windows-msvc + use-pgo: false # no native runner + use-cross: false + - os: macos-13 # x86 + target: x86_64-apple-darwin + use-pgo: true + use-cross: false + - os: macos-14 # M1 + target: aarch64-apple-darwin + use-pgo: true + use-cross: false + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Test Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: d08599ed5473616f57d57a0966939e1a5dbda9b4 + - name: Test Binary Build + uses: Reloaded-Project/devops-rust-lightweight-binary@v1 + with: + target: ${{ matrix.target }} + use-pgo: ${{ matrix.use-pgo }} + use-cross: ${{ matrix.use-cross }} + rust-project-path: "tools/cli/" + crate-name: "prs-rs-cli" + upload-artifacts: false + run-tests-and-coverage: true +``` + +## Setup + +To use this action in your own repository: + +1. Create a new workflow file (e.g., `.github/workflows/build-c-library.yml`) in your repository. +2. Copy the example usage job from above into the new workflow file. +3. Customize the input parameters as needed for your project. + +## Configuration + +### Inputs + +| Input | Required | Default | Description | +| ---------------------------- | -------- | ---------------- | -------------------------------------------------------------------------------------- | +| `rust-project-path` | No | `.` | Path to the Rust project | +| `pgo-project-path` | No | `.` | Path to the Rust project used for gathering PGO data. Can be same or separate project. | +| `crate-name` | Yes | | Name of the Rust crate (used to determine file name) | +| `target` | Yes | | The target platform for the Rust compiler | +| `features` | No | `''` | Comma-separated list of features to include in the build | +| `no-default-features` | No | `false` | Do not include default features in the build | +| `use-pgo` | No | `false` | Use Profile-Guided Optimization [PGO] to build the library. | +| `pgo-benchmark-name` | No | `'my_benchmark'` | Benchmark name to use with PGO. | +| `use-cross` | No | `false` | Use cross-rs for building. If false, use cargo. | +| `additional-rustflags` | No | `''` | Additional RUSTFLAGS to pass to the Rust compiler | +| `upload-artifacts` | No | `true` | Upload the built artifacts as a GitHub Actions artifact | +| `abort-on-panic` | No | `true` | Abort immediately on panic. If false, the default panic handler is used. | +| `build-library` | No | `false` | Build a library instead of a binary. | +| `run-tests-and-coverage` | No | `false` | Run tests and coverage using the `devops-rust-test-and-coverage` action. | +| `upload-coverage-to-codecov` | No | `true` | Uploads coverage to codecov if `run-tests-and-coverage` is enabled. | + +### Setting up Profile-Guided Optimization (PGO) + +Profile-Guided Optimization works by compiling and executing a benchmark whose name and project +can be defined by `pgo-benchmark-name` and `pgo-project-path` respectively. So you should strive +to keep the benchmark as close to the final usage of your application as possible. + +A benchmark for PGO can be defined as follows: + +```rust +// Regular benchmarks, not PGO +#[cfg(not(feature = "pgo"))] +{ + bench_estimate(c); + bench_decompress(c); + bench_compress_file(c); + bench_create_dict(c); +} + +// Benchmark with realistic usage patterns for PGO. +#[cfg(feature = "pgo")] +{ + generate_pgo_data(); +} +``` + +Then said profile is used to build the final version of your application. + +For PGO to work, the `target` platform must be the same as the host that generated the profiling +data. Sometimes you can get away with using `cross` to achieve this, for example: + +```yaml +# Host is x86-linux but this seems to work just a-ok! +target: aarch64-unknown-linux-gnu # x64 host to to aarch64 simulated guest +use-pgo: true +use-cross: true +``` + +If the process fails, your CI will fail, so do experiment. + +## Running Tests and Coverage + +To run tests and generate coverage reports as part of the build process, set the +`run-tests-and-coverage` input to `true`. + +This will invoke the [devops-rust-test-and-coverage][devops-test-coverage] action after the build +step, using the same configuration as the build (e.g., `target`, `features`, `use-cross`, etc.). + +The `devops-rust-test-and-coverage` action will run tests using either `cargo` or `cross`, +depending on the `use-cross` input. If `use-cross` is `false`, it will also generate a coverage +report using Tarpaulin and upload it to Codecov (if `upload-coverage` is `true`). + +Note that code coverage is skipped when using `cross` due to incompatibility with Tarpaulin. + +## Building Libraries + +To build a library instead of a binary, set the `build-library` input to `true`. +This is equivalent to setting `crate-type = ["cdylib", "staticlib"]` in `Cargo.toml`. + +When building a library, the generated artifacts will include static libraries (`.a`, `.lib`) +and dynamic libraries (`.so`, `.dll`, `.dylib`) depending on the target platform. + +## Examples + +Find more examples in [the tests](./.github/workflows/test-rust-build-c-library-workflow.yml). + +### Custom PGO Project Path + +```yaml +- name: Build C Library + uses: Reloaded-Project/devops-rust-lightweight-binary@v1 + with: + rust-project-path: ./rust-project + pgo-project-path: ./pgo-project + crate-name: my-crate + target: x86_64-unknown-linux-gnu +``` + +### Using cross-rs for Building + +```yaml +- name: Build C Library + uses: Reloaded-Project/devops-rust-lightweight-binary@v1 + with: + crate-name: my-crate + target: x86_64-unknown-linux-gnu + use-cross: true +``` + +### Custom Additional RUSTFLAGS + +```yaml +- name: Build C Library + uses: Reloaded-Project/devops-rust-lightweight-binary@v1 + with: + crate-name: my-crate + target: x86_64-unknown-linux-gnu + additional-rustflags: -C opt-level=3 +``` + +## Accessing the Built Artifacts + +After a successful run, the built artifacts will be available as a downloadable +artifact in the GitHub Actions run. + +For binary builds, the artifact will be named `${{ inputs.crate-name }}-${{ inputs.target }}-${{ inputs.features }}`. + +For library builds, the artifact will be named `C-Library-${{ inputs.target }}-${{ inputs.features }}`. + +To access the artifacts: + +1. Navigate to the Actions tab in your repository. +2. Click on the workflow run that built the artifacts. +3. In the "Artifacts" section, you will find the generated artifacts, which you can download. + +## Why this Exists? + +Building C libraries from Rust projects can be a complex process, especially when +considering different target platforms, compiler flags, and optimizations like PGO. + +This action simplifies the process by providing a configurable and reusable workflow +that handles the building of C libraries from Rust projects. + +## Contributing + +Contributions are welcome! If you encounter any issues or have suggestions for improvements, +please open an issue or submit a pull request in this repository. + +## License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. + +[devops-test-coverage]: https://github.com/Reloaded-Project/devops-rust-test-and-coverage \ No newline at end of file diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..cdb2a58 --- /dev/null +++ b/action.yml @@ -0,0 +1,241 @@ +name: 'Build Optimized Rust Binary' +description: 'Builds a min sized Rust binary or library. With self-built std, abort on panic, PGO and cross-compilation support.' +branding: + icon: 'check' + color: 'red' + +inputs: + rust-project-path: + description: 'Path to the Rust project' + required: false + default: '.' + pgo-project-path: + description: 'Path to the Rust project used for gathering PGO data. Can be same or separate project.' + required: false + default: '.' + crate-name: + description: 'Name of the Rust crate (used to determine file name)' + required: true + target: + description: 'The target platform for the Rust compiler' + required: true + features: + description: 'Comma-separated list of features to include in the build' + required: false + default: '' + no-default-features: + description: 'Do not include default features in the build' + required: false + default: false + use-pgo: + description: 'Use Profile-Guided Optimization [PGO] to build the artifact.' + required: false + default: false + pgo-benchmark-name: + description: 'Benchmark name to use with PGO.' + required: false + default: 'my_benchmark' + use-cross: + description: 'Use cross-rs for building. If false, use cargo.' + required: false + default: false + additional-rustflags: + description: 'Additional RUSTFLAGS to pass to the Rust compiler' + required: false + default: '' + upload-artifacts: + description: 'Upload the built artifacts as a GitHub Actions artifact' + required: false + default: true + abort-on-panic: + description: 'Abort immediately on panic. If false, the default panic handler is used.' + required: false + default: true + build-library: + description: 'Build a library instead of a binary. Requires `crate-type = ["cdylib", "staticlib"]` in Cargo.toml.' + required: false + default: false + run-tests-and-coverage: + description: 'Run tests and coverage using the `devops-rust-test-and-coverage` action.' + required: false + default: false + upload-coverage-to-codecov: + description: 'Uploads coverage to codecov if `run-tests-and-coverage` is enabled.' + required: false + default: true + codecov-token: + description: 'Codecov token for uploading coverage' + required: false + +runs: + using: 'composite' + steps: + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + matcher: false + cache: false + toolchain: nightly + + - name: Setup Rust Caching + uses: Swatinem/rust-cache@v2 + with: + key: ${{ inputs.rust-project-path }}+${{ inputs.target }} + cache-on-failure: true + workspaces: | + ${{ inputs.rust-project-path }} -> target + + - name: Install gcc-multilib (if on Ubuntu based System, and Target is not Host) + if: inputs.use-cross == 'false' && runner.os == 'Linux' + shell: bash + run: | + # Get host triple + HOST_TARGET=$(rustc -vV | sed -n 's|host: ||p') + echo "Host target: $HOST_TARGET" + echo "Target: ${{ inputs.target }}" + + if [ "$HOST_TARGET" != "${{ inputs.target }}" ]; then + echo "Target is different from host. Installing gcc-multilib..." + sudo apt-get update || true + sudo apt-get install -y gcc-multilib || true + else + echo "Target is the same as host. Skipping gcc-multilib installation." + fi + + - name: Setup Rust Toolchain + shell: bash + working-directory: ${{ inputs.rust-project-path }} + run: | + rustup target add ${{ inputs.target }} + rustup component add rust-src --toolchain nightly + rustup toolchain install nightly-${{ inputs.target }} --force-non-host + + # Install cross-rs if needed + if [ "${{ inputs.use-cross }}" == "true" ]; then + cargo install cross --git https://github.com/cross-rs/cross + fi + + - name: Build Rust Project + shell: bash + run: | + # Setup build variables + BUILD_CMD="cargo" + if [ "${{ inputs.use-cross }}" == "true" ]; then + BUILD_CMD="cross" + fi + + BUILD_FEATURES_ARGS="${{ inputs.features }}" + NO_DEFAULT_FEATURES="" + if [ "${{ inputs.no-default-features }}" == "true" ]; then + NO_DEFAULT_FEATURES="--no-default-features" + fi + + CRATE_TYPES="" + if [ "${{ inputs.build-library }}" == "true" ]; then + CRATE_TYPES="--crate-type cdylib --crate-type staticlib" + fi + + export RUSTFLAGS="${{ inputs.additional-rustflags }} -Zlocation-detail=none -C lto=fat" + if [ "${{ inputs.abort-on-panic }}" == "true" ]; then + export RUSTFLAGS="$RUSTFLAGS -C panic=abort" + BUILD_STD_ARGS="-Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort" + else + BUILD_STD_ARGS="-Z build-std=std" + fi + + # Handle PGO + if [ "${{ inputs.use-pgo }}" == "true" ]; then + rustup component add llvm-tools-preview + + # Normalize pgo-project-path for PGO, because it doesn't handle double slashes + # (user error) well. + PGO_PROJECT_PATH="${{ inputs.pgo-project-path }}" + PGO_PROJECT_PATH="${PGO_PROJECT_PATH%/}" # Remove trailing forward slash + PGO_PROJECT_PATH="${PGO_PROJECT_PATH%\\}" # Remove trailing backslash + + # Generate PGO profiling data + RUSTFLAGS_BACKUP="$RUSTFLAGS" + PGO_PROFILES_FOLDER="${GITHUB_WORKSPACE}/${PGO_PROJECT_PATH}/target/pgo-profiles" + export RUSTFLAGS="$RUSTFLAGS -Cprofile-generate=$PGO_PROFILES_FOLDER" + + cd "${GITHUB_WORKSPACE}/${PGO_PROJECT_PATH}" + echo "Flags: $RUSTFLAGS" + echo "$BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features \"$BUILD_FEATURES_ARGS,pgo\" $NO_DEFAULT_FEATURES" + $BUILD_CMD +nightly test --bench ${{ inputs.pgo-benchmark-name }} --release --target ${{ inputs.target }} --features "$BUILD_FEATURES_ARGS,pgo" $NO_DEFAULT_FEATURES + + # Check if .profraw files were created + echo "Profiles Folder: $PGO_PROFILES_FOLDER" + ls "$PGO_PROFILES_FOLDER" + if [ ! -f "$PGO_PROFILES_FOLDER/"*.profraw ]; then + echo "::error::No .profraw files were created during the PGO run. PGO data generation failed." + exit 1 + fi + + # Merge the PGO profiles + # This is tricky, llvm-profdata isn't in $PATH, so we need to find it ourselves. + target_libdir=$(rustc --print target-libdir) + bin_dir=$(dirname "$target_libdir")/bin + llvm_profdata_path=$(find "$bin_dir" -name "llvm-profdata*" | head -n 1) + + MERGED_PGO_PROFILE=$PGO_PROFILES_FOLDER/merged.profdata + $llvm_profdata_path merge -o "$MERGED_PGO_PROFILE" "$PGO_PROFILES_FOLDER" + + # Assert merged.profdata is not empty + echo "Merged Profiles Folder: $PGO_PROFILES_FOLDER" + ls "$PGO_PROFILES_FOLDER" + if [ ! -s "$MERGED_PGO_PROFILE" ]; then + # Note: RUSTFLAGS can't handle spaces, so we're kinda screwed if the path up to here + # has spaces in it. + echo "::error::merged.profdata is empty. PGO data generation failed." + exit 1 + fi + + # Use the generated PGO profiling data to perform an optimized build + export RUSTFLAGS="$RUSTFLAGS_BACKUP -C llvm-args=-pgo-warn-missing-function -C profile-use=$MERGED_PGO_PROFILE" + fi + + # Build the final project + cd "${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}" + echo "Flags: $RUSTFLAGS" + echo "$BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features \"$BUILD_FEATURES_ARGS\" $NO_DEFAULT_FEATURES" + $BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features "$BUILD_FEATURES_ARGS" $NO_DEFAULT_FEATURES + + echo "PWD: $(pwd)" + echo "Build Dir: ${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release" + ls "${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release" + + - name: Upload binary artifacts + if: inputs.upload-artifacts == 'true' && inputs.build-library != 'true' + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.crate-name }}-${{ inputs.target }}-${{ inputs.features }} + path: | + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/${{ inputs.crate-name }}* + !${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/${{ inputs.crate-name }}*.d + + - name: Upload library artifacts + if: inputs.upload-artifacts == 'true' && inputs.build-library == 'true' + uses: actions/upload-artifact@v4 + with: + name: C-Library-${{ inputs.target }}-${{ inputs.features }} + path: | + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.a + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.so + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.lib + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.dll + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.pdb + ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.dylib + + - name: Run Tests and Coverage + if: inputs.run-tests-and-coverage == 'true' + uses: Reloaded-Project/devops-rust-test-and-coverage@v1 + with: + rust-project-path: ${{ inputs.rust-project-path }} + rust-toolchain: nightly + target: ${{ inputs.target }} + install-rust-toolchain: false + setup-rust-cache: false + upload-coverage: ${{ inputs.upload-coverage-to-codecov }} + codecov-token: ${{ inputs.codecov-token }} + features: ${{ inputs.features }} + no-default-features: ${{ inputs.no-default-features }} + use-cross: ${{ inputs.use-cross }} \ No newline at end of file diff --git a/assets/reloaded-logo.png b/assets/reloaded-logo.png new file mode 100644 index 0000000..090fb3a Binary files /dev/null and b/assets/reloaded-logo.png differ