Browse Source

CMake: Add options for profile guided optimization

A PGO'd binary can be built as follows:

1. Build with `-DDEVILUTIONX_PROFILE_GENERATE=ON`.
3. Run the timedemo.
4. Build with `-DDEVILUTIONX_PROFILE_USE=ON`.
By default, the profile directory is at `${HOME}/devilutionx-profile`

Example for the RG99:

```bash
# Build the OPK for profiling data collection:
TOOLCHAIN=/opt/rs90-toolchain Packaging/OpenDingux/build.sh rg99 --profile-generate

# Copy the OPK to RG99:
scp -O build-rg99/devilutionx-rg99.opk rg99:/media/sdcard/apps

# Now, run the OPK. It will run the timedemo instead of the actual game and will take a couple of hours.
# 

# Copy the profiling data from RG99
scp -r -O rg99:/media/data/local/home/devilutionx-profile /tmp/devilutionx-profile

# Build the OPK use the collected profiling data:
TOOLCHAIN=/opt/rs90-toolchain Packaging/OpenDingux/build.sh rg99 --profile-use --profile-dir /tmp/devilutionx-profile

# Copy the resulting binary back to RG99
scp -O build-rg99/devilutionx-rg99.opk rg99:/media/sdcard/apps
```
pull/5620/head
Gleb Mazovetskiy 3 years ago
parent
commit
96c7b154be
  1. 1
      CMake/platforms/rg99.cmake
  2. 12
      CMakeLists.txt
  3. 119
      Packaging/OpenDingux/build.sh
  4. 13
      Packaging/OpenDingux/package-opk.sh
  5. 10
      Packaging/OpenDingux/profile-generate.sh

1
CMake/platforms/rg99.cmake

@ -2,7 +2,6 @@
set(BUILD_ASSETS_MPQ OFF)
set(UNPACKED_MPQS ON)
set(NONET ON)
set(DISABLE_DEMOMODE ON)
set(USE_SDL1 ON)
# Link `libstdc++` dynamically: ~1.3 MiB.

12
CMakeLists.txt

@ -117,6 +117,9 @@ option(PIE "Generate position-independent code" OFF)
cmake_dependent_option(DEVILUTIONX_DISABLE_RTTI "Disable RTTI" ON "NONET" OFF)
cmake_dependent_option(DEVILUTIONX_DISABLE_EXCEPTIONS "Disable exceptions" ON "NONET" OFF)
RELEASE_OPTION(DEVILUTIONX_STATIC_CXX_STDLIB "Link C++ standard library statically (if available)")
option(DEVILUTIONX_PROFILE_GENERATE "Build a binary that generates the profile for PGO" OFF)
option(DEVILUTIONX_PROFILE_USE "Build with PGO using the given profile file" OFF)
set(DEVILUTIONX_PROFILE_DIR "" CACHE STRING "Directory where the profile is stored")
include(MoldLinker)
@ -225,6 +228,15 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT PS4)
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_options("$<$<BOOL:${DEVILUTIONX_PROFILE_GENERATE}>:-fprofile-generate>")
add_link_options("$<$<BOOL:${DEVILUTIONX_PROFILE_GENERATE}>:-fprofile-generate>")
add_compile_options("$<$<BOOL:${DEVILUTIONX_PROFILE_USE}>:-fprofile-use>")
add_link_options("$<$<BOOL:${DEVILUTIONX_PROFILE_USE}>:-fprofile-use>")
add_compile_options("$<$<BOOL:${DEVILUTIONX_PROFILE_DIR}>:-fprofile-dir=${DEVILUTIONX_PROFILE_DIR}>")
add_link_options("$<$<BOOL:${DEVILUTIONX_PROFILE_DIR}>:-fprofile-dir=${DEVILUTIONX_PROFILE_DIR}>")
endif()
# Not a genexp because CMake doesn't support it
# https://gitlab.kitware.com/cmake/cmake/-/issues/20546
if(NOT DISABLE_LTO)

119
Packaging/OpenDingux/build.sh

