Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build/
build-*/
runtime-analyzer-artifacts/
.git/
__pycache__/
129 changes: 95 additions & 34 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,58 @@
# SPDX-License-Identifier: Apache-2.0
name: Release

# On a v* tag: check that the tag matches the project() version, build and test as the Build
# workflow does, then attach the installed tree as runtime-analyzer-linux-x86_64.tar.gz, with
# its SHA256SUMS, to the GitHub Release of the tag.
# Builds the self-contained Linux archives with Dockerfile.release (Ubuntu 22.04 base, LLVM
# libraries and Clang headers shipped, verified on bare images) for amd64 and arm64, on every
# change to the release files and on demand. On a v* tag, the tag must match the project()
# version, and the archives with their checksums are attached to the GitHub Release.

on:
push:
tags: ["v*"]
pull_request:
paths:
- Dockerfile.release
- .dockerignore
- .github/workflows/release.yml
- test/release/**
- cmake/**
- CMakeLists.txt
- src/**
- include/**
workflow_dispatch:

concurrency:
group: release-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write
contents: read

env:
LLVM_VERSION: 20
ARCHIVE: runtime-analyzer-linux-x86_64.tar.gz
PROJECT_NAME: runtime-analyzer

jobs:
release:
name: Build, test and attach the Linux x86_64 tarball
runs-on: ubuntu-24.04
build-archives:
name: Build the Linux archive (${{ matrix.arch }})
# Each architecture builds on a native runner: emulating arm64 on an x86 host takes far
# longer for an LLVM-linked tool.
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
arch: amd64
runner: ubuntu-24.04
- platform: linux/arm64
arch: arm64
runner: ubuntu-24.04-arm

steps:
- uses: actions/checkout@v4

- name: Check that the tag matches the project version
if: github.ref_type == 'tag'
run: |
version="$(sed -n 's/^project(.* VERSION \([0-9][0-9.]*\).*/\1/p' CMakeLists.txt)"
test -n "$version" || { echo "no project() VERSION in CMakeLists.txt"; exit 1; }
Expand All @@ -33,39 +61,72 @@ jobs:
exit 1
fi

- name: Install LLVM ${{ env.LLVM_VERSION }}
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build
wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh
sudo bash /tmp/llvm.sh "$LLVM_VERSION"
sudo apt-get install -y "llvm-$LLVM_VERSION-dev" "libclang-$LLVM_VERSION-dev" "clang-$LLVM_VERSION"
echo "LLVM_DIR=/usr/lib/llvm-$LLVM_VERSION/lib/cmake/llvm" >> "$GITHUB_ENV"
echo "Clang_DIR=/usr/lib/llvm-$LLVM_VERSION/lib/cmake/clang" >> "$GITHUB_ENV"

- name: Configure
- name: Resolve the artifact version
id: version
run: |
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR="$LLVM_DIR" -DClang_DIR="$Clang_DIR"
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
echo "value=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"
else
echo "value=sha-$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT"
fi

- name: Build
run: cmake --build build --parallel
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Test
run: ctest --test-dir build --output-on-failure
- name: Build, verify and export the archive
run: |
set -euo pipefail
out_dir="dist/${{ matrix.arch }}"
mkdir -p "$out_dir"
docker buildx build \
--platform "${{ matrix.platform }}" \
--file Dockerfile.release \
--target artifacts \
--build-arg VERSION="${{ steps.version.outputs.value }}" \
--build-arg PROJECT_NAME="$PROJECT_NAME" \
--output "type=local,dest=$out_dir" \
.
ls -la "$out_dir"

- name: Package
- name: Validate the artifact files
run: |
cmake --install build --prefix dist/runtime-analyzer
tar -C dist -czf "$ARCHIVE" runtime-analyzer
sha256sum "$ARCHIVE" > SHA256SUMS
cat SHA256SUMS
set -euo pipefail
dir="dist/${{ matrix.arch }}"
archive="$dir/$PROJECT_NAME-${{ steps.version.outputs.value }}-linux-${{ matrix.arch }}.tar.gz"
test -f "$archive" || { echo "missing archive: $archive"; exit 1; }
test -f "$archive.sha256" || { echo "missing checksum: $archive.sha256"; exit 1; }
(cd "$dir" && sha256sum -c "$(basename "$archive.sha256")")

