CPack/AppImage: Add CPACK_APPIMAGE_APPRUN_FILE and ignore directories

Installing a custom AppRun to the AppDir top level depends on
CPACK_PACKAGING_INSTALL_PREFIX, so add a variable to provide it instead.

Also skip directories when looking up the desktop file's Exec and Icon,
as they could match a directory with the same name.

Issue: #27478
This commit is contained in:
Daniel Nicoletti committed 2026-10-30 17:34:00 -03:00
1 parent 8e91f7aa9b
commit d9f1f4c346
15 files changed
+250 -5

No files matched your search

+16 -3
View File
@@ -41,9 +41,12 @@ application links to and copy them to the install location.
]])
The CPack AppImage generator will generate a default `AppRun`_ based on the
provided ``.desktop`` entry. Alternatively, if a custom ``AppRun`` is
installed, e.g., via the :command:`install` command, it will be used instead
of the generated one.
provided ``.desktop`` entry. Alternatively, a custom ``AppRun`` can be
provided by setting :variable:`CPACK_APPIMAGE_APPRUN_FILE`, or by installing
it to the top level of the AppDir, e.g., via the :command:`install` command.
In both cases it will be used instead of the generated one. The variable
is preferred because it does not depend on
:variable:`CPACK_PACKAGING_INSTALL_PREFIX`.
.. _`AppRun`: https://docs.appimage.org/introduction/software-overview.html#apprun
@@ -85,6 +88,16 @@ Variables Specific to CPack AppImage Generator
:Default: Unset
.. variable:: CPACK_APPIMAGE_APPRUN_FILE
.. versionadded:: 4.6
Absolute path to a custom ``AppRun`` file. The file is copied to the top
level of the AppDir and made executable, taking precedence over both the
generated ``AppRun`` and an ``AppRun`` installed by the project.
:Default: Unset
.. variable:: CPACK_APPIMAGE_UPDATE_INFORMATION
Embed the value of this variable as the update information. See the
@@ -0,0 +1,6 @@
cpack-appimage-apprun-file
--------------------------
* The :cpack_gen:`CPack AppImage Generator` gained the
:variable:`CPACK_APPIMAGE_APPRUN_FILE` option to provide a custom
``AppRun`` file.
+30 -2
View File
@@ -184,7 +184,32 @@ int cmCPackAppImageGenerator::PackageFiles()
}
std::string const appRunFile = this->toplevel + "/AppRun";
if (cmSystemTools::PathExists(appRunFile)) {
if (cmValue const customAppRun =
this->GetOption("CPACK_APPIMAGE_APPRUN_FILE")) {
// User provided an AppRun file outside of the installed tree
if (!cmSystemTools::FileExists(*customAppRun, true)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_APPIMAGE_APPRUN_FILE does not point to a file: \""
<< *customAppRun << '"' << std::endl);
return 0;
}
if (cmSystemTools::PathExists(appRunFile)) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_APPIMAGE_APPRUN_FILE overrides the installed "
"AppRun file: \""
<< appRunFile << '"' << std::endl);
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
cmStrCat("Using AppRun file: \"", *customAppRun, '"')
<< std::endl);
auto status = cmSystemTools::CopyFileAlways(*customAppRun, appRunFile);
if (!status.IsSuccess()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error copying AppRun file: " << status.GetString()
<< std::endl);
return 0;
}
} else if (cmSystemTools::PathExists(appRunFile)) {
// User provided an AppRun file
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
cmStrCat("Found AppRun file: \"", appRunFile, '"')
@@ -312,7 +337,10 @@ cm::optional<std::string> cmCPackAppImageGenerator::FindFile(
std::string const& filename) const
{
for (std::string const& file : this->files) {
if (cmSystemTools::GetFilenameName(file) == filename) {
// The list of files also contains directories, which could share the
// name we are looking for (e.g. "include/app" and "bin/app")
if (cmSystemTools::GetFilenameName(file) == filename &&
!cmSystemTools::FileIsDirectory(file)) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found file:" << file << std::endl);
return file;
}
@@ -0,0 +1,13 @@
if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/GeneratorTest-1.2.3-Linux.AppImage")
set(RunCMake_TEST_FAILED "AppImage package not generated")
return()
endif()
set(appRun "${RunCMake_TEST_BINARY_DIR}/_CPack_Packages/Linux/AppImage/GeneratorTest-1.2.3-Linux/AppRun")
file(READ "${appRun}" actual)
file(READ "${RunCMake_SOURCE_DIR}/../RunCPack/AppImageUsrPrefix/AppRun" expected)
if(NOT actual STREQUAL expected)
set(RunCMake_TEST_FAILED "AppRun does not match CPACK_APPIMAGE_APPRUN_FILE:\n${actual}")
elseif(NOT IS_EXECUTABLE "${appRun}")
set(RunCMake_TEST_FAILED "AppRun is not executable")
endif()
@@ -0,0 +1,19 @@
appimagetool[^
]*
Using architecture x86_64
Deleting pre-existing \.DirIcon
Creating \.DirIcon symlink based on information from desktop file
WARNING: AppStream upstream metadata is missing, please consider creating it
in usr/share/metainfo/com\.example\.app\.appdata\.xml
Please see https://www\.freedesktop\.org/software/appstream/docs/chap-Quickstart\.html#sect-Quickstart-DesktopApps
for more information or use the generator at
https://docs\.appimage\.org/packaging-guide/optional/appstream\.html#using-the-appstream-generator
Generating squashfs\.\.\.
Embedding ELF\.\.\.
Marking the AppImage as executable\.\.\.
Embedding MD5 digest
Success
Please consider submitting your AppImage to AppImageHub, the crowd-sourced
central directory of available AppImages, by opening a pull request
at https://github\.com/AppImage/appimage\.github\.io
@@ -0,0 +1,44 @@
CPack: Create package using AppImage
CPack: Install projects
CPack: - Install project: CPackAppImageGenerator \[Release\]
CPack: Create package
CPack: AppDir: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux"
CPack: Found Desktop file: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/usr/share/applications/com\.example\.app\.desktop"
CPack: Desktop file destination: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/com\.example\.app\.desktop"
CPack: Icon file: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/usr/share/icons/hicolor/64x64/apps/ApplicationIcon\.png"
CPack: Icon link destination: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/ApplicationIcon\.png"
CPack: Using AppRun file: "[^"]*/Tests/RunCMake/RunCPack/AppImageUsrPrefix/AppRun"
CPack: Running AppImageTool: "[^"]*" "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux" "\.\./GeneratorTest-1\.2\.3-Linux\.AppImage" "--runtime-file" "[^"]*"
[^
]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux should be packaged as \.\./GeneratorTest-1\.2\.3-Linux\.AppImage
Parallel mksquashfs: Using [0-9]+ processors
Creating 4\.0 filesystem on [^
]*/GeneratorTest-1\.2\.3-Linux\.AppImage, block size [0-9]+\.
.*
Exportable Squashfs 4\.0 filesystem, zstd compressed, data block size [0-9]+
[ ]compressed data, compressed metadata, compressed fragments,
[ ]compressed xattrs, compressed ids
[ ]duplicates are removed
Filesystem size [0-9\.]+ Kbytes \([0-9\.]+ Mbytes\)
[ ][0-9\.]+% of uncompressed filesystem size \([0-9\.]+ Kbytes\)
Inode table size [0-9]+ bytes \([0-9\.]+ Kbytes\)
[ ][0-9\.]+% of uncompressed inode table size \([0-9]+ bytes\)
Directory table size [0-9]+ bytes \([0-9\.]+ Kbytes\)
[ ][0-9\.]+% of uncompressed directory table size \([0-9]+ bytes\)
Number of duplicate files found [0-9]+
Number of inodes [0-9]+
Number of files [0-9]+
Number of fragments [0-9]+
Number of symbolic links [0-9]+
Number of device nodes [0-9]+
Number of fifo nodes [0-9]+
Number of socket nodes [0-9]+
Number of directories [0-9]+
Number of hard-links [0-9]+
Number of ids \(unique uids \+ gids\) [0-9]+
Number of uids [0-9]+
[ ]root \([0-9]+\)
Number of gids [0-9]+
[ ]root \([0-9]+\)
CPack: - package: [^
]*/Tests/RunCMake/CPack_AppImage/AppImageCustomAppRun-build/GeneratorTest-1\.2\.3-Linux\.AppImage generated\.
@@ -0,0 +1,3 @@
if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/GeneratorTest-1.2.3-Linux.AppImage")
set(RunCMake_TEST_FAILED "AppImage package not generated")
endif()
@@ -0,0 +1,19 @@
appimagetool[^
]*
Using architecture x86_64
Deleting pre-existing \.DirIcon
Creating \.DirIcon symlink based on information from desktop file
WARNING: AppStream upstream metadata is missing, please consider creating it
in usr/share/metainfo/com\.example\.app\.appdata\.xml
Please see https://www\.freedesktop\.org/software/appstream/docs/chap-Quickstart\.html#sect-Quickstart-DesktopApps
for more information or use the generator at
https://docs\.appimage\.org/packaging-guide/optional/appstream\.html#using-the-appstream-generator
Generating squashfs\.\.\.
Embedding ELF\.\.\.
Marking the AppImage as executable\.\.\.
Embedding MD5 digest
Success
Please consider submitting your AppImage to AppImageHub, the crowd-sourced
central directory of available AppImages, by opening a pull request
at https://github\.com/AppImage/appimage\.github\.io
@@ -0,0 +1,44 @@
CPack: Create package using AppImage
CPack: Install projects
CPack: - Install project: CPackAppImageGenerator \[Release\]
CPack: Create package
CPack: AppDir: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux"
CPack: Found Desktop file: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/usr/share/applications/com\.example\.app\.desktop"
CPack: Desktop file destination: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/com\.example\.app\.desktop"
CPack: Icon file: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/usr/share/icons/hicolor/64x64/apps/ApplicationIcon\.png"
CPack: Icon link destination: "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux/ApplicationIcon\.png"
CPack: No AppRun found, generating a default one that will run: "usr/bin/app"
CPack: Running AppImageTool: "[^"]*" "[^"]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux" "\.\./GeneratorTest-1\.2\.3-Linux\.AppImage" "--runtime-file" "[^"]*"
[^
]*/_CPack_Packages/Linux/AppImage/GeneratorTest-1\.2\.3-Linux should be packaged as \.\./GeneratorTest-1\.2\.3-Linux\.AppImage
Parallel mksquashfs: Using [0-9]+ processors
Creating 4\.0 filesystem on [^
]*/GeneratorTest-1\.2\.3-Linux\.AppImage, block size [0-9]+\.
.*
Exportable Squashfs 4\.0 filesystem, zstd compressed, data block size [0-9]+
[ ]compressed data, compressed metadata, compressed fragments,
[ ]compressed xattrs, compressed ids
[ ]duplicates are removed
Filesystem size [0-9\.]+ Kbytes \([0-9\.]+ Mbytes\)
[ ][0-9\.]+% of uncompressed filesystem size \([0-9\.]+ Kbytes\)
Inode table size [0-9]+ bytes \([0-9\.]+ Kbytes\)
[ ][0-9\.]+% of uncompressed inode table size \([0-9]+ bytes\)
Directory table size [0-9]+ bytes \([0-9\.]+ Kbytes\)
[ ][0-9\.]+% of uncompressed directory table size \([0-9]+ bytes\)
Number of duplicate files found [0-9]+
Number of inodes [0-9]+
Number of files [0-9]+
Number of fragments [0-9]+
Number of symbolic links [0-9]+
Number of device nodes [0-9]+
Number of fifo nodes [0-9]+
Number of socket nodes [0-9]+
Number of directories [0-9]+
Number of hard-links [0-9]+
Number of ids \(unique uids \+ gids\) [0-9]+
Number of uids [0-9]+
[ ]root \([0-9]+\)
Number of gids [0-9]+
[ ]root \([0-9]+\)
CPack: - package: [^
]*/Tests/RunCMake/CPack_AppImage/AppImageUsrPrefix-build/GeneratorTest-1\.2\.3-Linux\.AppImage generated\.
@@ -7,3 +7,9 @@ if(CMake_TEST_CPACK_APPIMAGE_RUNTIME_FILE)
endif()
run_cpack(AppImageTestApp BUILD)
run_cpack(AppImageUsrPrefix BUILD)
block()
list(APPEND RunCMake_TEST_OPTIONS -DCUSTOM_APPRUN=ON)
run_cpack(AppImageCustomAppRun SAMPLE AppImageUsrPrefix BUILD)
endblock()
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
# custom AppRun provided through CPACK_APPIMAGE_APPRUN_FILE
exec "$(dirname "$0")/usr/bin/app" "$@"
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 4.0)
project(CPackAppImageGenerator
LANGUAGES CXX
VERSION "1.2.3"
)
add_executable(app main.cpp)
install(TARGETS app
RUNTIME
DESTINATION bin
COMPONENT applications)
# A directory named like the executable, sorting before "bin", must not be
# mistaken for the executable referenced by the desktop file.
install(DIRECTORY DESTINATION apps/app)
install(FILES com.example.app.desktop DESTINATION share/applications)
install(FILES ApplicationIcon.png DESTINATION share/icons/hicolor/64x64/apps)
# Create AppImage package
set(CPACK_GENERATOR AppImage)
set(CPACK_PACKAGE_NAME GeneratorTest)
set(CPACK_PACKAGE_VERSION ${CMAKE_PROJECT_VERSION})
set(CPACK_PACKAGE_VENDOR "ACME Inc")
set(CPACK_PACKAGE_DESCRIPTION "An AppImage package for testing CMake's CPack AppImage generator")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A test AppImage package")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.example.com")
set(CPACK_PACKAGING_INSTALL_PREFIX /usr)
# AppImage generator variables
set(CPACK_PACKAGE_ICON ApplicationIcon.png)
if(CUSTOM_APPRUN)
set(CPACK_APPIMAGE_APPRUN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/AppRun")
endif()
include(CPack)
@@ -0,0 +1,6 @@
[Desktop Entry]
Name=App
Exec=app %u
Icon=ApplicationIcon
Type=Application
Categories=System
@@ -0,0 +1,3 @@
int main()
{
}