@ -8,17 +8,10 @@ source Packaging/OpenDingux/targets.sh
source Packaging/OpenDingux/package-opk.sh
usage() {
echo "Usage: build.sh [target]"
usage_target
>&2 echo "Usage: build.sh [--profile-generate|--profile-use] [--profile-dir PATH] [target]"
>&2 usage_target
}
if ! check_target "$@"; then
usage
exit 64
fi
declare -r TARGET="$1"
declare -r BUILD_DIR="build-${TARGET}"
declare -rA BUILDROOT_REPOS=(
[lepus]=https://github.com/OpenDingux/buildroot.git
[retrofw]=https://github.com/retrofw/buildroot.git
@ -34,15 +27,29 @@ declare -rA BUILDROOT_DEFCONFIGS=(
[gkd350h]='rg350_defconfig BR2_EXTERNAL=board/opendingux'
)
declare BUILDROOT_TARGET="$TARGET"
declare TARGET
declare BUILD_DIR
declare BUILDROOT
declare BUILDROOT_TARGET
declare TOOLCHAIN
# If a TOOLCHAIN environment variable is set, just use that.
if [[ -z ${TOOLCHAIN:-} ]]; then
BUILDROOT="${BUILDROOT:-$HOME/devilutionx-buildroots/$BUILDROOT_TARGET}"
TOOLCHAIN="${BUILDROOT}/output/host"
fi
declare -a CMAKE_CONFIGURE_OPTS=()
declare PROFILE_GENERATE=0
declare PROFILE_USE=0
declare PROFILE_DIR="%q{HOME}/devilutionx-profile"
declare BUILD_TYPE=release
main() {
parse_args "$@"
BUILD_DIR="build-${TARGET}"
BUILDROOT_TARGET="$TARGET"
# If a TOOLCHAIN environment variable is set, just use that.
if [[ -z ${TOOLCHAIN:-} ]]; then
BUILDROOT="${BUILDROOT:-$HOME/devilutionx-buildroots/$BUILDROOT_TARGET}"
TOOLCHAIN="${BUILDROOT}/output/host"
fi
>&2 echo "Building for target ${TARGET} in ${BUILD_DIR}"
set -x
if [[ -n ${BUILDROOT:-} ]]; then
@ -53,6 +60,74 @@ main() {
package_opk
}
parse_args() {
local -a positional=()
while [[ $# -gt 0 ]]; do
case "$1" in
--profile-generate)
PROFILE_GENERATE=1
shift
;;
--profile-use)
PROFILE_USE=1
shift
;;
--profile-dir)
shift
if [[ $# -eq 0 ]]; then
usage
exit 64
fi
PROFILE_DIR="$1"
shift
;;
-*|--*)
>&2 echo "Error: unknown argument $1"
>&2 echo
usage
exit 64
;;
*)
positional+=("$1")
shift
;;
esac
done
if [[ ${#positional[@]} -ne 1 ]] || ! check_target "${positional[0]}"; then
>&2 echo "Error: target is required"
>&2 echo
usage
exit 64
fi
TARGET="${positional[0]}"
if (( PROFILE_GENERATE )) && (( PROFILE_USE )); then
>&2 echo "Error: at most one of --profile-use and --profile-generate is allowed"
exit 64
fi
if (( PROFILE_GENERATE )); then
CMAKE_CONFIGURE_OPTS+=(
"-DDEVILUTIONX_PROFILE_GENERATE=ON"
"-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}"
)
BUILD_TYPE=relwithdebinfo
OPK_DESKTOP_NAME="DevilutionX PG"
OPK_DESKTOP_EXEC="profile-generate.sh"
OPK_EXTRA_FILES=(
Packaging/OpenDingux/profile-generate.sh
test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo
test/fixtures/timedemo/WarriorLevel1to2/demo_0_reference_spawn_0.sv
test/fixtures/timedemo/WarriorLevel1to2/spawn_0.sv
)
fi
if (( PROFILE_USE )); then
CMAKE_CONFIGURE_OPTS+=(
"-DDEVILUTIONX_PROFILE_USE=ON"
"-DDEVILUTIONX_PROFILE_DIR=${PROFILE_DIR}"
)
fi
}
prepare_buildroot() {
if [[ -d $BUILDROOT ]]; then
return
@ -90,7 +165,7 @@ cmake_configure() {
-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF \
-DDEVILUTIONX_SYSTEM_BZIP2=OFF \
-DSTACK_PROTECTOR=OFF \
"$@"
"${CMAKE_CONFIGURE_OPTS[@]}"
}
cmake_build() {
@ -102,30 +177,30 @@ strip_bin() {
}
build_debug() {
cmake_configure -DCMAKE_BUILD_TYPE=Debug -DASAN=OFF -DUBSAN=OFF -DCMAKE_CXX_FLAGS_DEBUG="-g -fno-omit-frame-pointer"
cmake_configure -DCMAKE_BUILD_TYPE=Debug -DASAN=OFF -DUBSAN=OFF -DCMAKE_CXX_FLAGS_DEBUG="-g -fno-omit-frame-pointer" "$@"
cmake_build
}
build_relwithdebinfo() {
cmake_configure -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake_configure -DCMAKE_BUILD_TYPE=RelWithDebInfo "$@"
cmake_build
}
build_minsizerel() {
cmake_configure -DCMAKE_BUILD_TYPE=MinSizeRel
cmake_configure -DCMAKE_BUILD_TYPE=MinSizeRel "$@"
cmake_build
strip_bin
}
build_release() {
cmake_configure -DCMAKE_BUILD_TYPE=Release
cmake_configure -DCMAKE_BUILD_TYPE=Release "$@"
cmake_build
strip_bin
}
build() {
rm -f "${BUILD_DIR}/CMakeCache.txt"
build_release
build_"$BUILD_TYPE" "$@"
}
main
main "$@"

13
Packaging/OpenDingux/package-opk.sh

@ -1,5 +1,9 @@
#!/usr/bin/env bash
declare OPK_DESKTOP_NAME
declare OPK_DESKTOP_EXEC
declare -a OPK_EXTRA_FILES
package_opk() {
local ext
if [[ $TARGET == rg350 ]] || [[ $TARGET == gkd350h ]]; then
@ -13,10 +17,19 @@ package_opk() {
mkdir -p "$tmp"
cp "Packaging/OpenDingux/${TARGET}.desktop" "${tmp}/default.${ext}.desktop"
cp "Packaging/OpenDingux/${TARGET}-manual.txt" "${tmp}/readme.${ext}.txt"
if [[ -v OPK_DESKTOP_NAME ]]; then
sed -i "s/Name=.*/Name=${OPK_DESKTOP_NAME}/" "${tmp}/default.${ext}.desktop"
fi
if [[ -v OPK_DESKTOP_EXEC ]]; then
sed -i "s/Exec=.*/Exec=${OPK_DESKTOP_EXEC}/" "${tmp}/default.${ext}.desktop"
fi
mksquashfs "${BUILD_DIR}/devilutionx" \
"${tmp}/default.${ext}.desktop" \
"${tmp}/readme.${ext}.txt" Packaging/resources/icon_32.png \
"${BUILD_DIR}/assets/" \
"${OPK_EXTRA_FILES[@]}" \
"${BUILD_DIR}/devilutionx-${TARGET}.opk" \
-all-root -no-xattrs -noappend -no-exports -no-progress
}

10
Packaging/OpenDingux/profile-generate.sh

@ -0,0 +1,10 @@
#!/bin/sh
set -x
SAVE_DIR="$(mktemp -d)"
ln -s "${PWD}/demo_0_reference_spawn_0.sv" "${SAVE_DIR}/"
ln -s "${PWD}/demo_0.dmo" "${SAVE_DIR}/"
cp "${PWD}/spawn_0.sv" "${SAVE_DIR}/"
./devilutionx --diablo --spawn --demo 0 --timedemo --save-dir "$SAVE_DIR" --data-dir ~/.local/share/diasurgical/devilution
rm -rf "$SAVE_DIR"
Loading…
Cancel
Save