- name: Upload the workflow artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.PROJECT_NAME }}-${{ steps.version.outputs.value }}-linux-${{ matrix.arch }}
path: |
dist/${{ matrix.arch }}/*.tar.gz
dist/${{ matrix.arch }}/*.sha256
if-no-files-found: error

publish:
name: Attach the archives to the GitHub Release
runs-on: ubuntu-24.04
needs: build-archives
if: github.ref_type == 'tag'
permissions:
contents: write

steps:
- name: Download the archives
uses: actions/download-artifact@v4
with:
pattern: ${{ env.PROJECT_NAME }}-*-linux-*
path: dist
merge-multiple: true

- name: Attach to the GitHub Release
- name: Publish the release assets
uses: softprops/action-gh-release@v2
with:
files: |
${{ env.ARCHIVE }}
SHA256SUMS
dist/*.tar.gz
dist/*.sha256
fail_on_unmatched_files: true
generate_release_notes: true
42 changes: 39 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

cmake_minimum_required(VERSION 3.16)
# 3.21 for install(RUNTIME_DEPENDENCY_SET).
cmake_minimum_required(VERSION 3.21)

# ============================================================================
# CoreTrace Runtime Analyzer
Expand All @@ -17,6 +18,7 @@ set(TOOL_SOURCES
src/process.cpp
src/runtime_analyzer.cpp
src/sarif.cpp
src/shipped_toolchain.cpp
)

# CLI
Expand Down Expand Up @@ -194,7 +196,36 @@ install(TARGETS ${TOOL_NAME}_lib
LIBRARY DESTINATION lib
)
if(BUILD_CLI)
install(TARGETS ${TOOL_NAME} RUNTIME DESTINATION bin)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# The archive is self-contained: the LLVM libraries the CLI links (libLLVM, libclang-cpp)
# are copied into lib/, found through the rpath. libstdc++ and libgcc_s are shipped too,
# as the build compiler may be newer than the target's and they are backward compatible.
# glibc stays the system's: the archive runs on any glibc at least as old as the build
# machine's.
set_target_properties(${TOOL_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
install(TARGETS ${TOOL_NAME}
RUNTIME_DEPENDENCY_SET ${TOOL_NAME}_deps
RUNTIME DESTINATION bin
)
install(RUNTIME_DEPENDENCY_SET ${TOOL_NAME}_deps
PRE_EXCLUDE_REGEXES
"^libc\\.so"
"^libm\\.so"
"^libdl\\.so"
"^librt\\.so"
"^libpthread\\.so"
"^ld-linux"
DIRECTORIES ${LLVM_LIBRARY_DIRS}
LIBRARY DESTINATION lib
)
# Instrumented programs are linked against the shipped libstdc++ (-lstdc++ needs the
# unversioned name), as the runtime archives may use symbols the target's lacks.
install(CODE "file(CREATE_LINK libstdc++.so.6 \"\${CMAKE_INSTALL_PREFIX}/lib/libstdc++.so\" SYMBOLIC)")
else()
install(TARGETS ${TOOL_NAME} RUNTIME DESTINATION bin)
endif()
# Clang's headers next to the CLI, so that no clang is needed where it runs.
include(ClangHeaders)
endif()
install(DIRECTORY include/ DESTINATION include)
install(FILES "${TOOL_GENERATED_INCLUDE_DIR}/runtime_analyzer_version.hpp" DESTINATION include)
Expand Down Expand Up @@ -231,6 +262,11 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
target_link_libraries(process_test PRIVATE ${TOOL_NAME}_lib)
add_test(NAME process_unit COMMAND process_test)

add_executable(shipped_toolchain_test unittests/shipped_toolchain_test.cpp)
target_include_directories(shipped_toolchain_test PRIVATE src)
target_link_libraries(shipped_toolchain_test PRIVATE ${TOOL_NAME}_lib)
add_test(NAME shipped_toolchain_unit COMMAND shipped_toolchain_test)

if(BUILD_CLI)
find_package(Python3 COMPONENTS Interpreter)
if(Python3_Interpreter_FOUND)
Expand Down Expand Up @@ -286,7 +322,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# runs an instrumented program with the runtime archives installed next to it.
set(_prefix "${CMAKE_CURRENT_BINARY_DIR}/prefix")
add_test(NAME install_layout
COMMAND sh -c "rm -rf \"${_prefix}\" && ${CMAKE_COMMAND} --install \"${CMAKE_CURRENT_BINARY_DIR}\" --prefix \"${_prefix}\" > /dev/null && test -f \"${_prefix}/lib/lib${TOOL_NAME}_lib.a\" && test -f \"${_prefix}/include/runtime_analyzer.hpp\" && test -f \"${_prefix}/include/runtime_analyzer_version.hpp\" && \"${_prefix}/bin/${TOOL_NAME}\" --version && \"${_prefix}/bin/${TOOL_NAME}\" -o \"${_prefix}/hello\" -- test/examples/fixtures/hello.c"
COMMAND sh -c "rm -rf \"${_prefix}\" && ${CMAKE_COMMAND} --install \"${CMAKE_CURRENT_BINARY_DIR}\" --prefix \"${_prefix}\" > /dev/null && test -f \"${_prefix}/lib/lib${TOOL_NAME}_lib.a\" && test -f \"${_prefix}/include/runtime_analyzer.hpp\" && test -f \"${_prefix}/include/runtime_analyzer_version.hpp\" && test -f \"${_prefix}\"/lib/clang/*/include/stddef.h && \"${_prefix}/bin/${TOOL_NAME}\" --version && \"${_prefix}/bin/${TOOL_NAME}\" -o \"${_prefix}/hello\" -- test/examples/fixtures/hello.c"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
endif()
Loading
Loading