Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad3cf7ecf0 | ||
|
|
5075668363 | ||
|
|
d09b59863a | ||
|
|
685d63dd71 | ||
|
|
00e61a90aa | ||
|
|
07b2237074 | ||
|
|
5d4f1f3d01 | ||
|
|
0d4dfb570d | ||
|
|
ea81a17325 |
@@ -447,3 +447,45 @@ jobs:
|
||||
export PATH=$GITHUB_WORKSPACE:$PATH
|
||||
make package
|
||||
working-directory: ${{ github.workspace }}/build_osx
|
||||
|
||||
# BRL-CAD's STABLE branch is intended to represent the most recent
|
||||
# SHA1 that has successfully passed our primary tests on our CI
|
||||
# platforms. This job is intended to execute that update if the
|
||||
# prior tasks succeed. It's "needs" section should contain every
|
||||
# test that is not already the dependency of another tests.
|
||||
# sync-stable-branch:
|
||||
# name: Sync STABLE branch
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: [archives, componentbext, windows_std_tools, osx]
|
||||
# # This job should only run on a successful push to the main branch
|
||||
# if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
# steps:
|
||||
# # 1. Generate a short-lived token using the GitHub App
|
||||
# - name: Generate GitHub App Token
|
||||
# id: generate_token
|
||||
# uses: tibdex/github-app-token@v2
|
||||
# with:
|
||||
# app_id: ${{ secrets.STABLESYNC_APP_ID }}
|
||||
# private_key: ${{ secrets.STABLESYNC_APP_PRIVATE_KEY }}
|
||||
|
||||
# # 2. Checkout the repository using the App Token
|
||||
# - name: Checkout Code
|
||||
# uses: actions/checkout@v4
|
||||
# with:
|
||||
# token: ${{ steps.generate_token.outputs.token }}
|
||||
# fetch-depth: 0 # Fetches all history to safely move branches
|
||||
|
||||
# # 3. Securely update and push the STABLE branch pointer
|
||||
# - name: Update STABLE Branch Pointer
|
||||
# run: |
|
||||
# # Configure Git to identify as the GitHub Actions bot
|
||||
# git config --global user.name "github-actions[bot]"
|
||||
# git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# echo "Updating STABLE branch to point to the latest successfully CI tested main SHA: ${{ github.sha }}"
|
||||
|
||||
# # Force the local STABLE branch to point directly to the current main SHA
|
||||
# git branch -f STABLE ${{ github.sha }}
|
||||
|
||||
# # Push the updated stable branch reference securely back to origin
|
||||
# git push origin STABLE --force
|
||||
|
||||
+352
-21
@@ -15,16 +15,24 @@ on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *' # daily at 03:00 UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'The branch ref to run the conditional jobs on (e.g., refs/heads/pgo)'
|
||||
required: true
|
||||
default: 'refs/heads/main'
|
||||
type: string
|
||||
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
CLANG_VERSION: 18
|
||||
|
||||
jobs:
|
||||
|
||||
linux_bext:
|
||||
name: Linux - BRL-CAD bext build
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: &ubuntu_runner ubuntu-24.04 # Define the ubuntu runner anchor here
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Setup - CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
@@ -225,12 +233,13 @@ jobs:
|
||||
linux_static:
|
||||
name: Clang Static Analyser
|
||||
needs: [linux_bext]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: *ubuntu_runner # Use the ubuntu runner alias
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(github.event_name == 'workflow_dispatch' && github.ref == inputs.branch ||
|
||||
github.event_name == 'schedule' && github.ref == 'refs/heads/main')
|
||||
steps:
|
||||
- name: Setup - CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
@@ -239,19 +248,19 @@ jobs:
|
||||
- name: Clang Static Analyzer Setup
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-18 clang-tools-18
|
||||
sudo apt-get install -y clang-${{ env.CLANG_VERSION }} clang-tools-${{ env.CLANG_VERSION }}
|
||||
# Install X/OpenGL dev pkgs
|
||||
sudo apt-get install xserver-xorg-dev libx11-dev libxi-dev libxext-dev libglu1-mesa-dev libfontconfig-dev
|
||||
sudo apt-get install -y xserver-xorg-dev libx11-dev libxi-dev libxext-dev libglu1-mesa-dev libfontconfig-dev
|
||||
# Install tools
|
||||
sudo apt-get install astyle re2c xsltproc libxml2-utils
|
||||
sudo apt-get install -y astyle re2c xsltproc libxml2-utils
|
||||
# Install dependency dev pkgs
|
||||
sudo apt-get install zlib1g-dev libpng-dev libjpeg-dev libtiff-dev libeigen3-dev libgdal-dev libassimp-dev libopencv-dev tcl-dev tk-dev
|
||||
sudo apt-get install -y zlib1g-dev libpng-dev libjpeg-dev libtiff-dev libeigen3-dev libgdal-dev libassimp-dev libopencv-dev tcl-dev tk-dev
|
||||
# Install XCB/OpenGL dev pkgs for Qt - see:
|
||||
# https://wiki.qt.io/Building_Qt_6_from_Git
|
||||
# https://doc.qt.io/qt-6/linux-requirements.html
|
||||
sudo apt-get install libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev
|
||||
sudo apt-get install libgl-dev
|
||||
sudo apt-get install libinput-dev # Cleanup
|
||||
sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev
|
||||
sudo apt-get install -y libgl-dev
|
||||
sudo apt-get install -y libinput-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
@@ -261,7 +270,7 @@ jobs:
|
||||
- name: Prepare bext dependencies
|
||||
uses: ./brlcad/.github/actions/prepare-bext
|
||||
with:
|
||||
platform-channel: ubuntu-24.04-${{ runner.arch }}-release
|
||||
platform-channel: ubuntu-*ubuntu_version-${{ runner.arch }}-release
|
||||
source-dir: ${{ github.workspace }}/brlcad
|
||||
output-dir: ${{ runner.temp }}/bext_output
|
||||
build-type: Release
|
||||
@@ -278,7 +287,7 @@ jobs:
|
||||
env:
|
||||
BRLCAD_EXT_DIR: ${{ runner.temp }}/bext_output
|
||||
run: |
|
||||
export PATH=$GITHUB_WORKSPACE:/usr/share/clang/scan-build-18/bin:/usr/share/clang/scan-build-18/libexec:$PATH
|
||||
# The script will now receive the version number and find the tools itself
|
||||
cp $GITHUB_WORKSPACE/brlcad/misc/clang-static-analyzer-run.sh .
|
||||
./clang-static-analyzer-run.sh
|
||||
working-directory: ${{ github.workspace }}/brlcad/build_clangstatic
|
||||
@@ -290,17 +299,339 @@ jobs:
|
||||
html2text scan-reports-all/*/index.html
|
||||
working-directory: ${{ github.workspace }}/brlcad/build_clangstatic
|
||||
|
||||
linux_pgo:
|
||||
name: GCC Profile-Guided Optimization
|
||||
needs: [linux_bext]
|
||||
runs-on: *ubuntu_runner # Use the ubuntu runner alias
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: "2"
|
||||
PGO_PATH: ${{ github.workspace }}/pgo-profile
|
||||
PGO_BENCHMARK_TARGETS: >-
|
||||
rt pixcmp benchmark_cp BENCHMARK_PIX_cp PIX_LOG_cp
|
||||
bldg391.g m35.g moss.g sphflake.g star.g world.g
|
||||
PGO_TRAINING_TARGETS: >-
|
||||
havoc.g Generic_Twin.g NIST_MBE_PMI_2.g
|
||||
PGO_TRAINING_SIZE: "512"
|
||||
PGO_TRAINING_AZIMUTH: "35"
|
||||
PGO_TRAINING_ELEVATION: "25"
|
||||
PGO_BENCHMARK_TIMEFRAME: "8"
|
||||
PGO_BENCHMARK_MAXTIME: "60"
|
||||
PGO_BENCHMARK_AVERAGE: "3"
|
||||
PGO_BENCHMARK_DEVIATION: "3"
|
||||
PGO_MIN_SPEEDUP: "1.0"
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(github.event_name == 'workflow_dispatch' && github.ref == inputs.branch ||
|
||||
github.event_name == 'schedule' && github.ref == 'refs/heads/main')
|
||||
steps:
|
||||
- name: Setup - CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Install apt dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
# Install X/OpenGL dev pkgs
|
||||
sudo apt-get install xserver-xorg-dev libx11-dev libxi-dev libxext-dev libglu1-mesa-dev libfontconfig-dev
|
||||
# Install tools
|
||||
sudo apt-get install astyle re2c xsltproc libxml2-utils
|
||||
# Install dependency dev pkgs
|
||||
sudo apt-get install zlib1g-dev libpng-dev libjpeg-dev libtiff-dev libeigen3-dev libgdal-dev libassimp-dev libopencv-dev tcl-dev tk-dev
|
||||
# Install XCB/OpenGL dev pkgs for a fallback bext build
|
||||
sudo apt-get install libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxcb-xinput-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev
|
||||
sudo apt-get install libgl-dev libinput-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: brlcad
|
||||
|
||||
- name: Prepare bext dependencies
|
||||
uses: ./brlcad/.github/actions/prepare-bext
|
||||
with:
|
||||
platform-channel: ubuntu-*ubuntu_version-${{ runner.arch }}-release
|
||||
source-dir: ${{ github.workspace }}/brlcad
|
||||
output-dir: ${{ runner.temp }}/bext_output
|
||||
build-type: Release
|
||||
artifact-token: ${{ secrets.BEXT_ARTIFACT_TOKEN }}
|
||||
|
||||
- name: Directory setup
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cmake -E make_directory $HOME/.cache/BRL-CAD
|
||||
if [[ -e "$PGO_PATH" ]]; then
|
||||
echo "::error::PGO profile path unexpectedly exists before the generation build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Configure baseline build
|
||||
run: |
|
||||
cmake -S brlcad -B build_pgo_baseline -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DBUILD_TESTING=ON \
|
||||
-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output \
|
||||
-DBRLCAD_ENABLE_QT=OFF \
|
||||
-DBRLCAD_ENABLE_STEP=ON \
|
||||
-DBRLCAD_ENABLE_STRICT=ON
|
||||
|
||||
- name: Build baseline
|
||||
run: cmake --build build_pgo_baseline --target $PGO_BENCHMARK_TARGETS
|
||||
|
||||
- name: Configure profile-generation build
|
||||
run: |
|
||||
cmake -S brlcad -B build_pgo -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DBUILD_TESTING=ON \
|
||||
-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output \
|
||||
-DBRLCAD_ENABLE_QT=OFF \
|
||||
-DBRLCAD_ENABLE_STEP=ON \
|
||||
-DBRLCAD_ENABLE_STRICT=ON \
|
||||
-DBRLCAD_PGO=ON
|
||||
grep -q -- '-fprofile-generate=' build_pgo/compile_commands.json
|
||||
|
||||
- name: Build profile-generation binaries
|
||||
run: cmake --build build_pgo --target $PGO_BENCHMARK_TARGETS $PGO_TRAINING_TARGETS
|
||||
|
||||
- name: Generate profile data
|
||||
run: |
|
||||
cmake \
|
||||
-DPGO_MODE=TRAIN \
|
||||
-DPGO_BUILD_DIR="$GITHUB_WORKSPACE/build_pgo" \
|
||||
-DPGO_RESULTS_DIR="$GITHUB_WORKSPACE/pgo-training" \
|
||||
-DPGO_PROFILE_DIR="$PGO_PATH" \
|
||||
-DPGO_TIMEFRAME="$PGO_BENCHMARK_TIMEFRAME" \
|
||||
-DPGO_MAXTIME="$PGO_BENCHMARK_MAXTIME" \
|
||||
-DPGO_AVERAGE="$PGO_BENCHMARK_AVERAGE" \
|
||||
-DPGO_DEVIATION="$PGO_BENCHMARK_DEVIATION" \
|
||||
-DPGO_TRAINING_SIZE="$PGO_TRAINING_SIZE" \
|
||||
-DPGO_TRAINING_AZIMUTH="$PGO_TRAINING_AZIMUTH" \
|
||||
-DPGO_TRAINING_ELEVATION="$PGO_TRAINING_ELEVATION" \
|
||||
-P brlcad/misc/CMake/scripts/pgo_benchmark.cmake
|
||||
|
||||
- name: Configure profile-use build
|
||||
run: |
|
||||
# GCC incorporates the build path into profile filenames, so both
|
||||
# compilation passes must use the same build directory.
|
||||
cmake -E rm -rf build_pgo
|
||||
cmake -S brlcad -B build_pgo -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DBUILD_TESTING=ON \
|
||||
-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output \
|
||||
-DBRLCAD_ENABLE_QT=OFF \
|
||||
-DBRLCAD_ENABLE_STEP=ON \
|
||||
-DBRLCAD_ENABLE_STRICT=ON \
|
||||
-DBRLCAD_PGO=ON
|
||||
grep -q -- '-fprofile-use=' build_pgo/compile_commands.json
|
||||
|
||||
- name: Build profile-guided binaries
|
||||
run: cmake --build build_pgo --target $PGO_BENCHMARK_TARGETS
|
||||
|
||||
- name: Benchmark and compare profile-guided build
|
||||
run: |
|
||||
cmake \
|
||||
-DPGO_MODE=COMPARE \
|
||||
-DPGO_BASELINE_BUILD_DIR="$GITHUB_WORKSPACE/build_pgo_baseline" \
|
||||
-DPGO_OPTIMIZED_BUILD_DIR="$GITHUB_WORKSPACE/build_pgo" \
|
||||
-DPGO_RESULTS_DIR="$GITHUB_WORKSPACE/pgo-results" \
|
||||
-DPGO_TIMEFRAME="$PGO_BENCHMARK_TIMEFRAME" \
|
||||
-DPGO_MAXTIME="$PGO_BENCHMARK_MAXTIME" \
|
||||
-DPGO_AVERAGE="$PGO_BENCHMARK_AVERAGE" \
|
||||
-DPGO_DEVIATION="$PGO_BENCHMARK_DEVIATION" \
|
||||
-DPGO_MIN_SPEEDUP="$PGO_MIN_SPEEDUP" \
|
||||
-P brlcad/misc/CMake/scripts/pgo_benchmark.cmake
|
||||
|
||||
windows_pgo:
|
||||
name: MSVC Profile-Guided Optimization
|
||||
needs: [windows_bext]
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: "2"
|
||||
PGO_BENCHMARK_TARGETS: >-
|
||||
rt pixcmp benchmark_cp BENCHMARK_PIX_cp PIX_LOG_cp
|
||||
bldg391.g m35.g moss.g sphflake.g star.g world.g
|
||||
PGO_TRAINING_TARGETS: >-
|
||||
havoc.g Generic_Twin.g NIST_MBE_PMI_2.g
|
||||
PGO_TRAINING_SIZE: "512"
|
||||
PGO_TRAINING_AZIMUTH: "35"
|
||||
PGO_TRAINING_ELEVATION: "25"
|
||||
PGO_BENCHMARK_TIMEFRAME: "8"
|
||||
PGO_BENCHMARK_MAXTIME: "60"
|
||||
PGO_BENCHMARK_AVERAGE: "3"
|
||||
PGO_BENCHMARK_DEVIATION: "3"
|
||||
PGO_MIN_SPEEDUP: "1.0"
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(github.event_name == 'workflow_dispatch' && github.ref == inputs.branch ||
|
||||
github.event_name == 'schedule' && github.ref == 'refs/heads/main')
|
||||
steps:
|
||||
- name: Setup - CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Add cl.exe to PATH
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: brlcad
|
||||
|
||||
- name: Prepare bext dependencies
|
||||
uses: ./brlcad/.github/actions/prepare-bext
|
||||
with:
|
||||
platform-channel: windows-2025-${{ runner.arch }}-release
|
||||
source-dir: ${{ github.workspace }}/brlcad
|
||||
output-dir: ${{ runner.temp }}/bext_output
|
||||
build-type: Release
|
||||
artifact-token: ${{ secrets.BEXT_ARTIFACT_TOKEN }}
|
||||
|
||||
- name: Set up PGO paths
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Short build roots keep STEP-generated paths below Windows MAX_PATH.
|
||||
$paths = @{
|
||||
PGO_PATH = Join-Path $env:RUNNER_TEMP 'pgo-d'
|
||||
PGO_BASELINE_BUILD_DIR = Join-Path $env:RUNNER_TEMP 'pgo-b'
|
||||
PGO_GENERATE_BUILD_DIR = Join-Path $env:RUNNER_TEMP 'pgo-g'
|
||||
PGO_OPTIMIZED_BUILD_DIR = Join-Path $env:RUNNER_TEMP 'pgo-u'
|
||||
PGO_TRAINING_RESULTS_DIR = Join-Path $env:RUNNER_TEMP 'pgo-t'
|
||||
PGO_RESULTS_DIR = Join-Path $env:RUNNER_TEMP 'pgo-r'
|
||||
}
|
||||
if (Test-Path -LiteralPath $paths.PGO_PATH) {
|
||||
throw "PGO profile path unexpectedly exists before the generation build: $($paths.PGO_PATH)"
|
||||
}
|
||||
foreach ($path in $paths.GetEnumerator()) {
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "$($path.Key)=$($path.Value)"
|
||||
}
|
||||
|
||||
- name: Configure baseline build
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -S brlcad -B "$env:PGO_BASELINE_BUILD_DIR" -G Ninja `
|
||||
-DCMAKE_C_COMPILER=cl.exe `
|
||||
-DCMAKE_CXX_COMPILER=cl.exe `
|
||||
-DCMAKE_BUILD_TYPE=Release `
|
||||
-DBUILD_TESTING=ON `
|
||||
"-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output" `
|
||||
-DBRLCAD_ENABLE_QT=OFF `
|
||||
-DBRLCAD_ENABLE_STEP=ON `
|
||||
-DBRLCAD_ENABLE_STRICT=ON
|
||||
|
||||
- name: Build baseline
|
||||
shell: pwsh
|
||||
run: |
|
||||
$targets = $env:PGO_BENCHMARK_TARGETS -split '\s+'
|
||||
$arguments = @('--build', $env:PGO_BASELINE_BUILD_DIR, '--target') + $targets
|
||||
cmake @arguments
|
||||
|
||||
- name: Configure profile-generation build
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -S brlcad -B "$env:PGO_GENERATE_BUILD_DIR" -G Ninja `
|
||||
-DCMAKE_C_COMPILER=cl.exe `
|
||||
-DCMAKE_CXX_COMPILER=cl.exe `
|
||||
-DCMAKE_BUILD_TYPE=Release `
|
||||
-DBUILD_TESTING=ON `
|
||||
"-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output" `
|
||||
-DBRLCAD_ENABLE_QT=OFF `
|
||||
-DBRLCAD_ENABLE_STEP=ON `
|
||||
-DBRLCAD_ENABLE_STRICT=ON `
|
||||
-DBRLCAD_PGO=ON
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
if (-not (Select-String -Path "$env:PGO_GENERATE_BUILD_DIR/build.ninja" -SimpleMatch '/GENPROFILE:PGD=' -Quiet)) {
|
||||
throw 'The profile-generation build does not contain /GENPROFILE.'
|
||||
}
|
||||
|
||||
- name: Build profile-generation binaries
|
||||
shell: pwsh
|
||||
run: |
|
||||
$targets = ($env:PGO_BENCHMARK_TARGETS + ' ' + $env:PGO_TRAINING_TARGETS) -split '\s+'
|
||||
$arguments = @('--build', $env:PGO_GENERATE_BUILD_DIR, '--target') + $targets
|
||||
cmake @arguments
|
||||
|
||||
- name: Generate profile data
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake `
|
||||
-DPGO_MODE=TRAIN `
|
||||
"-DPGO_BUILD_DIR=$env:PGO_GENERATE_BUILD_DIR" `
|
||||
"-DPGO_RESULTS_DIR=$env:PGO_TRAINING_RESULTS_DIR" `
|
||||
"-DPGO_PROFILE_DIR=$env:PGO_PATH" `
|
||||
"-DPGO_TIMEFRAME=$env:PGO_BENCHMARK_TIMEFRAME" `
|
||||
"-DPGO_MAXTIME=$env:PGO_BENCHMARK_MAXTIME" `
|
||||
"-DPGO_AVERAGE=$env:PGO_BENCHMARK_AVERAGE" `
|
||||
"-DPGO_DEVIATION=$env:PGO_BENCHMARK_DEVIATION" `
|
||||
"-DPGO_TRAINING_SIZE=$env:PGO_TRAINING_SIZE" `
|
||||
"-DPGO_TRAINING_AZIMUTH=$env:PGO_TRAINING_AZIMUTH" `
|
||||
"-DPGO_TRAINING_ELEVATION=$env:PGO_TRAINING_ELEVATION" `
|
||||
-P brlcad/misc/CMake/scripts/pgo_benchmark.cmake
|
||||
|
||||
- name: Configure profile-use build
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -S brlcad -B "$env:PGO_OPTIMIZED_BUILD_DIR" -G Ninja `
|
||||
-DCMAKE_C_COMPILER=cl.exe `
|
||||
-DCMAKE_CXX_COMPILER=cl.exe `
|
||||
-DCMAKE_BUILD_TYPE=Release `
|
||||
-DBUILD_TESTING=ON `
|
||||
"-DBRLCAD_EXT_DIR=${{ runner.temp }}/bext_output" `
|
||||
-DBRLCAD_ENABLE_QT=OFF `
|
||||
-DBRLCAD_ENABLE_STEP=ON `
|
||||
-DBRLCAD_ENABLE_STRICT=ON `
|
||||
-DBRLCAD_PGO=ON
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
if (-not (Select-String -Path "$env:PGO_OPTIMIZED_BUILD_DIR/build.ninja" -SimpleMatch '/USEPROFILE:PGD=' -Quiet)) {
|
||||
throw 'The profile-use build does not contain /USEPROFILE.'
|
||||
}
|
||||
|
||||
- name: Build profile-guided binaries
|
||||
shell: pwsh
|
||||
run: |
|
||||
$targets = $env:PGO_BENCHMARK_TARGETS -split '\s+'
|
||||
$arguments = @('--build', $env:PGO_OPTIMIZED_BUILD_DIR, '--target') + $targets
|
||||
cmake @arguments
|
||||
|
||||
- name: Benchmark and compare profile-guided build
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake `
|
||||
-DPGO_MODE=COMPARE `
|
||||
"-DPGO_BASELINE_BUILD_DIR=$env:PGO_BASELINE_BUILD_DIR" `
|
||||
"-DPGO_OPTIMIZED_BUILD_DIR=$env:PGO_OPTIMIZED_BUILD_DIR" `
|
||||
"-DPGO_RESULTS_DIR=$env:PGO_RESULTS_DIR" `
|
||||
"-DPGO_TIMEFRAME=$env:PGO_BENCHMARK_TIMEFRAME" `
|
||||
"-DPGO_MAXTIME=$env:PGO_BENCHMARK_MAXTIME" `
|
||||
"-DPGO_AVERAGE=$env:PGO_BENCHMARK_AVERAGE" `
|
||||
"-DPGO_DEVIATION=$env:PGO_BENCHMARK_DEVIATION" `
|
||||
"-DPGO_MIN_SPEEDUP=$env:PGO_MIN_SPEEDUP" `
|
||||
-P brlcad/misc/CMake/scripts/pgo_benchmark.cmake
|
||||
|
||||
|
||||
# See https://app.codecov.io/gh/BRL-CAD/brlcad for analysis results
|
||||
linux_cov:
|
||||
name: LCOV Coverage testing
|
||||
needs: [linux_bext]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: *ubuntu_runner # Use the ubuntu runner alias
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(github.event_name == 'workflow_dispatch' && github.ref == inputs.branch ||
|
||||
github.event_name == 'schedule' && github.ref == 'refs/heads/main')
|
||||
steps:
|
||||
- name: Setup - CMake
|
||||
uses: lukka/get-cmake@latest
|
||||
@@ -331,7 +662,7 @@ jobs:
|
||||
- name: Prepare bext dependencies
|
||||
uses: ./brlcad/.github/actions/prepare-bext
|
||||
with:
|
||||
platform-channel: ubuntu-24.04-${{ runner.arch }}-release
|
||||
platform-channel: ubuntu-*ubuntu_version-${{ runner.arch }}-release
|
||||
source-dir: ${{ github.workspace }}/brlcad
|
||||
output-dir: ${{ runner.temp }}/bext_output
|
||||
build-type: Release
|
||||
|
||||
+104
-6
@@ -1338,6 +1338,90 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
brlcad_deferred_define("BRLCAD_HAS_BIG_STACK 1")
|
||||
endif()
|
||||
|
||||
# Profile-Guided Optimization uses a shared profile location for both compiler
|
||||
# families. A path that does not exist selects the instrumentation pass; an
|
||||
# existing path selects the profile-use pass in a fresh build tree.
|
||||
if("$ENV{PGO_PATH}" STREQUAL "")
|
||||
set(BRLCAD_PGO_PATH "${CMAKE_BINARY_DIR}/profiling")
|
||||
else()
|
||||
file(TO_CMAKE_PATH "$ENV{PGO_PATH}" BRLCAD_PGO_PATH)
|
||||
endif()
|
||||
|
||||
# MSVC creates one profile database per linked image. The target-dependent
|
||||
# generator expression gives every executable and DLL a distinct database,
|
||||
# while /GL also covers code contributed through object and static libraries.
|
||||
if(MSVC AND BRLCAD_PGO)
|
||||
if(DEFINED BRLCAD_MSVC_PGO_PHASE)
|
||||
if(NOT "${BRLCAD_MSVC_PGO_PATH}" STREQUAL "${BRLCAD_PGO_PATH}")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"PGO_PATH changed from '${BRLCAD_MSVC_PGO_PATH}' to '${BRLCAD_PGO_PATH}'. "
|
||||
"Use a fresh build directory when changing PGO phases or profile locations."
|
||||
)
|
||||
endif()
|
||||
elseif(EXISTS "${BRLCAD_PGO_PATH}")
|
||||
set(BRLCAD_MSVC_PGO_PHASE USE)
|
||||
else()
|
||||
set(BRLCAD_MSVC_PGO_PHASE GENERATE)
|
||||
endif()
|
||||
|
||||
if(NOT BRLCAD_MSVC_PGO_PHASE MATCHES "^(GENERATE|USE)$")
|
||||
message(FATAL_ERROR "Invalid internal MSVC PGO phase '${BRLCAD_MSVC_PGO_PHASE}'")
|
||||
endif()
|
||||
set(BRLCAD_MSVC_PGO_PHASE "${BRLCAD_MSVC_PGO_PHASE}" CACHE INTERNAL "MSVC PGO build phase" FORCE)
|
||||
set(BRLCAD_MSVC_PGO_PATH "${BRLCAD_PGO_PATH}" CACHE INTERNAL "MSVC PGO profile path" FORCE)
|
||||
|
||||
if(BRLCAD_MSVC_PGO_PHASE STREQUAL "GENERATE")
|
||||
# link.exe requires the PGD parent directory to exist before it links the
|
||||
# instrumented image. Cache the phase above so an in-place CMake rerun
|
||||
# does not mistake this newly created directory for completed profiles.
|
||||
file(MAKE_DIRECTORY "${BRLCAD_PGO_PATH}")
|
||||
set(_brlcad_msvc_pgo_link_mode GENPROFILE)
|
||||
message(
|
||||
STATUS
|
||||
"MSVC PGO generation enabled; set VCPROFILE_PATH=${BRLCAD_PGO_PATH} while running training workloads"
|
||||
)
|
||||
distclean("${BRLCAD_PGO_PATH}")
|
||||
else()
|
||||
message(STATUS "MSVC PGO profile use enabled from ${BRLCAD_PGO_PATH}")
|
||||
endif()
|
||||
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:/GL>")
|
||||
add_link_options(/LTCG)
|
||||
if(_brlcad_msvc_pgo_link_mode)
|
||||
add_link_options(
|
||||
"/${_brlcad_msvc_pgo_link_mode}:PGD=${BRLCAD_PGO_PATH}/$<TARGET_PROPERTY:NAME>.pgd"
|
||||
)
|
||||
endif()
|
||||
unset(_brlcad_msvc_pgo_link_mode)
|
||||
endif()
|
||||
|
||||
# Apply profile-use only to images exercised during training. link.exe emits
|
||||
# C4961 for an untrained PGD, and strict builds promote that warning to an
|
||||
# error during LTCG. The generation pass names PGC files after the target's
|
||||
# PGD, so this check also works when OUTPUT_NAME changes the binary name.
|
||||
function(_BRLCAD_MSVC_PGO_APPLY_PROFILES directory)
|
||||
get_property(_brlcad_pgo_targets DIRECTORY "${directory}" PROPERTY BUILDSYSTEM_TARGETS)
|
||||
foreach(_brlcad_pgo_target IN LISTS _brlcad_pgo_targets)
|
||||
get_target_property(_brlcad_pgo_target_type ${_brlcad_pgo_target} TYPE)
|
||||
if(_brlcad_pgo_target_type MATCHES "^(EXECUTABLE|SHARED_LIBRARY|MODULE_LIBRARY)$")
|
||||
set(_brlcad_pgo_database "${BRLCAD_PGO_PATH}/${_brlcad_pgo_target}.pgd")
|
||||
file(GLOB _brlcad_pgo_counts LIST_DIRECTORIES FALSE "${BRLCAD_PGO_PATH}/${_brlcad_pgo_target}![0-9]*.pgc")
|
||||
if(EXISTS "${_brlcad_pgo_database}" AND _brlcad_pgo_counts)
|
||||
target_link_options(${_brlcad_pgo_target} PRIVATE "/USEPROFILE:PGD=${_brlcad_pgo_database}")
|
||||
set_property(GLOBAL APPEND PROPERTY BRLCAD_MSVC_PGO_TRAINED_TARGETS ${_brlcad_pgo_target})
|
||||
endif()
|
||||
unset(_brlcad_pgo_counts)
|
||||
unset(_brlcad_pgo_database)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
get_property(_brlcad_pgo_subdirectories DIRECTORY "${directory}" PROPERTY SUBDIRECTORIES)
|
||||
foreach(_brlcad_pgo_subdirectory IN LISTS _brlcad_pgo_subdirectories)
|
||||
_brlcad_msvc_pgo_apply_profiles("${_brlcad_pgo_subdirectory}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# The following tests are almost entirely for gcc/llvm style flags, so
|
||||
# we don't unnecessarily slow down the Windows build.
|
||||
if(NOT MSVC)
|
||||
@@ -1400,11 +1484,6 @@ if(NOT MSVC)
|
||||
# variable set to a temp folder
|
||||
|
||||
set(pgo_flags_found "")
|
||||
if("$ENV{PGO_PATH}" STREQUAL "")
|
||||
set(BRLCAD_PGO_PATH "${CMAKE_BINARY_DIR}/profiling")
|
||||
else(NOT "$ENV{PGO_PATH}" STREQUAL "")
|
||||
set(BRLCAD_PGO_PATH "$ENV{PGO_PATH}")
|
||||
endif("$ENV{PGO_PATH}" STREQUAL "")
|
||||
|
||||
if(BRLCAD_PGO AND NOT EXISTS "${BRLCAD_PGO_PATH}")
|
||||
if("${CMAKE_C_FLAGS}" MATCHES ".*fprofile-use.*")
|
||||
@@ -1450,7 +1529,8 @@ if(NOT MSVC)
|
||||
# gcc-style USE
|
||||
if("${pgo_flags_found}" STREQUAL "")
|
||||
cmake_push_check_state()
|
||||
set(flags "fprofile-use=\"${BRLCAD_PGO_PATH}\" -Wno-error=coverage-mismatch -fprofile-correction")
|
||||
set(flags "fprofile-use=\"${BRLCAD_PGO_PATH}\" -Wno-error=coverage-mismatch")
|
||||
string(APPEND flags " -Wno-error=missing-profile -fprofile-correction")
|
||||
set(CMAKE_REQUIRED_FLAGS "-${flags}")
|
||||
check_c_flag("${flags}" GROUPS OPTIMIZE_C_FLAGS VARS pgo_flags_found)
|
||||
check_cxx_flag("${flags}" GROUPS OPTIMIZE_CXX_FLAGS)
|
||||
@@ -2973,6 +3053,24 @@ verbose_add_subdirectory("" doc)
|
||||
# NOTE: misc/tools is added separately (earlier)
|
||||
verbose_add_subdirectory("" misc)
|
||||
|
||||
if(MSVC AND BRLCAD_PGO AND BRLCAD_MSVC_PGO_PHASE STREQUAL "USE")
|
||||
set_property(GLOBAL PROPERTY BRLCAD_MSVC_PGO_TRAINED_TARGETS)
|
||||
_brlcad_msvc_pgo_apply_profiles("${CMAKE_SOURCE_DIR}")
|
||||
get_property(_brlcad_msvc_pgo_targets GLOBAL PROPERTY BRLCAD_MSVC_PGO_TRAINED_TARGETS)
|
||||
list(LENGTH _brlcad_msvc_pgo_targets _brlcad_msvc_pgo_target_count)
|
||||
if(_brlcad_msvc_pgo_target_count EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"No MSVC PGO counter files were found in ${BRLCAD_PGO_PATH}. "
|
||||
"Set VCPROFILE_PATH to that directory while running the training workloads "
|
||||
"before configuring the profile-use build."
|
||||
)
|
||||
endif()
|
||||
message(STATUS "MSVC PGO will use training data for ${_brlcad_msvc_pgo_target_count} linked targets")
|
||||
unset(_brlcad_msvc_pgo_target_count)
|
||||
unset(_brlcad_msvc_pgo_targets)
|
||||
endif()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# CMake package configuration files for modern find_package(BRLCAD CONFIG)
|
||||
#
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ __BEGIN_DECLS
|
||||
* version 5 UUID suitable for repeatable identifier hashing.
|
||||
*/
|
||||
BU_EXPORT int
|
||||
bu_uuid_create(uint8_t uuid[STATIC_ARRAY(16)], size_t nbytes, const uint8_t *bytes, const uint8_t namespace_uuid[STATIC_ARRAY(16)]);
|
||||
bu_uuid_create(uint8_t uuid[STATIC_ARRAY(16)], size_t nbytes, const uint8_t *bytes, const uint8_t *namespace_uuid);
|
||||
|
||||
/**
|
||||
* This is a convenience UUID comparison routine compatible with
|
||||
|
||||
@@ -471,11 +471,13 @@ if(BRLCAD_VERBOSE)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif(BRLCAD_VERBOSE)
|
||||
|
||||
# Build with profile-guided optimization support. this requires a two-pass
|
||||
# compile, once with BRLCAD_PGO=ON on a location that did not exist beforehand
|
||||
# (specified via the PGO_PATH environment variable), and again to use profiling
|
||||
# metrics captured on "typical" operations and data. By default, path is
|
||||
# BUILDDIR/profiling
|
||||
# Build with profile-guided optimization support. This requires a two-pass
|
||||
# compile, once with BRLCAD_PGO=ON and a profile location that did not exist
|
||||
# beforehand (specified via the PGO_PATH environment variable), and again in a
|
||||
# fresh build directory to use metrics captured on "typical" operations and
|
||||
# data. By default, the path is BUILDDIR/profiling. For MSVC, set
|
||||
# VCPROFILE_PATH to PGO_PATH while running the instrumented programs so their
|
||||
# per-binary .pgc files are available beside the corresponding .pgd files.
|
||||
|
||||
option(BRLCAD_PGO "Enable profile-guided optimization (set PGO_PATH environment variable)")
|
||||
mark_as_advanced(BRLCAD_PGO)
|
||||
|
||||
@@ -108,6 +108,7 @@ set(
|
||||
probe_validation/README.md
|
||||
probe_validation/CMakeLists.txt
|
||||
probe_validation/probe_validation.cpp
|
||||
scripts/pgo_benchmark.cmake
|
||||
scripts/printtime.cmake
|
||||
scripts/tcl_mkindex.cmake
|
||||
scripts/timestamp.cmake
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
# P G O _ B E N C H M A R K . C M A K E
|
||||
# BRL-CAD
|
||||
#
|
||||
# Copyright (c) 2026 United States Government as represented by
|
||||
# the U.S. Army Research Laboratory.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. The name of the author may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
# TRAIN runs the standard benchmark and additional geometry, then verifies
|
||||
# that compiler profile counters were produced. COMPARE runs the standard
|
||||
# benchmark from baseline and profile-use build trees and requires its
|
||||
# equal-weight mean speedup to exceed PGO_MIN_SPEEDUP. The training model
|
||||
# list accepts build-relative or absolute paths, so external model sets can be
|
||||
# supplied without changing this script.
|
||||
#
|
||||
# Required inputs:
|
||||
# TRAIN: PGO_BUILD_DIR, PGO_RESULTS_DIR, PGO_PROFILE_DIR
|
||||
# COMPARE: PGO_BASELINE_BUILD_DIR, PGO_OPTIMIZED_BUILD_DIR,
|
||||
# PGO_RESULTS_DIR
|
||||
|
||||
set(_pgo_valid_modes TRAIN COMPARE)
|
||||
if(NOT DEFINED PGO_MODE)
|
||||
message(FATAL_ERROR "PGO_MODE must be TRAIN or COMPARE")
|
||||
endif()
|
||||
|
||||
string(TOUPPER "${PGO_MODE}" PGO_MODE)
|
||||
if(NOT PGO_MODE IN_LIST _pgo_valid_modes)
|
||||
message(FATAL_ERROR "PGO_MODE must be TRAIN or COMPARE, not '${PGO_MODE}'")
|
||||
endif()
|
||||
|
||||
set(_pgo_default_models moss world star bldg391 m35 sphflake)
|
||||
set(
|
||||
_pgo_default_training_models
|
||||
share/db/havoc.g
|
||||
share/db/faa/Generic_Twin.g
|
||||
share/db/nist/NIST_MBE_PMI_2.g
|
||||
)
|
||||
|
||||
if(NOT DEFINED PGO_MODELS)
|
||||
set(PGO_MODELS ${_pgo_default_models})
|
||||
endif()
|
||||
if(NOT DEFINED PGO_TRAINING_MODELS)
|
||||
set(PGO_TRAINING_MODELS ${_pgo_default_training_models})
|
||||
endif()
|
||||
if(NOT DEFINED PGO_TIMEFRAME)
|
||||
set(PGO_TIMEFRAME 8)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_MAXTIME)
|
||||
set(PGO_MAXTIME 60)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_AVERAGE)
|
||||
set(PGO_AVERAGE 3)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_DEVIATION)
|
||||
set(PGO_DEVIATION 3)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_TRAINING_SIZE)
|
||||
set(PGO_TRAINING_SIZE 512)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_TRAINING_AZIMUTH)
|
||||
set(PGO_TRAINING_AZIMUTH 35)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_TRAINING_ELEVATION)
|
||||
set(PGO_TRAINING_ELEVATION 25)
|
||||
endif()
|
||||
if(NOT DEFINED PGO_MIN_SPEEDUP)
|
||||
set(PGO_MIN_SPEEDUP 1.0)
|
||||
endif()
|
||||
|
||||
function(_pgo_require variable_name)
|
||||
if(NOT DEFINED "${variable_name}" OR "${${variable_name}}" STREQUAL "")
|
||||
message(FATAL_ERROR "${variable_name} is required for PGO_MODE=${PGO_MODE}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_pgo_absolute_path input_path output_variable)
|
||||
get_filename_component(_pgo_path "${input_path}" ABSOLUTE)
|
||||
file(TO_CMAKE_PATH "${_pgo_path}" _pgo_path)
|
||||
set("${output_variable}" "${_pgo_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_pgo_cache_value build_directory variable_name output_variable)
|
||||
set(_pgo_cache_file "${build_directory}/CMakeCache.txt")
|
||||
if(NOT EXISTS "${_pgo_cache_file}")
|
||||
message(FATAL_ERROR "CMake cache does not exist: ${_pgo_cache_file}")
|
||||
endif()
|
||||
file(
|
||||
STRINGS
|
||||
"${_pgo_cache_file}"
|
||||
_pgo_cache_entry
|
||||
LIMIT_COUNT 1
|
||||
REGEX "^${variable_name}(:[^=]*)?="
|
||||
)
|
||||
if(_pgo_cache_entry)
|
||||
string(REGEX REPLACE "^[^=]*=" "" _pgo_value "${_pgo_cache_entry}")
|
||||
else()
|
||||
set(_pgo_value "")
|
||||
endif()
|
||||
set("${output_variable}" "${_pgo_value}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_pgo_validate_build build_directory expected_pgo expected_msvc_phase)
|
||||
_pgo_cache_value("${build_directory}" BRLCAD_PGO _pgo_enabled)
|
||||
if(expected_pgo AND NOT _pgo_enabled)
|
||||
message(FATAL_ERROR "BRLCAD_PGO is not enabled in ${build_directory}")
|
||||
elseif(NOT expected_pgo AND _pgo_enabled)
|
||||
message(FATAL_ERROR "The baseline build unexpectedly enables BRLCAD_PGO: ${build_directory}")
|
||||
endif()
|
||||
|
||||
_pgo_cache_value("${build_directory}" BRLCAD_MSVC_PGO_PHASE _pgo_msvc_phase)
|
||||
if(_pgo_msvc_phase AND NOT _pgo_msvc_phase STREQUAL expected_msvc_phase)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Expected MSVC PGO phase ${expected_msvc_phase} in ${build_directory}, found ${_pgo_msvc_phase}"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_pgo_find_build_file build_directory file_name output_variable)
|
||||
set(_pgo_candidates "${build_directory}/bin/${file_name}")
|
||||
if(DEFINED PGO_CONFIG AND NOT "${PGO_CONFIG}" STREQUAL "")
|
||||
list(
|
||||
APPEND
|
||||
_pgo_candidates
|
||||
"${build_directory}/bin/${PGO_CONFIG}/${file_name}"
|
||||
"${build_directory}/${PGO_CONFIG}/bin/${file_name}"
|
||||
)
|
||||
endif()
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(_pgo_executable_candidates "")
|
||||
foreach(_pgo_candidate IN LISTS _pgo_candidates)
|
||||
list(APPEND _pgo_executable_candidates "${_pgo_candidate}.exe")
|
||||
endforeach()
|
||||
list(APPEND _pgo_candidates ${_pgo_executable_candidates})
|
||||
endif()
|
||||
|
||||
foreach(_pgo_candidate IN LISTS _pgo_candidates)
|
||||
if(EXISTS "${_pgo_candidate}")
|
||||
set("${output_variable}" "${_pgo_candidate}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
message(FATAL_ERROR "Could not find ${file_name} under ${build_directory}/bin")
|
||||
endfunction()
|
||||
|
||||
function(_pgo_find_shell build_directory output_variable)
|
||||
if(DEFINED PGO_SHELL AND NOT "${PGO_SHELL}" STREQUAL "")
|
||||
set(_pgo_shell "${PGO_SHELL}")
|
||||
elseif(EXISTS "${build_directory}/CMakeCache.txt")
|
||||
file(
|
||||
STRINGS
|
||||
"${build_directory}/CMakeCache.txt"
|
||||
_pgo_shell_cache_entry
|
||||
LIMIT_COUNT 1
|
||||
REGEX "^SH_EXEC(:[^=]*)?="
|
||||
)
|
||||
if(_pgo_shell_cache_entry)
|
||||
string(REGEX REPLACE "^[^=]*=" "" _pgo_shell "${_pgo_shell_cache_entry}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED _pgo_shell OR "${_pgo_shell}" STREQUAL "" OR NOT EXISTS "${_pgo_shell}")
|
||||
unset(_pgo_shell)
|
||||
unset(_pgo_shell CACHE)
|
||||
find_program(_pgo_shell NAMES sh bash)
|
||||
endif()
|
||||
if(NOT _pgo_shell)
|
||||
message(FATAL_ERROR "The BRL-CAD benchmark requires a POSIX shell; set PGO_SHELL to its path")
|
||||
endif()
|
||||
set("${output_variable}" "${_pgo_shell}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_pgo_run_benchmark build_directory result_directory)
|
||||
_pgo_find_build_file("${build_directory}" benchmark _pgo_benchmark)
|
||||
_pgo_find_build_file("${build_directory}" rt _pgo_rt)
|
||||
_pgo_find_build_file("${build_directory}" pixcmp _pgo_pixcmp)
|
||||
_pgo_find_shell("${build_directory}" _pgo_shell)
|
||||
file(MAKE_DIRECTORY "${result_directory}")
|
||||
|
||||
message(STATUS "Running the BRL-CAD benchmark from ${build_directory}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${_pgo_shell}" "${_pgo_benchmark}" run
|
||||
"TIMEFRAME=${PGO_TIMEFRAME}"
|
||||
"MAXTIME=${PGO_MAXTIME}"
|
||||
"AVERAGE=${PGO_AVERAGE}"
|
||||
"DEVIATION=${PGO_DEVIATION}"
|
||||
"RT=${_pgo_rt}"
|
||||
"CMP=${_pgo_pixcmp}"
|
||||
-P1
|
||||
WORKING_DIRECTORY "${result_directory}"
|
||||
RESULT_VARIABLE _pgo_benchmark_result
|
||||
)
|
||||
if(NOT "${_pgo_benchmark_result}" STREQUAL "0")
|
||||
message(FATAL_ERROR "The benchmark from ${build_directory} failed with status ${_pgo_benchmark_result}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_pgo_extract_rate log_file output_text output_integer)
|
||||
if(NOT EXISTS "${log_file}")
|
||||
message(FATAL_ERROR "Benchmark log does not exist: ${log_file}")
|
||||
endif()
|
||||
file(READ "${log_file}" _pgo_log)
|
||||
string(REGEX MATCHALL "[0-9]+(\\.[0-9]+)? rays/sec \\(RTFM\\)" _pgo_rate_lines "${_pgo_log}")
|
||||
if(NOT _pgo_rate_lines)
|
||||
message(FATAL_ERROR "No RTFM result was found in ${log_file}")
|
||||
endif()
|
||||
list(GET _pgo_rate_lines -1 _pgo_rate_line)
|
||||
string(REGEX REPLACE " rays/sec.*$" "" _pgo_rate "${_pgo_rate_line}")
|
||||
|
||||
if(NOT _pgo_rate MATCHES "^([0-9]+)(\\.([0-9]+))?$")
|
||||
message(FATAL_ERROR "Invalid RTFM result '${_pgo_rate}' in ${log_file}")
|
||||
endif()
|
||||
set(_pgo_whole "${CMAKE_MATCH_1}")
|
||||
set(_pgo_fraction "${CMAKE_MATCH_3}00")
|
||||
string(SUBSTRING "${_pgo_fraction}" 0 2 _pgo_fraction)
|
||||
string(REGEX REPLACE "^0+" "" _pgo_whole "${_pgo_whole}")
|
||||
string(REGEX REPLACE "^0+" "" _pgo_fraction "${_pgo_fraction}")
|
||||
if("${_pgo_whole}" STREQUAL "")
|
||||
set(_pgo_whole 0)
|
||||
endif()
|
||||
if("${_pgo_fraction}" STREQUAL "")
|
||||
set(_pgo_fraction 0)
|
||||
endif()
|
||||
math(EXPR _pgo_rate_integer "${_pgo_whole} * 100 + ${_pgo_fraction}")
|
||||
if(_pgo_rate_integer LESS_EQUAL 0)
|
||||
message(FATAL_ERROR "Non-positive RTFM result '${_pgo_rate}' in ${log_file}")
|
||||
endif()
|
||||
|
||||
set("${output_text}" "${_pgo_rate}" PARENT_SCOPE)
|
||||
set("${output_integer}" "${_pgo_rate_integer}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_pgo_decimal_to_thousandths value output_variable)
|
||||
if(NOT "${value}" MATCHES "^([0-9]+)(\\.([0-9]+))?$")
|
||||
message(FATAL_ERROR "Expected a non-negative decimal number, not '${value}'")
|
||||
endif()
|
||||
set(_pgo_whole "${CMAKE_MATCH_1}")
|
||||
set(_pgo_fraction "${CMAKE_MATCH_3}000")
|
||||
string(SUBSTRING "${_pgo_fraction}" 0 3 _pgo_fraction)
|
||||
string(REGEX REPLACE "^0+" "" _pgo_whole "${_pgo_whole}")
|
||||
string(REGEX REPLACE "^0+" "" _pgo_fraction "${_pgo_fraction}")
|
||||
if("${_pgo_whole}" STREQUAL "")
|
||||
set(_pgo_whole 0)
|
||||
endif()
|
||||
if("${_pgo_fraction}" STREQUAL "")
|
||||
set(_pgo_fraction 0)
|
||||
endif()
|
||||
math(EXPR _pgo_value "${_pgo_whole} * 1000 + ${_pgo_fraction}")
|
||||
set("${output_variable}" "${_pgo_value}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_pgo_format_thousandths value output_variable)
|
||||
math(EXPR _pgo_whole "${value} / 1000")
|
||||
math(EXPR _pgo_fraction "${value} % 1000")
|
||||
set(_pgo_fraction "00${_pgo_fraction}")
|
||||
string(LENGTH "${_pgo_fraction}" _pgo_fraction_length)
|
||||
math(EXPR _pgo_fraction_offset "${_pgo_fraction_length} - 3")
|
||||
string(SUBSTRING "${_pgo_fraction}" ${_pgo_fraction_offset} 3 _pgo_fraction)
|
||||
set("${output_variable}" "${_pgo_whole}.${_pgo_fraction}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(PGO_MODE STREQUAL "TRAIN")
|
||||
_pgo_require(PGO_BUILD_DIR)
|
||||
_pgo_require(PGO_RESULTS_DIR)
|
||||
_pgo_require(PGO_PROFILE_DIR)
|
||||
_pgo_absolute_path("${PGO_BUILD_DIR}" PGO_BUILD_DIR)
|
||||
_pgo_absolute_path("${PGO_RESULTS_DIR}" PGO_RESULTS_DIR)
|
||||
_pgo_absolute_path("${PGO_PROFILE_DIR}" PGO_PROFILE_DIR)
|
||||
if(NOT IS_DIRECTORY "${PGO_BUILD_DIR}")
|
||||
message(FATAL_ERROR "PGO_BUILD_DIR does not exist: ${PGO_BUILD_DIR}")
|
||||
endif()
|
||||
_pgo_validate_build("${PGO_BUILD_DIR}" TRUE GENERATE)
|
||||
|
||||
# MSVC's profile runtime uses this location for each image's PGC files.
|
||||
# GCC ignores it and writes its GCDA files to the compiled-in PGO path.
|
||||
file(MAKE_DIRECTORY "${PGO_PROFILE_DIR}")
|
||||
set(ENV{VCPROFILE_PATH} "${PGO_PROFILE_DIR}")
|
||||
_pgo_run_benchmark("${PGO_BUILD_DIR}" "${PGO_RESULTS_DIR}/benchmark")
|
||||
|
||||
_pgo_find_build_file("${PGO_BUILD_DIR}" rt _pgo_rt)
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(_pgo_null_device NUL)
|
||||
else()
|
||||
set(_pgo_null_device /dev/null)
|
||||
endif()
|
||||
|
||||
set(_pgo_training_index 0)
|
||||
foreach(_pgo_model IN LISTS PGO_TRAINING_MODELS)
|
||||
math(EXPR _pgo_training_index "${_pgo_training_index} + 1")
|
||||
if(IS_ABSOLUTE "${_pgo_model}")
|
||||
set(_pgo_model_path "${_pgo_model}")
|
||||
else()
|
||||
set(_pgo_model_path "${PGO_BUILD_DIR}/${_pgo_model}")
|
||||
endif()
|
||||
if(NOT EXISTS "${_pgo_model_path}")
|
||||
message(FATAL_ERROR "Training model does not exist: ${_pgo_model_path}")
|
||||
endif()
|
||||
|
||||
get_filename_component(_pgo_log_name "${_pgo_model_path}" NAME_WE)
|
||||
string(REGEX REPLACE "[^A-Za-z0-9_.-]" "_" _pgo_log_name "${_pgo_log_name}")
|
||||
set(_pgo_log_file "${PGO_RESULTS_DIR}/${_pgo_training_index}-${_pgo_log_name}.log")
|
||||
message(STATUS "Training with ${_pgo_model_path}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${_pgo_rt}" -B -P1 "-s${PGO_TRAINING_SIZE}"
|
||||
"-a${PGO_TRAINING_AZIMUTH}" "-e${PGO_TRAINING_ELEVATION}"
|
||||
-o "${_pgo_null_device}" "${_pgo_model_path}"
|
||||
RESULT_VARIABLE _pgo_rt_result
|
||||
OUTPUT_VARIABLE _pgo_rt_output
|
||||
ERROR_VARIABLE _pgo_rt_error
|
||||
)
|
||||
file(WRITE "${_pgo_log_file}" "${_pgo_rt_output}${_pgo_rt_error}")
|
||||
if(NOT "${_pgo_rt_result}" STREQUAL "0")
|
||||
message(FATAL_ERROR "Training ${_pgo_model} failed with status ${_pgo_rt_result}; see ${_pgo_log_file}")
|
||||
endif()
|
||||
string(REGEX MATCH "[^\r\n]*rays/sec \\(RTFM\\)" _pgo_rtfm_line "${_pgo_rt_output}${_pgo_rt_error}")
|
||||
if(NOT _pgo_rtfm_line)
|
||||
message(FATAL_ERROR "Training ${_pgo_model} did not complete a raytrace; see ${_pgo_log_file}")
|
||||
endif()
|
||||
message(STATUS "${_pgo_model}: ${_pgo_rtfm_line}")
|
||||
endforeach()
|
||||
|
||||
file(GLOB_RECURSE _pgo_gcda_files LIST_DIRECTORIES FALSE "${PGO_PROFILE_DIR}/*.gcda")
|
||||
file(GLOB_RECURSE _pgo_pgc_files LIST_DIRECTORIES FALSE "${PGO_PROFILE_DIR}/*.pgc")
|
||||
list(LENGTH _pgo_gcda_files _pgo_gcda_count)
|
||||
list(LENGTH _pgo_pgc_files _pgo_pgc_count)
|
||||
math(EXPR _pgo_profile_count "${_pgo_gcda_count} + ${_pgo_pgc_count}")
|
||||
if(_pgo_profile_count EQUAL 0)
|
||||
message(FATAL_ERROR "Training did not generate GCC GCDA or MSVC PGC data under ${PGO_PROFILE_DIR}")
|
||||
endif()
|
||||
message(STATUS "Training generated ${_pgo_profile_count} profile counter files under ${PGO_PROFILE_DIR}")
|
||||
else()
|
||||
_pgo_require(PGO_BASELINE_BUILD_DIR)
|
||||
_pgo_require(PGO_OPTIMIZED_BUILD_DIR)
|
||||
_pgo_require(PGO_RESULTS_DIR)
|
||||
_pgo_absolute_path("${PGO_BASELINE_BUILD_DIR}" PGO_BASELINE_BUILD_DIR)
|
||||
_pgo_absolute_path("${PGO_OPTIMIZED_BUILD_DIR}" PGO_OPTIMIZED_BUILD_DIR)
|
||||
_pgo_absolute_path("${PGO_RESULTS_DIR}" PGO_RESULTS_DIR)
|
||||
_pgo_validate_build("${PGO_BASELINE_BUILD_DIR}" FALSE "")
|
||||
_pgo_validate_build("${PGO_OPTIMIZED_BUILD_DIR}" TRUE USE)
|
||||
|
||||
_pgo_run_benchmark("${PGO_BASELINE_BUILD_DIR}" "${PGO_RESULTS_DIR}/baseline")
|
||||
_pgo_run_benchmark("${PGO_OPTIMIZED_BUILD_DIR}" "${PGO_RESULTS_DIR}/optimized")
|
||||
|
||||
set(_pgo_report "### Profile-guided optimization results\n\n")
|
||||
string(APPEND _pgo_report "| Model | Baseline rays/sec | PGO rays/sec | Speedup |\n")
|
||||
string(APPEND _pgo_report "| --- | ---: | ---: | ---: |\n")
|
||||
set(_pgo_speedup_sum 0)
|
||||
set(_pgo_model_count 0)
|
||||
set(_pgo_tsv "model\tbaseline_rays_per_second\tpgo_rays_per_second\tspeedup\n")
|
||||
|
||||
foreach(_pgo_model IN LISTS PGO_MODELS)
|
||||
_pgo_extract_rate("${PGO_RESULTS_DIR}/baseline/${_pgo_model}.log" _pgo_baseline_rate _pgo_baseline_integer)
|
||||
_pgo_extract_rate("${PGO_RESULTS_DIR}/optimized/${_pgo_model}.log" _pgo_optimized_rate _pgo_optimized_integer)
|
||||
math(
|
||||
EXPR
|
||||
_pgo_speedup
|
||||
"(${_pgo_optimized_integer} * 1000 + ${_pgo_baseline_integer} / 2) / ${_pgo_baseline_integer}"
|
||||
)
|
||||
_pgo_format_thousandths("${_pgo_speedup}" _pgo_speedup_text)
|
||||
math(EXPR _pgo_speedup_sum "${_pgo_speedup_sum} + ${_pgo_speedup}")
|
||||
math(EXPR _pgo_model_count "${_pgo_model_count} + 1")
|
||||
string(
|
||||
APPEND
|
||||
_pgo_report
|
||||
"| `${_pgo_model}` | ${_pgo_baseline_rate} | ${_pgo_optimized_rate} | ${_pgo_speedup_text}x |\n"
|
||||
)
|
||||
string(
|
||||
APPEND
|
||||
_pgo_tsv
|
||||
"${_pgo_model}\t${_pgo_baseline_rate}\t${_pgo_optimized_rate}\t${_pgo_speedup_text}\n"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(_pgo_model_count EQUAL 0)
|
||||
message(FATAL_ERROR "PGO_MODELS must name at least one benchmark model")
|
||||
endif()
|
||||
math(EXPR _pgo_mean_speedup "(${_pgo_speedup_sum} + ${_pgo_model_count} / 2) / ${_pgo_model_count}")
|
||||
_pgo_format_thousandths("${_pgo_mean_speedup}" _pgo_mean_speedup_text)
|
||||
string(APPEND _pgo_report "\nArithmetic mean speedup: ${_pgo_mean_speedup_text}x\n")
|
||||
file(MAKE_DIRECTORY "${PGO_RESULTS_DIR}")
|
||||
file(WRITE "${PGO_RESULTS_DIR}/results.tsv" "${_pgo_tsv}")
|
||||
|
||||
if(DEFINED PGO_SUMMARY_FILE AND NOT "${PGO_SUMMARY_FILE}" STREQUAL "")
|
||||
_pgo_absolute_path("${PGO_SUMMARY_FILE}" _pgo_summary_file)
|
||||
elseif(NOT "$ENV{GITHUB_STEP_SUMMARY}" STREQUAL "")
|
||||
set(_pgo_summary_file "$ENV{GITHUB_STEP_SUMMARY}")
|
||||
endif()
|
||||
if(DEFINED _pgo_summary_file)
|
||||
file(APPEND "${_pgo_summary_file}" "${_pgo_report}")
|
||||
endif()
|
||||
message("${_pgo_report}")
|
||||
|
||||
_pgo_decimal_to_thousandths("${PGO_MIN_SPEEDUP}" _pgo_min_speedup)
|
||||
if(NOT _pgo_mean_speedup GREATER _pgo_min_speedup)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"PGO raytracing speedup ${_pgo_mean_speedup_text}x did not exceed ${PGO_MIN_SPEEDUP}x"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
@@ -7,14 +7,25 @@
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
# Note: we set these variables to tell the ccc-analyzer script which compilers
|
||||
# to use, but it is not always enough - when some of the sub-builds are
|
||||
# triggered, they do not seem to inherit these settings and revert to the
|
||||
# default compiler. The only way so far to avoid this issue reliably seems to
|
||||
# be to edit the ccc-analyzer script to use the compiler we want as the default
|
||||
# compiler.
|
||||
export CCC_CC=clang
|
||||
export CCC_CXX=clang++
|
||||
# CLANG_VERSION should be set by User or CI environments to avoid hard-coding
|
||||
# a particular version into the script
|
||||
if [ -z "$CLANG_VERSION" ]; then
|
||||
echo "Error: CLANG_VERSION environment variable is not set." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Derive tool paths from the version
|
||||
SCAN_BUILD_DIR="/usr/share/clang/scan-build-${CLANG_VERSION}"
|
||||
SCAN_BUILD_BIN="${SCAN_BUILD_DIR}/bin"
|
||||
SCAN_BUILD_LIBEXEC="${SCAN_BUILD_DIR}/libexec"
|
||||
CLANG_ANALYZER_BIN="/usr/bin/clang-${CLANG_VERSION}"
|
||||
|
||||
# Add scan-build to the PATH
|
||||
export PATH="${SCAN_BUILD_BIN}:${SCAN_BUILD_LIBEXEC}:${PATH}"
|
||||
|
||||
# Set compilers for the analyzer scripts
|
||||
export CCC_CC="clang-${CLANG_VERSION}"
|
||||
export CCC_CXX="clang++-${CLANG_VERSION}"
|
||||
|
||||
# This appears to be a workable way to enable the new Z3 static analyzer
|
||||
# support, but at least as of 2017-12 it greatly slows the testing (by orders
|
||||
@@ -45,19 +56,24 @@ fi
|
||||
|
||||
# Encapsulate the logic to do a scan build
|
||||
function runtest {
|
||||
echo "$1"
|
||||
scan-build --use-analyzer=/usr/bin/$CCC_CC -o ./scan-reports-$1 make -j12 $1
|
||||
if [ "$(ls -A ./scan-reports-$1)" ]; then
|
||||
report_cnt=$(ls -l ./scan-reports-$1/*/report* | wc -l)
|
||||
failure=$(($failure + $report_cnt))
|
||||
else
|
||||
rm -rf ./scan-reports-$1
|
||||
fi
|
||||
echo "$1"
|
||||
scan-build --use-analyzer="${CLANG_ANALYZER_BIN}" -o "./scan-reports-$1" make -j12 "$1"
|
||||
if [ -d "./scan-reports-$1" ] && [ -n "$(ls -A "./scan-reports-$1")" ]; then
|
||||
report_cnt=$(find "./scan-reports-$1" -name 'report-*.html' | wc -l)
|
||||
failure=$((failure + report_cnt))
|
||||
else
|
||||
rm -rf "./scan-reports-$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# configure using the correct compiler and values. We don't
|
||||
# need this report, so clear it after configure is done
|
||||
scan-build --use-analyzer=/usr/bin/$CCC_CC -o ./scan-reports-config cmake .. -DBRLCAD_EXTRADOCS=OFF -DBRLCAD_ENABLE_QT=ON -DBRLCAD_LTO_MODE=OFF -DBRLCAD_EXT_DIR="$bext_dir" -DCMAKE_C_COMPILER=ccc-analyzer -DCMAKE_CXX_COMPILER=c++-analyzer
|
||||
# Configure using the correct compiler and values.
|
||||
scan-build --use-analyzer="${CLANG_ANALYZER_BIN}" -o ./scan-reports-config cmake .. \
|
||||
-DBRLCAD_EXTRADOCS=OFF \
|
||||
-DBRLCAD_ENABLE_QT=ON \
|
||||
-DBRLCAD_LTO_MODE=OFF \
|
||||
-DBRLCAD_EXT_DIR="$bext_dir" \
|
||||
-DCMAKE_C_COMPILER=ccc-analyzer \
|
||||
-DCMAKE_CXX_COMPILER=c++-analyzer
|
||||
|
||||
# clear out any old reports
|
||||
rm -rfv ./scan-reports-*
|
||||
|
||||
@@ -109,6 +109,16 @@ brlcad_addexec(g-var g-var.c "librt;libbu;${M_LIBRARY}" FOLDER Conv)
|
||||
brlcad_addexec(g-vrml g-vrml.c "librt;libnmg;libbu;${M_LIBRARY}" FOLDER Conv)
|
||||
|
||||
brlcad_addexec(g-x3d g-x3d.c "librt;libnmg;libbu;${M_LIBRARY}" FOLDER Conv)
|
||||
# GCC cannot model BU_SETJUMP's longjmp path during LTO and reports an
|
||||
# anonymous value as potentially uninitialized.
|
||||
check_linker_flag(
|
||||
"C"
|
||||
"-Wno-error=maybe-uninitialized"
|
||||
G_X3D_LINKER_WNO_MAYBE_UNINITIALIZED
|
||||
)
|
||||
if(G_X3D_LINKER_WNO_MAYBE_UNINITIALIZED)
|
||||
target_link_options(g-x3d PRIVATE -Wno-maybe-uninitialized)
|
||||
endif()
|
||||
|
||||
brlcad_addexec(nastran-g nastran-g.c "libwdb;librt;libnmg;libbu;${M_LIBRARY}" FOLDER Conv)
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks ) {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize the info structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo),1));
|
||||
SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1,sizeof(SHPInfo)));
|
||||
|
||||
psSHP->bUpdated = FALSE;
|
||||
memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
|
||||
@@ -1176,7 +1176,7 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
|
||||
psObject->nParts = MAX(1,nParts);
|
||||
|
||||
psObject->panPartStart = STATIC_CAST(int *,
|
||||
calloc(sizeof(int), psObject->nParts));
|
||||
calloc(psObject->nParts, sizeof(int)));
|
||||
psObject->panPartType = STATIC_CAST(int *,
|
||||
malloc(sizeof(int) * psObject->nParts));
|
||||
|
||||
@@ -1205,13 +1205,13 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
|
||||
{
|
||||
const size_t nSize = sizeof(double) * nVertices;
|
||||
psObject->padfX = STATIC_CAST(double *, padfX ? malloc(nSize) :
|
||||
calloc(sizeof(double),nVertices));
|
||||
calloc(nVertices,sizeof(double)));
|
||||
psObject->padfY = STATIC_CAST(double *, padfY ? malloc(nSize) :
|
||||
calloc(sizeof(double),nVertices));
|
||||
calloc(nVertices,sizeof(double)));
|
||||
psObject->padfZ = STATIC_CAST(double *, padfZ && bHasZ ? malloc(nSize) :
|
||||
calloc(sizeof(double),nVertices));
|
||||
calloc(nVertices,sizeof(double)));
|
||||
psObject->padfM = STATIC_CAST(double *, padfM && bHasM ? malloc(nSize) :
|
||||
calloc(sizeof(double),nVertices));
|
||||
calloc(nVertices,sizeof(double)));
|
||||
if( padfX != SHPLIB_NULLPTR )
|
||||
memcpy(psObject->padfX, padfX, nSize);
|
||||
if( padfY != SHPLIB_NULLPTR )
|
||||
|
||||
@@ -5545,8 +5545,8 @@ repair_ambiguous_singular_periodic_loop_branches(ON_Brep *brep,
|
||||
std::vector<int> affected_positions;
|
||||
affected_positions.reserve(arc_positions.size() + 2);
|
||||
affected_positions.push_back(first_position);
|
||||
affected_positions.insert(affected_positions.end(),
|
||||
arc_positions.begin(), arc_positions.end());
|
||||
for (const int position : arc_positions)
|
||||
affected_positions.push_back(position);
|
||||
affected_positions.push_back(second_position);
|
||||
|
||||
for (int shift_sign = -1; shift_sign <= 1 && !repaired;
|
||||
|
||||
+20
-16
@@ -50,16 +50,16 @@
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
|
||||
void SHA1Transform(uint32_t state[5], const unsigned char buffer[SHA1_BLOCK_SIZE])
|
||||
{
|
||||
uint32_t a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
unsigned char c[SHA1_BLOCK_SIZE];
|
||||
uint32_t l[16];
|
||||
} CHAR64LONG16;
|
||||
#ifdef SHA1HANDSOFF
|
||||
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
|
||||
memcpy(block, buffer, 64);
|
||||
memcpy(block, buffer, sizeof(block));
|
||||
#else
|
||||
/* The following had better never be used because it causes the
|
||||
* pointer-to-const buffer to be cast into a pointer to non-const.
|
||||
@@ -131,11 +131,11 @@ void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
|
||||
if ((context->count[0] += len << 3) < j)
|
||||
context->count[1]++;
|
||||
context->count[1] += (len>>29);
|
||||
j = (j >> 3) & 63;
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
j = (j >> 3) & (SHA1_BLOCK_SIZE - 1);
|
||||
if ((j + len) >= SHA1_BLOCK_SIZE) {
|
||||
memcpy(&context->buffer[j], data, (i = SHA1_BLOCK_SIZE-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
for ( ; i + SHA1_BLOCK_SIZE - 1 < len; i += SHA1_BLOCK_SIZE) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
@@ -149,22 +149,26 @@ void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||
{
|
||||
unsigned i;
|
||||
static const unsigned char padding[SHA1_BLOCK_SIZE] = {0x80};
|
||||
unsigned char finalcount[8];
|
||||
unsigned char c;
|
||||
const uint32_t block_size = (uint32_t)sizeof(context->buffer);
|
||||
const uint32_t length_offset = block_size - (uint32_t)sizeof(finalcount);
|
||||
uint32_t buffer_used;
|
||||
uint32_t padding_length;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
|
||||
c = 0200;
|
||||
SHA1Update(context, &c, 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
c = 0000;
|
||||
SHA1Update(context, &c, 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
buffer_used = (context->count[0] >> 3) & (block_size - 1);
|
||||
if (buffer_used < length_offset)
|
||||
padding_length = length_offset - buffer_used;
|
||||
else
|
||||
padding_length = block_size + length_offset - buffer_used;
|
||||
SHA1Update(context, padding, padding_length);
|
||||
SHA1Update(context, finalcount, (uint32_t)sizeof(finalcount));
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
|
||||
+4
-2
@@ -7,15 +7,17 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[5];
|
||||
uint32_t count[2];
|
||||
unsigned char buffer[64];
|
||||
unsigned char buffer[SHA1_BLOCK_SIZE];
|
||||
} SHA1_CTX;
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
|
||||
void SHA1Transform(uint32_t state[5], const unsigned char buffer[SHA1_BLOCK_SIZE]);
|
||||
void SHA1Init(SHA1_CTX* context);
|
||||
void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ extern double drand48(void);
|
||||
|
||||
|
||||
int
|
||||
bu_uuid_create(uint8_t uuid[STATIC_ARRAY(16)], size_t nbytes, const uint8_t *bytes, const uint8_t namespace_uuid[STATIC_ARRAY(16)])
|
||||
bu_uuid_create(uint8_t uuid[STATIC_ARRAY(16)], size_t nbytes, const uint8_t *bytes, const uint8_t *namespace_uuid)
|
||||
{
|
||||
int type = 4; /* random */
|
||||
|
||||
|
||||
@@ -934,7 +934,7 @@ x24_setup(struct fb *ifp, int width, int height)
|
||||
case FLG_VP8:
|
||||
case FLG_VS8:
|
||||
case FLG_VG8:
|
||||
if ((xi->xi_pix = (unsigned char *) calloc(sizeof(uint8_t), width*height)) == NULL) {
|
||||
if ((xi->xi_pix = (unsigned char *) calloc(width*height, sizeof(uint8_t))) == NULL) {
|
||||
fb_log("X24_open: pix8 malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -950,7 +950,7 @@ x24_setup(struct fb *ifp, int width, int height)
|
||||
xi->xi_visual, xi->xi_depth, XYBitmap, 0,
|
||||
NULL, width, height, 32, 0);
|
||||
|
||||
if ((xi->xi_pix = (unsigned char *) calloc(sizeof(uint8_t), xi->xi_image->bytes_per_line * height)) == NULL) {
|
||||
if ((xi->xi_pix = (unsigned char *) calloc(xi->xi_image->bytes_per_line * height, sizeof(uint8_t))) == NULL) {
|
||||
fb_log("X24_open: pix1 malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -2653,7 +2653,7 @@ X24_configureWindow(struct fb *ifp, int width, int height)
|
||||
XDestroyImage(xi->xi_image);
|
||||
|
||||
/* Make new buffers and new image */
|
||||
if ((xi->xi_pix = (unsigned char *)calloc(sizeof(uint8_t), xi->xi_xwidth * xi->xi_xheight)) == NULL) {
|
||||
if ((xi->xi_pix = (unsigned char *)calloc(xi->xi_xwidth * xi->xi_xheight, sizeof(uint8_t))) == NULL) {
|
||||
fb_log("X24: pix8 malloc failed in resize!\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -2671,7 +2671,7 @@ X24_configureWindow(struct fb *ifp, int width, int height)
|
||||
xi->xi_visual, xi->xi_depth, XYBitmap, 0,
|
||||
NULL, xi->xi_xwidth, xi->xi_xheight, 32, 0);
|
||||
|
||||
if ((xi->xi_pix = (unsigned char *)calloc(sizeof(uint8_t), xi->xi_image->bytes_per_line * xi->xi_xheight)) == NULL) {
|
||||
if ((xi->xi_pix = (unsigned char *)calloc(xi->xi_image->bytes_per_line * xi->xi_xheight, sizeof(uint8_t))) == NULL) {
|
||||
fb_log("X24: pix1 malloc failed in resize!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -422,12 +422,12 @@ fb_open(const char *file, int width, int height)
|
||||
if (width < 0 || height < 0)
|
||||
return FB_NULL;
|
||||
|
||||
ifp = (struct fb *)calloc(sizeof(struct fb), 1);
|
||||
ifp = (struct fb *)calloc(1, sizeof(struct fb));
|
||||
if (ifp == FB_NULL) {
|
||||
Malloc_Bomb(sizeof(struct fb));
|
||||
return FB_NULL;
|
||||
}
|
||||
ifp->i = (struct fb_impl *)calloc(sizeof(struct fb_impl), 1);
|
||||
ifp->i = (struct fb_impl *)calloc(1, sizeof(struct fb_impl));
|
||||
if (file == NULL || *file == '\0') {
|
||||
/* No name given, check environment variable first. */
|
||||
file = (const char *)getenv("FB_FILE");
|
||||
|
||||
@@ -114,8 +114,8 @@ struct fb *
|
||||
fb_open_existing(const char *file, int width, int height, struct fb_platform_specific *fb_p)
|
||||
{
|
||||
struct fb *ifp;
|
||||
ifp = (struct fb *)calloc(sizeof(struct fb), 1);
|
||||
ifp->i = (struct fb_impl *) calloc(sizeof(struct fb_impl), 1);
|
||||
ifp = (struct fb *)calloc(1, sizeof(struct fb));
|
||||
ifp->i = (struct fb_impl *) calloc(1, sizeof(struct fb_impl));
|
||||
fb_set_interface(ifp, file);
|
||||
fb_set_magic(ifp, FB_MAGIC);
|
||||
fb_setup_existing(ifp, width, height, fb_p);
|
||||
|
||||
@@ -111,7 +111,7 @@ hlbvh_init_pool(size_t n_primatives) {
|
||||
}
|
||||
|
||||
/* utility functions */
|
||||
static inline uint32_t left_shift3(uint32_t x)
|
||||
static uint32_t left_shift3(uint32_t x)
|
||||
{
|
||||
BU_ASSERT(x <= (1 << 10));
|
||||
if (x == (1 << 10)) --x;
|
||||
@@ -299,7 +299,7 @@ maximum_extent(const fastf_t b[6])
|
||||
return 2;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static int
|
||||
pred(const struct bvh_build_node *node, fastf_t *centroid_bounds,
|
||||
uint8_t dim, long min_cost_split_bucket)
|
||||
{
|
||||
|
||||
@@ -730,7 +730,7 @@ bot_makesegs_specific(hit_da *hits,
|
||||
/* r_min can describe a spatial partition cell that begins inside this
|
||||
* solid. Start BVH traversal just before the ray enters the BoT's own
|
||||
* root box so entrance triangles behind the ray origin remain visible. */
|
||||
static inline void
|
||||
static void
|
||||
bot_backed_origin(point_t b_pt, const struct xray *rp, const struct bvh_flat_node *root,
|
||||
const vect_t inv_dir, const struct soltab *stp)
|
||||
{
|
||||
|
||||
@@ -517,7 +517,7 @@ rt_metaball_vshot(struct soltab *stp[], struct xray *rp[], struct seg *segp, int
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
static void
|
||||
rt_metaball_norm_internal(vect_t *n, point_t *p, struct rt_metaball_internal *mb)
|
||||
{
|
||||
struct wdb_metaball_pnt *mbpt;
|
||||
|
||||
@@ -27,7 +27,6 @@ __BEGIN_DECLS
|
||||
int rt_metaball_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol);
|
||||
fastf_t rt_metaball_get_bounding_sphere(point_t *center, fastf_t threshold, struct rt_metaball_internal *mb);
|
||||
int rt_metaball_find_intersection(point_t *intersect, const struct rt_metaball_internal *mb, const point_t *a, const point_t *b, fastf_t step, const fastf_t finalstep);
|
||||
void rt_metaball_norm_internal(vect_t *n, point_t *p, struct rt_metaball_internal *mb);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* LIBRT_PRIMITIVES_METABALL_METABALL_H */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define PART_SPHERE_HEIGHT_RATIO 0.001
|
||||
#define PART_CYLINDER_RADIUS_RATIO 0.001
|
||||
|
||||
static inline int
|
||||
static int
|
||||
part_update_type(struct rt_part_internal *part)
|
||||
{
|
||||
if (!part || !isfinite(part->part_vrad) ||
|
||||
|
||||
+1
-1
@@ -337,7 +337,7 @@ main(int ac, char *av[])
|
||||
unsigned char ground_rgb[3];
|
||||
unsigned char light_rgb[3];
|
||||
|
||||
double pitch_r[MAX_GEARS];
|
||||
double pitch_r[MAX_GEARS] = {0.0};
|
||||
double center_x[MAX_GEARS];
|
||||
double total_span;
|
||||
double max_outer;
|
||||
|
||||
Reference in New Issue
Block a user