diff --git a/AppImageBuilder/assets/citron.desktop b/AppImageBuilder/assets/citron.desktop
index 1822831df0..b42cc1962b 100644
--- a/AppImageBuilder/assets/citron.desktop
+++ b/AppImageBuilder/assets/citron.desktop
@@ -2,5 +2,5 @@
Type=Application
Name=citron
Icon=citron
-Exec=AppRun
+Exec=citron
Categories=Game;
diff --git a/AppImageBuilder/assets/citron.sh b/AppImageBuilder/assets/citron.sh
index 93a6057926..56ee226242 100755
--- a/AppImageBuilder/assets/citron.sh
+++ b/AppImageBuilder/assets/citron.sh
@@ -1,3 +1,24 @@
-#! /bin/sh
+#!/bin/sh
+# citron AppImage wrapper script
-LD_LIBRARY_PATH=/usr/lib/$(uname -m)-linux-gnu:/usr/lib:. exec ./citron "$@"
+# Find the directory where the AppImage is located
+if [ -n "$APPIMAGE" ]; then
+ APPIMAGE_DIR="$(dirname "$APPIMAGE")"
+else
+ # Fallback for non-AppImage execution
+ APPIMAGE_DIR="$(cd "$(dirname "$0")" && pwd)"
+fi
+
+# Set PGO profile output to be next to the AppImage
+# This ensures that instrumented builds write their results where the user expects.
+if [ -z "$LLVM_PROFILE_FILE" ]; then
+ export LLVM_PROFILE_FILE="$APPIMAGE_DIR/default-%p.profraw"
+fi
+
+# We don't 'cd' to APPIMAGE_DIR to avoid breaking relative paths for games,
+# but Citron will find the 'user' folder if it's in the current working directory
+# from which the AppImage was launched.
+
+# Run the real binary
+# $APPDIR is the mount point set by the AppRun loader
+exec "$APPDIR/usr/bin/citron.bin" "$@"
diff --git a/AppImageBuilder/assets/citron.svg b/AppImageBuilder/assets/citron.svg
index 3db81d5d7d..36ee4151d5 100644
--- a/AppImageBuilder/assets/citron.svg
+++ b/AppImageBuilder/assets/citron.svg
@@ -1,8 +1,58 @@
-
-
diff --git a/AppImageBuilder/build-v2.sh b/AppImageBuilder/build-v2.sh
new file mode 100755
index 0000000000..056c36d3bd
--- /dev/null
+++ b/AppImageBuilder/build-v2.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+set -e
+
+# Get script directory
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+BUILD_DIR="${1:-$SCRIPT_DIR/../build/generate}"
+
+# Save environment overrides
+ENV_QT_PATH="${CITRON_QT_PATH:-}"
+ENV_ICU_PATH="${CITRON_ICU_PATH:-}"
+ENV_XCB_PATH="${CITRON_XCB_PATH:-}"
+ENV_BINARY_DIR="${CITRON_BINARY_DIR:-}"
+
+if [ ! -f "$BUILD_DIR/AppImageBuilder/config.sh" ]; then
+ echo "Error: config.sh not found in $BUILD_DIR/AppImageBuilder/"
+ echo "Please run CMake first."
+ exit 1
+fi
+
+source "$BUILD_DIR/AppImageBuilder/config.sh"
+
+# Allow environment variables to override config.sh
+export CITRON_QT_PATH="${ENV_QT_PATH:-$CITRON_QT_PATH}"
+export CITRON_ICU_PATH="${ENV_ICU_PATH:-$CITRON_ICU_PATH}"
+export CITRON_XCB_PATH="${ENV_XCB_PATH:-$CITRON_XCB_PATH}"
+export CITRON_BINARY_DIR="${ENV_BINARY_DIR:-$CITRON_BINARY_DIR}"
+
+# Tools setup
+TOOLS_DIR="$BUILD_DIR/AppImageBuilder/tools"
+mkdir -p "$TOOLS_DIR"
+LINUXDEPLOY="$TOOLS_DIR/linuxdeploy-x86_64.AppImage"
+LINUXDEPLOY_QT="$TOOLS_DIR/linuxdeploy-plugin-qt-x86_64.AppImage"
+
+download_tool() {
+ local url=$1
+ local file=$2
+ if [ ! -f "$file" ]; then
+ echo "Downloading $file..."
+ wget -q --show-progress "$url" -O "$file"
+ chmod +x "$file"
+ fi
+}
+
+download_tool "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" "$LINUXDEPLOY"
+download_tool "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" "$LINUXDEPLOY_QT"
+
+# AppDir setup
+APPDIR="$BUILD_DIR/AppImageBuilder/AppDir"
+rm -rf "$APPDIR"
+mkdir -p "$APPDIR"
+
+# Build the AppImage
+# We need to tell linuxdeploy where our custom libraries are
+export LD_LIBRARY_PATH="$CITRON_ICU_PATH:$CITRON_XCB_PATH/lib:$LD_LIBRARY_PATH"
+export EXTRA_QT_PLUGINS="wayland" # Add any extra plugins needed
+
+# Run linuxdeploy
+# --plugin qt handles Qt dependencies
+export QMAKE="$CITRON_QT_PATH/bin/qmake"
+export QT_ROOT="$CITRON_QT_PATH"
+export LD_LIBRARY_PATH="$CITRON_QT_PATH/lib:$CITRON_ICU_PATH:$CITRON_XCB_PATH/lib:${LD_LIBRARY_PATH:-}"
+
+pushd "$BUILD_DIR" > /dev/null
+# Run linuxdeploy to populate AppDir
+$LINUXDEPLOY --appdir "$APPDIR" \
+ --executable "$CITRON_BINARY_DIR/citron" \
+ --desktop-file "$SCRIPT_DIR/assets/citron.desktop" \
+ --icon-file "$SCRIPT_DIR/assets/citron.svg" \
+ --library "$CITRON_ICU_PATH/libicuuc.so.73" \
+ --library "$CITRON_ICU_PATH/libicui18n.so.73" \
+ --library "$CITRON_ICU_PATH/libicudata.so.73" \
+ --library "$CITRON_XCB_PATH/lib/libxcb.so.1" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-cursor.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-xkb.so.1" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-render.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-render-util.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-shape.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-shm.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-sync.so.1" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-xfixes.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-randr.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-image.so.0" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-keysyms.so.1" \
+ --library "$CITRON_XCB_PATH/lib/libxcb-icccm.so.4" \
+ --library "$CITRON_XCB_PATH/lib/libXau.so.6" \
+ --library "$CITRON_XCB_PATH/lib/libXdmcp.so.6" \
+ --plugin qt
+
+# Inject the wrapper script to support portable mode (user folder) and PGO profiles
+# We rename the real binary to citron.bin and put the script as 'citron'
+if [ -f "$APPDIR/usr/bin/citron" ]; then
+ mv "$APPDIR/usr/bin/citron" "$APPDIR/usr/bin/citron.bin"
+ cp "$SCRIPT_DIR/assets/citron.sh" "$APPDIR/usr/bin/citron"
+ chmod +x "$APPDIR/usr/bin/citron"
+fi
+
+# Build the final AppImage
+$LINUXDEPLOY --appdir "$APPDIR" --output appimage
+
+popd > /dev/null
+
+echo "AppImage build complete in $BUILD_DIR"
diff --git a/AppImageBuilder/config.sh.in b/AppImageBuilder/config.sh.in
new file mode 100644
index 0000000000..971e02fd51
--- /dev/null
+++ b/AppImageBuilder/config.sh.in
@@ -0,0 +1,6 @@
+# Build configuration for AppImageBuilder
+export CITRON_QT_PATH="@QT_TARGET_PATH@"
+export CITRON_ICU_PATH="@ICU_BINARY_DIR@"
+export CITRON_XCB_PATH="@XCB_BUILD_ROOT@"
+export CITRON_BINARY_DIR="@CMAKE_BINARY_DIR@/bin"
+export ARCH="@CMAKE_SYSTEM_PROCESSOR@"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c91897ec1..43ff27599d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -582,23 +582,23 @@ if (ENABLE_QT AND NOT CITRON_USE_CPM)
# Try to find Qt6 installation path (aqtinstall layout: externals/qt//)
# We prioritize llvm-mingw_64 for Clang builds to ensure libc++ compatibility.
if (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/llvm-mingw_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/llvm-mingw_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/llvm-mingw_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/mingw_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/mingw_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/mingw_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_arm64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_arm64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2022_arm64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2019_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2019_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.9.3/msvc2019_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/llvm-mingw_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/llvm-mingw_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/llvm-mingw_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2022_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2022_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2022_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2019_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2019_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.8.3/msvc2019_64" CACHE PATH "Path to Qt6" FORCE)
elseif (EXISTS "${CMAKE_BINARY_DIR}/externals/qt/6.7.3/msvc2019_64")
- set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.7.3/msvc2019_64")
+ set(QT_TARGET_PATH "${CMAKE_BINARY_DIR}/externals/qt/6.7.3/msvc2019_64" CACHE PATH "Path to Qt6" FORCE)
endif()
endif()
@@ -626,18 +626,12 @@ if (ENABLE_QT AND NOT CITRON_USE_CPM)
endif()
# Fallback detection if QT_TARGET_PATH was not found in common bundled locations
- if (NOT QT_TARGET_PATH)
- get_target_property(qtcore_path Qt6::Core LOCATION_Release)
- if (qtcore_path)
- string(FIND "${qtcore_path}" "/bin/" qtcore_path_bin_pos REVERSE)
- string(FIND "${qtcore_path}" "/lib/" qtcore_path_lib_pos REVERSE)
- if (qtcore_path_bin_pos GREATER qtcore_path_lib_pos)
- string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_bin_pos} QT_TARGET_PATH)
- else()
- string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_lib_pos} QT_TARGET_PATH)
- endif()
- endif()
+ if (NOT QT_TARGET_PATH AND Qt6_DIR)
+ get_filename_component(_tmp_path "${Qt6_DIR}/../../.." ABSOLUTE)
+ set(QT_TARGET_PATH "${_tmp_path}" CACHE PATH "Path to Qt6" FORCE)
+ message(STATUS "Resolved QT_TARGET_PATH from Qt6_DIR: ${QT_TARGET_PATH}")
endif()
+ message(STATUS "Final QT_TARGET_PATH: ${QT_TARGET_PATH}")
endif()
function(set_citron_qt_components)
@@ -974,3 +968,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CITRON_ENABLE_LTO)
endif()
endforeach()
endif()
+# Generate AppImage build configuration
+if (UNIX AND NOT APPLE)
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/AppImageBuilder/config.sh.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/AppImageBuilder/config.sh"
+ @ONLY
+ )
+endif()
diff --git a/CMakeModules/FixLinuxBundleRpaths.cmake b/CMakeModules/FixLinuxBundleRpaths.cmake
deleted file mode 100644
index ca87a917a6..0000000000
--- a/CMakeModules/FixLinuxBundleRpaths.cmake
+++ /dev/null
@@ -1,152 +0,0 @@
-# SPDX-FileCopyrightText: 2026 citron Emulator Project
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-if (NOT DEFINED BUNDLE_BIN_DIR)
- message(FATAL_ERROR "BUNDLE_BIN_DIR is required")
-endif()
-if (NOT DEFINED PATCHELF_EXE OR NOT EXISTS "${PATCHELF_EXE}")
- message(FATAL_ERROR "patchelf is required to make the Linux bundle portable")
-endif()
-
-set(_bin_dir "${BUNDLE_BIN_DIR}")
-set(_lib_dir "${_bin_dir}/lib")
-set(_plugins_dir "${_bin_dir}/plugins")
-file(MAKE_DIRECTORY "${_lib_dir}")
-
-if (DEFINED RUNTIME_DEPENDENCY_DIRS)
- string(REPLACE "|" ";" _runtime_dependency_dirs "${RUNTIME_DEPENDENCY_DIRS}")
-endif()
-list(APPEND _runtime_dependency_dirs "${_lib_dir}")
-list(REMOVE_DUPLICATES _runtime_dependency_dirs)
-
-foreach(_candidate citron citron-cmd citron-room shader_tool)
- if (EXISTS "${_bin_dir}/${_candidate}")
- list(APPEND _executables "${_bin_dir}/${_candidate}")
- endif()
-endforeach()
-
-file(GLOB _bundled_libraries "${_lib_dir}/*.so" "${_lib_dir}/*.so.*")
-if (EXISTS "${_plugins_dir}")
- file(GLOB_RECURSE _bundled_modules "${_plugins_dir}/*.so")
-endif()
-
-if (_executables OR _bundled_libraries OR _bundled_modules)
- file(GET_RUNTIME_DEPENDENCIES
- RESOLVED_DEPENDENCIES_VAR _resolved_dependencies
- UNRESOLVED_DEPENDENCIES_VAR _unresolved_dependencies
- CONFLICTING_DEPENDENCIES_PREFIX _conflicting
- EXECUTABLES ${_executables}
- LIBRARIES ${_bundled_libraries}
- MODULES ${_bundled_modules}
- DIRECTORIES ${_runtime_dependency_dirs}
- PRE_EXCLUDE_REGEXES
- [[^libgcc_s\.so\..*]]
- [[^libstdc\+\+\.so\..*]]
- [[^libglapi\.so\..*]]
- [[^libGL\.so\..*]]
- [[^libEGL\.so\..*]]
- [[^libvulkan\.so\..*]]
- [[^libXau\.so\..*]]
- [[^libXdmcp\.so\..*]]
- [[^libxcb\.so\..*]]
- POST_EXCLUDE_REGEXES
- [[/ld-linux[^/]*\.so(\..*)?$]]
- [[/libc\.so(\..*)?$]]
- [[/libm\.so(\..*)?$]]
- [[/libdl\.so(\..*)?$]]
- [[/libpthread\.so(\..*)?$]]
- [[/librt\.so(\..*)?$]]
- [[/libresolv\.so(\..*)?$]]
- [[/libutil\.so(\..*)?$]]
- [[/libnss_[^/]*\.so(\..*)?$]]
- [[/libanl\.so(\..*)?$]]
- [[/libgcc_s\.so(\..*)?$]]
- [[/libstdc\+\+\.so(\..*)?$]]
- )
-endif()
-
-foreach(_dependency ${_resolved_dependencies})
- get_filename_component(_dependency_name "${_dependency}" NAME)
- if (NOT EXISTS "${_lib_dir}/${_dependency_name}")
- file(COPY "${_dependency}" DESTINATION "${_lib_dir}" FOLLOW_SYMLINK_CHAIN)
- endif()
-endforeach()
-
-if (_unresolved_dependencies)
- list(REMOVE_DUPLICATES _unresolved_dependencies)
- message(WARNING "Unresolved Linux bundle dependencies: ${_unresolved_dependencies}")
-endif()
-
-function(_citron_is_elf output_var file_path)
- execute_process(
- COMMAND readelf -h "${file_path}"
- RESULT_VARIABLE _readelf_result
- OUTPUT_QUIET
- ERROR_QUIET
- )
- if (_readelf_result EQUAL 0)
- set(${output_var} TRUE PARENT_SCOPE)
- else()
- set(${output_var} FALSE PARENT_SCOPE)
- endif()
-endfunction()
-
-function(_citron_set_rpath file_path rpath)
- _citron_is_elf(_is_elf "${file_path}")
- if (NOT _is_elf)
- return()
- endif()
-
- execute_process(
- COMMAND "${PATCHELF_EXE}" --force-rpath --set-rpath "${rpath}" "${file_path}"
- RESULT_VARIABLE _patchelf_result
- OUTPUT_VARIABLE _patchelf_stdout
- ERROR_VARIABLE _patchelf_stderr
- )
- if (NOT _patchelf_result EQUAL 0)
- message(FATAL_ERROR
- "Failed to set RPATH on ${file_path}\n"
- "${_patchelf_stdout}\n${_patchelf_stderr}")
- endif()
-endfunction()
-
-foreach(_executable ${_executables})
- _citron_set_rpath("${_executable}" "$ORIGIN/lib")
-endforeach()
-
-file(GLOB _final_libraries "${_lib_dir}/*.so" "${_lib_dir}/*.so.*")
-foreach(_library ${_final_libraries})
- _citron_set_rpath("${_library}" "$ORIGIN")
-endforeach()
-
-if (EXISTS "${_plugins_dir}")
- file(GLOB_RECURSE _final_modules "${_plugins_dir}/*.so")
- foreach(_module ${_final_modules})
- _citron_set_rpath("${_module}" "$ORIGIN/../../lib")
- endforeach()
-endif()
-
-set(_rpath_failures)
-foreach(_file ${_executables} ${_final_libraries} ${_final_modules})
- _citron_is_elf(_is_elf "${_file}")
- if (NOT _is_elf)
- continue()
- endif()
-
- execute_process(
- COMMAND readelf -d "${_file}"
- OUTPUT_VARIABLE _dynamic_section
- ERROR_QUIET
- )
- if (_dynamic_section MATCHES "(RPATH|RUNPATH)[^\n]*\\[/" OR
- _dynamic_section MATCHES "(RPATH|RUNPATH)[^\n]*:/")
- list(APPEND _rpath_failures "${_file}")
- endif()
-endforeach()
-
-if (_rpath_failures)
- list(REMOVE_DUPLICATES _rpath_failures)
- message(FATAL_ERROR "Absolute RPATH/RUNPATH remains in Linux bundle: ${_rpath_failures}")
-endif()
-
-message(STATUS "Linux bundle dependencies copied and RPATHs normalized in ${_bin_dir}")
diff --git a/CMakeModules/dependencies.cmake b/CMakeModules/dependencies.cmake
index c4a94f1e32..27b286b427 100644
--- a/CMakeModules/dependencies.cmake
+++ b/CMakeModules/dependencies.cmake
@@ -591,6 +591,7 @@ set(CITRON_ICU_TAG "release-73-2" CACHE STRING "ICU git tag/version")
set(CITRON_XCB_MACROS_VER "1.20.2" CACHE STRING "XCB util-macros version")
set(CITRON_XCB_PROTO_VER "1.17.0" CACHE STRING "XCB proto version")
set(CITRON_XCB_XAU_VER "1.0.11" CACHE STRING "XCB libXau version")
+set(CITRON_XCB_XDMCP_VER "1.1.5" CACHE STRING "XCB libXdmcp version")
set(CITRON_XCB_LIBXCB_VER "1.16" CACHE STRING "XCB libxcb version")
set(CITRON_XCB_UTIL_VER "0.4.1" CACHE STRING "XCB util version")
set(CITRON_XCB_CURSOR_VER "0.1.6" CACHE STRING "XCB cursor version")
diff --git a/CMakeModules/qt_download.cmake b/CMakeModules/qt_download.cmake
index d072f88f41..81e4fae1bd 100644
--- a/CMakeModules/qt_download.cmake
+++ b/CMakeModules/qt_download.cmake
@@ -70,6 +70,10 @@ endif()
# ── Download target Qt ────────────────────────────────────────────────────────
if (Qt6_DIR AND EXISTS "${Qt6_DIR}/Qt6Config.cmake")
message(STATUS "[Qt] Using target Qt from Qt6_DIR: ${Qt6_DIR}")
+ if (NOT QT_TARGET_PATH)
+ get_filename_component(_tmp_path "${Qt6_DIR}/../../.." ABSOLUTE)
+ set(QT_TARGET_PATH "${_tmp_path}" CACHE PATH "Path to Qt6 target root" FORCE)
+ endif()
else()
set(_QT_TARGET_DIR "${CITRON_QT_BASE_DIR}/${CITRON_QT_VERSION}/${_QT_DIR_NAME}")
set(_QT_TARGET_CMAKE "${_QT_TARGET_DIR}/${_QT_CMAKE_SUB}/Qt6Config.cmake")
@@ -118,7 +122,9 @@ else()
if (EXISTS "${_QT_TARGET_CMAKE}")
get_filename_component(_qt6_dir "${_QT_TARGET_CMAKE}" DIRECTORY)
set(Qt6_DIR "${_qt6_dir}" CACHE PATH "Path to Qt6Config.cmake (from aqt)" FORCE)
+ set(QT_TARGET_PATH "${_QT_TARGET_DIR}" CACHE PATH "Path to Qt6 target root" FORCE)
message(STATUS "[Qt] Qt6_DIR = ${Qt6_DIR}")
+ message(STATUS "[Qt] QT_TARGET_PATH = ${QT_TARGET_PATH}")
endif()
endif()
diff --git a/CMakeModules/xcb_build.cmake b/CMakeModules/xcb_build.cmake
index c9d667f942..26099e1356 100644
--- a/CMakeModules/xcb_build.cmake
+++ b/CMakeModules/xcb_build.cmake
@@ -10,7 +10,7 @@ endif()
# We need a list of components to fetch and build.
# 'macros' and 'proto' must come first as others depend on them.
-set(_xcb_components macros proto xau libxcb util image keysyms renderutil wm cursor)
+set(_xcb_components macros proto xau xdmcp libxcb util image keysyms renderutil wm cursor)
set(XCB_BUILD_ROOT "${CMAKE_BINARY_DIR}/externals/xcb-build")
file(MAKE_DIRECTORY "${XCB_BUILD_ROOT}")
@@ -21,6 +21,7 @@ set(XCB_BINARY_DIR "${XCB_BUILD_ROOT}/lib" CACHE INTERNAL "Location of CPM-built
set(_xcb_macros_ver "${CITRON_XCB_MACROS_VER}")
set(_xcb_proto_ver "${CITRON_XCB_PROTO_VER}")
set(_xcb_xau_ver "${CITRON_XCB_XAU_VER}")
+set(_xcb_xdmcp_ver "${CITRON_XCB_XDMCP_VER}")
set(_xcb_libxcb_ver "${CITRON_XCB_LIBXCB_VER}")
set(_xcb_cursor_ver "${CITRON_XCB_CURSOR_VER}")
set(_xcb_util_ver "${CITRON_XCB_UTIL_VER}")
@@ -38,6 +39,9 @@ foreach(_comp ${_xcb_components})
elseif(_comp STREQUAL "xau")
set(_url "https://xorg.freedesktop.org/archive/individual/lib/libXau-${_xcb_xau_ver}.tar.xz")
set(_name "libXau")
+ elseif(_comp STREQUAL "xdmcp")
+ set(_url "https://xorg.freedesktop.org/archive/individual/lib/libXdmcp-${_xcb_xdmcp_ver}.tar.xz")
+ set(_name "libXdmcp")
elseif(_comp STREQUAL "libxcb")
set(_url "https://xcb.freedesktop.org/dist/libxcb-${_xcb_libxcb_ver}.tar.xz")
set(_name "libxcb")
diff --git a/build-citron-linux.sh b/build-citron-linux.sh
index 835348b0c2..0a50ff0a70 100755
--- a/build-citron-linux.sh
+++ b/build-citron-linux.sh
@@ -26,7 +26,7 @@
# - The LTO linker backend receives -fprofile-use for LTCG with profile data
# - Profile runtime symbols are force-kept on the linker command line
#
-# LTO + PGO LINKER FLAGS (use/csgenerate/bolt/propeller stages):
+# LTO + PGO LINKER FLAGS (use/csgenerate/bolt stages):
# For full LTO (-flto), the -fprofile-use flag must appear on
# CMAKE_EXE_LINKER_FLAGS as well as the compile flags, so the LTO backend
# applies the profile during link-time code generation.
@@ -47,8 +47,7 @@
# merge Merge collected .profraw files into .profdata.
# summary Show profile statistics.
# use Stage 2: PGO + LTO optimized build (or baseline if --pgo none).
-# bolt Stage 3A: BOLT binary layout optimization.
-# propeller Stage 3B: Propeller BB+function layout (requires perf + LBR).
+# bolt Stage 3: BOLT binary layout optimization.
# clean Remove build directories (profile data preserved).
#
# USAGE:
@@ -107,12 +106,6 @@
# # BOLT pauses — run instrumented binary, exit, press Enter.
# # Binary: ./build/bolt/citron
#
-# IR PGO + Propeller (requires perf + LBR-capable CPU):
-# (after completing 'use' above)
-# ./build-citron-linux.sh propeller --pgo ir --lto full
-# # Propeller pauses — run perf command shown, exit, press Enter.
-# # Binary: ./build/propeller/bin/citron
-#
# DEPENDENCIES MANAGED BY CMAKE (not this script):
# All C++ library dependencies are fetched from source by CPM at cmake
# configure time. No system library packages are required.
@@ -130,7 +123,6 @@
# autoconf + automake + make FFmpeg autotools build
# glslang (glslc) Vulkan shader compilation
# patchelf bundle RPATH normalization
-# perf propeller stage only
# =============================================================================
set -euo pipefail
@@ -167,10 +159,8 @@ _set_derived_paths() {
BUILD_CSGENERATE="${BUILD_ROOT}/cs-generate"
BUILD_USE="${BUILD_ROOT}/use"
BUILD_BOLT="${BUILD_ROOT}/bolt"
- BUILD_PROPELLER="${BUILD_ROOT}/propeller"
PROFILE_DIR="${BUILD_ROOT}/pgo-profiles"
BOLT_PROFILE_DIR="${BUILD_ROOT}/bolt-profiles"
- PROPELLER_PROFILE_DIR="${BUILD_ROOT}/propeller-profiles"
}
_set_derived_paths
@@ -191,14 +181,14 @@ _set_clang_tools
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
-info() { echo -e "${CYAN}[INFO]${RESET} $*"; }
-success() { echo -e "${GREEN}[OK]${RESET} $*"; }
-warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; }
+info() { echo -e "${CYAN}[INFO]${RESET} $*" >&2; }
+success() { echo -e "${GREEN}[OK]${RESET} $*" >&2; }
+warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
error() { echo -e "${RED}[ERROR]${RESET} $*" >&2; exit 1; }
header() {
- echo -e "\n${BOLD}${GREEN}=================================================================${RESET}"
- echo -e "${BOLD}${GREEN} $*${RESET}"
- echo -e "${BOLD}${GREEN}=================================================================${RESET}"
+ echo -e "\n${BOLD}${GREEN}=================================================================${RESET}" >&2
+ echo -e "${BOLD}${GREEN} $*${RESET}" >&2
+ echo -e "${BOLD}${GREEN}=================================================================${RESET}" >&2
}
# =============================================================================
@@ -590,6 +580,31 @@ normalize_profraw_dirs() {
done < <(find "${base_dir}" -maxdepth 1 -type d -name '*.profraw' -print0)
}
+_collect_appimage_profiles() {
+ # Profiles generated by running the AppImage are written next to the AppImage file
+ # by the citron.sh wrapper. We collect them back to the main profile directory
+ # so they can be merged and used by the build script.
+
+ # Standard PGO profiles
+ if [[ -d "${BUILD_GENERATE}/AppImage" ]]; then
+ local count; count="$(find "${BUILD_GENERATE}/AppImage" -maxdepth 1 -name "*.profraw" 2>/dev/null | wc -l)"
+ if [[ "${count}" -gt 0 ]]; then
+ info "Collecting ${count} profile(s) from ${BUILD_GENERATE}/AppImage..."
+ mv "${BUILD_GENERATE}/AppImage"/*.profraw "${PROFILE_DIR}/" 2>/dev/null || true
+ fi
+ fi
+
+ # CS-PGO profiles
+ if [[ -d "${BUILD_CSGENERATE}/AppImage" ]]; then
+ local count; count="$(find "${BUILD_CSGENERATE}/AppImage" -maxdepth 1 -name "*.profraw" 2>/dev/null | wc -l)"
+ if [[ "${count}" -gt 0 ]]; then
+ info "Collecting ${count} CS profile(s) from ${BUILD_CSGENERATE}/AppImage..."
+ mkdir -p "${PROFILE_DIR}/cs"
+ mv "${BUILD_CSGENERATE}/AppImage"/*.profraw "${PROFILE_DIR}/cs/" 2>/dev/null || true
+ fi
+ fi
+}
+
_merge_profraw_to_profdata() {
local profile_dir="$1"; local output_file="$2"
normalize_profraw_dirs "${profile_dir}"
@@ -604,6 +619,7 @@ _merge_profraw_to_profdata() {
}
resolve_use_profdata() {
+ _collect_appimage_profiles
# Determine which profdata to hand to the use stage.
# Preference order: merged.profdata (stage1+CS) > default.profdata (stage1) > merge from profraw.
local merged="${PROFILE_DIR}/merged.profdata"
@@ -783,6 +799,33 @@ _build_with_flags() {
cmake --build . --config "${BUILD_TYPE}" -j "${JOBS}"
}
+# =============================================================================
+# AppImage building
+# =============================================================================
+
+build_appimage_stage() {
+ local build_dir="$1"
+ local stage_name="$2"
+ local binary_override="${3:-}"
+ header "Building AppImage for ${stage_name}"
+
+ if [[ -n "${binary_override}" ]]; then
+ # Override CITRON_BINARY_DIR so build-v2.sh finds the correct binary
+ export CITRON_BINARY_DIR="$(dirname "${binary_override}")"
+ else
+ unset CITRON_BINARY_DIR
+ fi
+
+ # Run the AppImage build script
+ bash "${SCRIPT_DIR}/AppImageBuilder/build-v2.sh" "${build_dir}"
+
+ # Create the output directory and move the AppImage
+ mkdir -p "${build_dir}/AppImage/user"
+ mv "${build_dir}/citron-x86_64.AppImage" "${build_dir}/AppImage/"
+
+ success "AppImage for ${stage_name} placed in ${build_dir}/AppImage/citron-x86_64.AppImage"
+}
+
# =============================================================================
# Stage: generate
# =============================================================================
@@ -829,6 +872,7 @@ stage_generate() {
write_gen_sentinel
mkdir -p "${BUILD_GENERATE}/bin/user"
success "Instrumented build: ${BUILD_GENERATE}/bin/citron"
+ build_appimage_stage "${BUILD_GENERATE}" "generate"
print_profiling_instructions "${BUILD_GENERATE}/bin/citron"
}
@@ -902,6 +946,7 @@ stage_csgenerate() {
mkdir -p "${BUILD_CSGENERATE}/bin/user"
success "CS-IRPGO instrumented build: ${BUILD_CSGENERATE}/bin/citron"
+ build_appimage_stage "${BUILD_CSGENERATE}" "csgenerate"
echo ""
echo -e "${YELLOW}════════════════════════════════════════════════════════════════${RESET}"
echo -e "${YELLOW} NEXT STEP: Collect CS Profile Data (Session 2)${RESET}"
@@ -925,6 +970,7 @@ stage_csgenerate() {
stage_merge() {
header "Merging PGO Profiles"
+ _collect_appimage_profiles
[[ -d "${PROFILE_DIR}" ]] || error "Profile directory not found: ${PROFILE_DIR}"
_merge_profraw_to_profdata "${PROFILE_DIR}" "${PROFILE_DIR}/default.profdata"
find "${PROFILE_DIR}" -maxdepth 1 -name "*.profraw" -delete
@@ -972,6 +1018,7 @@ stage_use() {
_build_with_flags "${BUILD_ROOT}/use-nopgo" nopgo
mkdir -p "${BUILD_ROOT}/use-nopgo/bin/user"
success "Baseline build: ${BUILD_ROOT}/use-nopgo/bin/citron"
+ build_appimage_stage "${BUILD_ROOT}/use-nopgo" "use-nopgo"
return 0
fi
@@ -1017,10 +1064,10 @@ stage_use() {
success " PGO: ${pgo_label}"
success " LTO: ${LTO_MODE}${LTO_MODE:+ ($(lto_clang_flag))}"
success "════════════════════════════════════════════════════════════════"
+ build_appimage_stage "${BUILD_USE}" "use"
echo ""
info "Next steps (optional):"
echo " BOLT: ./build-citron-linux.sh bolt --pgo ${PGO_MODE} --lto ${LTO_MODE}"
- echo " Propeller: ./build-citron-linux.sh propeller --pgo ${PGO_MODE} --lto ${LTO_MODE}"
if [[ "${profdata}" != "${PROFILE_DIR}/merged.profdata" && "${PGO_MODE}" == "ir" ]]; then
echo ""
echo " CS-IRPGO (add a second profiling layer):"
@@ -1137,20 +1184,32 @@ stage_bolt() {
local fdata_pattern="${BOLT_PROFILE_DIR}/citron-%p.fdata"
local merged_fdata="${BOLT_PROFILE_DIR}/citron-merged.fdata"
+ local skipped_funcs="RC4_options"
+
info "Instrumenting ELF with BOLT..."
"${LLVM_BOLT}" "${elf_binary}" \
--instrument \
+ --skip-funcs="${skipped_funcs}" \
--instrumentation-file="${fdata_pattern}" \
--instrumentation-file-append-pid \
-o "${instrumented}"
success "Instrumented: ${instrumented}"
+ # Load custom library paths from config.sh for the run instructions
+ local lp_env=""
+ local config_file="${relocs_dir}/AppImageBuilder/config.sh"
+ if [[ -f "${config_file}" ]]; then
+ # Use a subshell to avoid polluting our current environment
+ lp_env="$( (source "${config_file}"; echo "LD_LIBRARY_PATH=\"${CITRON_QT_PATH}/lib:${CITRON_ICU_PATH}:${CITRON_XCB_PATH}/lib\" ") )"
+ fi
+
echo ""
echo -e "${YELLOW}════════════════════════════════════════════════════════════════${RESET}"
echo -e "${YELLOW} Run the BOLT-instrumented binary${RESET}"
echo -e "${YELLOW}════════════════════════════════════════════════════════════════${RESET}"
echo ""
- echo " ${instrumented}"
+ echo " Run the instrumented binary with custom library paths:"
+ echo " ${lp_env}${instrumented}"
echo ""
echo " Play for 15-30 min. Exit cleanly."
echo " fdata files will appear in: ${BOLT_PROFILE_DIR}/"
@@ -1170,6 +1229,7 @@ stage_bolt() {
info "Optimizing ELF with BOLT..."
"${LLVM_BOLT}" "${elf_binary}" \
-p "${merged_fdata}" \
+ --skip-funcs="${skipped_funcs}" \
--reorder-blocks=ext-tsp \
--reorder-functions=cdsort \
--split-functions \
@@ -1186,178 +1246,10 @@ stage_bolt() {
success " Binary: ${BUILD_BOLT}/bin/citron"
success " Optimizations: PGO + LTO + BOLT basic-block reordering"
success "════════════════════════════════════════════════════════════════"
+ build_appimage_stage "${relocs_dir}" "bolt" "${BUILD_BOLT}/bin/citron"
echo ""
}
-# =============================================================================
-# Propeller helpers
-# =============================================================================
-
-_ensure_create_llvm_prof() {
- local ver_sentinel="/usr/local/bin/.create_llvm_prof_ver"
- local clang_ver; clang_ver="$("${CLANG}" --version 2>&1 | head -1 || echo unknown)"
-
- if command -v create_llvm_prof &>/dev/null; then
- local stored=""; [[ -f "${ver_sentinel}" ]] && stored="$(cat "${ver_sentinel}")"
- if [[ "${clang_ver}" == "${stored}" ]]; then
- success "create_llvm_prof available"; return 0
- fi
- warn "create_llvm_prof version mismatch — rebuilding."
- sudo rm -f /usr/local/bin/create_llvm_prof "${ver_sentinel}"
- fi
-
- header "Building create_llvm_prof (google/llvm-propeller)"
- local pkg_mgr; pkg_mgr="$(detect_pkg_manager)"
- case "${pkg_mgr}" in
- apt) sudo apt-get install -y libelf-dev libssl-dev libzstd-dev 2>/dev/null || true ;;
- pacman) sudo pacman -S --needed --noconfirm elfutils openssl zstd 2>/dev/null || true ;;
- dnf) sudo dnf install -y elfutils-libelf-devel openssl-devel libzstd-devel 2>/dev/null || true ;;
- zypper) sudo zypper install -y libelf-devel libopenssl-devel libzstd-devel 2>/dev/null || true ;;
- esac
-
- local src="/tmp/propeller-src" bld="/tmp/propeller-build"
- [[ -d "${src}/.git" ]] \
- || git clone --depth=1 https://github.com/google/llvm-propeller.git "${src}"
- rm -rf "${bld}"
- CC="${CLANG}" CXX="${CLANGPP}" \
- cmake -S "${src}" -B "${bld}" -G Ninja -DCMAKE_BUILD_TYPE=Release \
- || error "llvm-propeller cmake configure failed."
- cmake --build "${bld}" --target generate_propeller_profiles -j "${JOBS}" \
- || error "llvm-propeller build failed."
- sudo cp "${bld}/propeller/generate_propeller_profiles" /usr/local/bin/create_llvm_prof
- sudo chmod +x /usr/local/bin/create_llvm_prof
- printf '%s' "${clang_ver}" | sudo tee "${ver_sentinel}" > /dev/null
- success "create_llvm_prof installed."
-}
-
-# =============================================================================
-# Stage: propeller
-# =============================================================================
-
-stage_propeller() {
- header "Stage 3B: Propeller BB+Function Layout Optimization"
- command -v perf &>/dev/null \
- || error "perf not found. Install linux-tools-$(uname -r) and re-run."
- _ensure_create_llvm_prof
-
- # Build a binary with -fbasic-block-address-map for perf profiling.
- # LTO is intentionally OFF: the ThinLTO backend in lld does not propagate
- # -fbasic-block-address-map through the link step, so .llvm_bb_addr_map
- # sections would be absent in the final binary. PGO data alone provides
- # sufficient representative coverage for the Propeller conversion step.
- local bb_dir="${BUILD_ROOT}/use-bb"
- if [[ ! -f "${bb_dir}/bin/citron" ]]; then
- info "Building BB-annotated binary (-fbasic-block-address-map, no LTO)..."
- apply_source_patches
- local bt_upper; bt_upper="$(echo "${BUILD_TYPE}" | tr '[:lower:]' '[:upper:]')"
- local debug_flag=""; [[ "${BUILD_TYPE}" == "RelWithDebInfo" ]] && debug_flag="-g"
- local pgo_part="" pgo_enable="OFF"
- if [[ "${PGO_MODE}" != "none" ]]; then
- check_stage_compatibility
- local profdata; profdata="$(resolve_use_profdata)"
- pgo_part="$(pgo_use_compile_flag "${profdata}")"
- pgo_enable="ON"
- fi
- local bb_cflags="-O3 -DNDEBUG ${debug_flag} -USuccess -UNone ${ARCH_FLAGS:-} -Wno-error -w ${pgo_part} -fbasic-block-address-map"
- local bb_linker="-fuse-ld=${LLD} -Wl,--emit-relocs"
- _build_with_flags "${bb_dir}" use \
- "-DCITRON_ENABLE_PGO_USE=${pgo_enable}" \
- "-DCITRON_ENABLE_PGO_GENERATE=OFF" \
- "-DCITRON_PGO_FLAGS_MANAGED_BY_SCRIPT=ON" \
- "-DCITRON_ENABLE_LTO=OFF" \
- "-DCITRON_PGO_PROFILE_DIR=${PROFILE_DIR}" \
- "-DCMAKE_C_FLAGS_${bt_upper}=${bb_cflags}" \
- "-DCMAKE_CXX_FLAGS_${bt_upper}=${bb_cflags}" \
- "-DCMAKE_EXE_LINKER_FLAGS_${bt_upper}=${bb_linker}"
- success "BB-annotated binary: ${bb_dir}/bin/citron"
- fi
-
- local elf_binary="${bb_dir}/bin/citron"
- mkdir -p "${PROPELLER_PROFILE_DIR}" "${BUILD_PROPELLER}/bin"
- local perf_data="${PROPELLER_PROFILE_DIR}/perf.data"
- local cc_profile="${PROPELLER_PROFILE_DIR}/propeller_cc.prof"
- local symorder="${PROPELLER_PROFILE_DIR}/propeller_symorder.txt"
-
- # Ensure perf can record branch stacks
- local paranoid; paranoid="$(cat /proc/sys/kernel/perf_event_paranoid 2>/dev/null || echo 1)"
- if [[ "${paranoid}" -gt 1 ]]; then
- warn "perf_event_paranoid=${paranoid} — branch stacks require <= 1. Setting now..."
- sudo sysctl -w kernel.perf_event_paranoid=1 \
- || error "Could not set perf_event_paranoid. Run: sudo sysctl kernel.perf_event_paranoid=1"
- fi
-
- if [[ ! -f "${perf_data}" ]]; then
- echo ""
- echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${RESET}"
- echo -e "${YELLOW} Propeller — Branch Profile Collection${RESET}"
- echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${RESET}"
- echo ""
- echo " Run the following to collect a branch-stack profile:"
- echo ""
- echo " perf record -b -e cycles:u \\"
- echo " -o ${perf_data} \\"
- echo " -- ${elf_binary}"
- echo ""
- echo " Play for 15-30 minutes. Exit citron cleanly."
- echo ""
- echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${RESET}"
- read -rp " Press Enter once perf has finished and perf.data is written... "
- echo ""
- [[ -f "${perf_data}" ]] \
- || error "perf.data not found at ${perf_data}. Run the perf command above first."
- fi
-
- info "Converting perf branch data to Propeller profiles..."
- create_llvm_prof \
- --binary="${elf_binary}" \
- --profile="${perf_data}" \
- --cc_profile="${cc_profile}" \
- --ld_profile="${symorder}" \
- 2>&1 || error "generate_propeller_profiles failed — check perf.data and ELF compatibility."
-
- [[ -f "${cc_profile}" ]] && success "CC profile: ${cc_profile} ($(wc -l < "${cc_profile}") entries)"
- [[ -f "${symorder}" ]] && success "LD profile: ${symorder} ($(wc -l < "${symorder}") functions)"
-
- # Final rebuild: PGO + LTO + Propeller
- info "Rebuilding optimized binary with Propeller profiles (PGO + LTO + Propeller)..."
- apply_source_patches
- local bt_upper; bt_upper="$(echo "${BUILD_TYPE}" | tr '[:lower:]' '[:upper:]')"
- local debug_flag=""; [[ "${BUILD_TYPE}" == "RelWithDebInfo" ]] && debug_flag="-g"
- local lto_flag; lto_flag="$(lto_clang_flag)"
- local pgo_part="" pgo_enable="OFF"
- if [[ "${PGO_MODE}" != "none" ]]; then
- check_stage_compatibility
- local profdata; profdata="$(resolve_use_profdata)"
- pgo_part="$(pgo_use_compile_flag "${profdata}")"
- pgo_enable="ON"
- fi
-
- local prop_cflags="-O3 -DNDEBUG ${debug_flag} -USuccess -UNone ${ARCH_FLAGS:-} -Wno-error -w ${lto_flag:+${lto_flag} }${pgo_part}"
- [[ -f "${cc_profile}" ]] && prop_cflags="${prop_cflags} -fbasic-block-sections=list=${cc_profile}"
-
- # -fprofile-use on the linker so LTO backend gets profile guidance
- local prop_linker="-fuse-ld=${LLD} ${debug_flag:+${debug_flag} }${lto_flag:+${lto_flag} }${pgo_part}"
- [[ -f "${symorder}" ]] && prop_linker="${prop_linker} -Wl,--symbol-ordering-file=${symorder}"
-
- _build_with_flags "${BUILD_PROPELLER}" use \
- "-DCITRON_ENABLE_PGO_USE=${pgo_enable}" \
- "-DCITRON_ENABLE_PGO_GENERATE=OFF" \
- "-DCITRON_PGO_FLAGS_MANAGED_BY_SCRIPT=ON" \
- "-DCITRON_ENABLE_LTO=$(lto_cmake_flag)" \
- "-DCITRON_PGO_PROFILE_DIR=${PROFILE_DIR}" \
- "-DCMAKE_C_FLAGS_${bt_upper}=${prop_cflags}" \
- "-DCMAKE_CXX_FLAGS_${bt_upper}=${prop_cflags}" \
- "-DCMAKE_EXE_LINKER_FLAGS_${bt_upper}=${prop_linker}"
-
- echo ""
- success "════════════════════════════════════════════════════════════════"
- success " Stage propeller complete"
- mkdir -p "${BUILD_PROPELLER}/bin/user"
- success " Binary: ${BUILD_PROPELLER}/bin/citron"
- success " Optimizations: PGO + LTO + Propeller BB+function layout"
- success "════════════════════════════════════════════════════════════════"
- echo ""
-}
# =============================================================================
# Stage: clean
@@ -1385,7 +1277,7 @@ STAGE=""
while [[ $# -gt 0 ]]; do
case "$1" in
- setup|generate|csgenerate|merge|summary|use|bolt|propeller|clean)
+ setup|generate|csgenerate|merge|summary|use|bolt|clean)
STAGE="$1"; shift ;;
--build)
BUILD_ROOT="$2"; _set_derived_paths; shift 2 ;;
@@ -1421,7 +1313,7 @@ while [[ $# -gt 0 ]]; do
done
[[ -n "${STAGE}" ]] \
- || error "No stage specified.\nUsage: $0 [options]\nStages: setup generate csgenerate merge summary use bolt propeller clean"
+ || error "No stage specified.\nUsage: $0 [options]\nStages: setup generate csgenerate merge summary use bolt clean"
resolve_arch_flags
@@ -1433,6 +1325,5 @@ case "${STAGE}" in
summary) stage_summary ;;
use) stage_use ;;
bolt) stage_bolt ;;
- propeller) stage_propeller ;;
clean) stage_clean ;;
esac
diff --git a/src/citron/CMakeLists.txt b/src/citron/CMakeLists.txt
index f1c91db39a..569365e181 100644
--- a/src/citron/CMakeLists.txt
+++ b/src/citron/CMakeLists.txt
@@ -11,18 +11,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set_property(GLOBAL PROPERTY JOB_POOLS link_pool=1)
set(CMAKE_JOB_POOL_LINK link_pool)
-# Set the RPATH for Qt Libraries
-# This must be done before the `citron` target is created
-if (CITRON_USE_BUNDLED_QT AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
- # Use relative RPATH so the binary finds libraries in the 'lib' subfolder.
- # $ORIGIN refers to the directory containing the executable.
- # We use --disable-new-dtags to force RPATH instead of RUNPATH,
- # ensuring recursive dependency resolution for bundled libraries.
- set(CMAKE_BUILD_RPATH "$ORIGIN/lib/")
- set(CMAKE_INSTALL_RPATH "$ORIGIN/lib/")
- add_link_options("-Wl,--disable-new-dtags")
-endif()
-
+# citron target creation
add_executable(citron
Info.plist
about_dialog.cpp
@@ -656,14 +645,8 @@ if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6)
)
endif()
-if (CITRON_USE_BUNDLED_QT)
+if (WIN32 AND CITRON_USE_BUNDLED_QT)
include(CopyCitronQt6Deps)
- if (TARGET icu-build)
- add_dependencies(citron icu-build)
- endif()
- if (CITRON_XCB_TARGETS)
- add_dependencies(citron ${CITRON_XCB_TARGETS})
- endif()
copy_citron_Qt6_deps(citron)
endif()