diff --git a/CMake/platforms/rg99.cmake b/CMake/platforms/rg99.cmake index 70226ab71..450f8d464 100644 --- a/CMake/platforms/rg99.cmake +++ b/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. diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f2f0b63..0d68fbfc7 100644 --- a/CMakeLists.txt +++ b/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("$<$:-fprofile-generate>") + add_link_options("$<$:-fprofile-generate>") + add_compile_options("$<$:-fprofile-use>") + add_link_options("$<$:-fprofile-use>") + add_compile_options("$<$:-fprofile-dir=${DEVILUTIONX_PROFILE_DIR}>") + add_link_options("$<$:-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) diff --git a/Packaging/OpenDingux/build.sh b/Packaging/OpenDingux/build.sh index 7c9cb793d..ad08758b4 100755 --- a/Packaging/OpenDingux/build.sh +++ b/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 "$@" diff --git a/Packaging/OpenDingux/package-opk.sh b/Packaging/OpenDingux/package-opk.sh index 52c14b30f..16bc604e2 100755 --- a/Packaging/OpenDingux/package-opk.sh +++ b/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 } diff --git a/Packaging/OpenDingux/profile-generate.sh b/Packaging/OpenDingux/profile-generate.sh new file mode 100755 index 000000000..67c63676a --- /dev/null +++ b/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"