Skip to content

Instantly share code, notes, and snippets.

@hbirchtree
Forked from fracek/CMakeLists.txt
Last active December 11, 2021 09:08
Show Gist options
  • Save hbirchtree/afada1b4886a79abac3e2771773059e3 to your computer and use it in GitHub Desktop.
Save hbirchtree/afada1b4886a79abac3e2771773059e3 to your computer and use it in GitHub Desktop.
CMake, GTK+ 3 and AppImage
[Desktop Entry]
Version=1.0
Type=Application
Name=@APPIMAGE_TITLE@
Exec=@APPIMAGE_EXEC@
StartupWMClass=@APPIMAGE_EXEC_WM@
Icon=@APPIMAGE_ICON_REF@
# Set the name and the supported language of the project
PROJECT(hello-world C)
# Set the minimum version of cmake required to build this project
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
### We need this in order to find CMake modules located in this directory
set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR} )
include ( LinuxAppImageBuild )
# Use the package PkgConfig to detect GTK+ headers/library files
FIND_PACKAGE(PkgConfig REQUIRED)
PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0)
# Setup CMake to use GTK+, tell the compiler where to look for headers
# and to the linker where to look for libraries
INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS})
LINK_DIRECTORIES(${GTK3_LIBRARY_DIRS})
# Add other flags to the compiler
ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER})
# Add an executable compiled from hello.c
ADD_EXECUTABLE(hello hello.c)
# Link the target to the GTK+ libraries
TARGET_LINK_LIBRARIES(hello ${GTK3_LIBRARIES})
### We now generate the AppImage
APPIMAGE_PACKAGE(hello "Hello GTK+ 3" "" "" "")
#include <gtk/gtk.h>
static void
activate(GtkApplication *app,
gpointer user_data) {
GtkWidget *window;
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Hello GNOME");
gtk_widget_show_all(window);
}
int
main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example",
G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate",
G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return (status);
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
set ( APPIMAGE_CONFIG_DIR "${CMAKE_SOURCE_DIR}" ) # Specifies where to find template files, in this case this same directory
set ( APPIMAGE_ASSISTANT_PROGRAM CACHE FILEPATH "AppImageAssistant executable" )
set ( APPIMAGE_APPRUN_PROGRAM CACHE FILEPATH "AppImage AppRun executable" )
set ( APPIMAGE_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deploy/linux-appimage" CACHE PATH "Where to put the AppDir items" )
set ( APPIMAGE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/package/linux-appimage" CACHE PATH "AppImage output directory" )
set ( APPIMAGE_FOLLOW_STANDARD OFF CACHE BOOL "Whether generator should follow the spec" )
set ( APPIMAGE_DEFAULT_ICON_FILE "${CMAKE_SOURCE_DIR}/icon.svg" CACHE FILEPATH "Default icon for AppImages" )
macro( APPIMAGE_PACKAGE TARGET APPIMAGE_TITLE DATA LIBRARIES LIBRARY_FILES )
string ( TOLOWER "${APPIMAGE_TITLE}" APPIMAGE_INTERNALNAME )
string ( MAKE_C_IDENTIFIER "${APPIMAGE_INTERNALNAME}" APPIMAGE_INTERNALNAME )
# Some prerequisites
# TITLE here is used as the name of the final AppImage as well as the desktop entry's name
set ( APPIMAGE_TITLE "${APPIMAGE_TITLE}" )
set ( APPIMAGE_INTERNALNAME "${APPIMAGE_INTERNALNAME}" )
set ( APPIMAGE_LIBRARIES )
set ( APPIMAGE_DATA )
# Icon file to be used for the AppImage, only one in this case, preferrably SVG
set ( APPIMAGE_ICON "${APPIMAGE_DEFAULT_ICON_FILE}" )
# We define a way to reference this icon based on where it is located
set ( APPIMAGE_ICON_REF "${APPIMAGE_INTERNALNAME}.svg" )
# This helps the window manager to recognize the program even if it has no embedded or loaded icon
set ( APPIMAGE_EXEC_WM ${TARGET} )
# Sets the launch variable in .desktop entry
set ( APPIMAGE_EXEC ${TARGET} )
# This directory is used for temporary files, might get messy
set ( APPIMAGE_CACHE_DIR "${APPIMAGE_WORKING_DIRECTORY}/${APPIMAGE_INTERNALNAME}_cache" )
# Where the AppDir is generated
set ( APPIMAGE_INTERMEDIATE_DIR "${APPIMAGE_WORKING_DIRECTORY}/${APPIMAGE_INTERNALNAME}" )
set ( APPIMAGE_ICON_TARGET "${APPIMAGE_INTERMEDIATE_DIR}/${APPIMAGE_ICON_REF}" )
set ( APPIMAGE_BINARY_DIR "${APPIMAGE_INTERMEDIATE_DIR}/usr/bin" )
set ( APPIMAGE_ASSET_DIR "${APPIMAGE_INTERMEDIATE_DIR}/usr/share" )
set ( APPIMAGE_LIBRARY_DIR "${APPIMAGE_INTERMEDIATE_DIR}/usr/lib" )
set ( APPIMAGE_FINAL_NAME "${APPIMAGE_OUTPUT_DIRECTORY}/${APPIMAGE_TITLE}.AppImage" )
list ( APPEND APPIMAGE_LIBRARIES
${LIBRARIES} )
list ( APPEND APPIMAGE_DATA
${DATA} )
# Remove the previous AppImage file to avoid confusion when generating a new one
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E remove "${APPIMAGE_FINAL_NAME}"
)
# Create some necessary directory structure in AppDir
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${APPIMAGE_OUTPUT_DIRECTORY}"
)
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${APPIMAGE_BINARY_DIR}"
)
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${APPIMAGE_CACHE_DIR}"
)
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${APPIMAGE_LIBRARY_DIR}"
)
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${APPIMAGE_ASSET_DIR}"
)
# Copy and configure some data for the AppDir
configure_file (
"${APPIMAGE_ICON}"
"${APPIMAGE_ICON_TARGET}"
COPYONLY
)
configure_file (
"${APPIMAGE_ICON}"
"${APPIMAGE_INTERMEDIATE_DIR}/.DirIcon"
COPYONLY
)
configure_file (
"${APPIMAGE_CONFIG_DIR}/application.desktop.in"
"${APPIMAGE_INTERMEDIATE_DIR}/${APPIMAGE_INTERNALNAME}.desktop"
@ONLY
)
configure_file (
"${APPIMAGE_APPRUN_PROGRAM}"
"${APPIMAGE_INTERMEDIATE_DIR}/AppRun"
COPYONLY
)
# Copy resources into AppDir
foreach ( RESC ${DATA} )
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${RESC}" "${APPIMAGE_ASSET_DIR}"
)
endforeach()
# Copy bundled libraries into AppDir
foreach ( LIB ${LIBRARY_FILES} )
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${LIB}" "${APPIMAGE_LIBRARY_DIR}"
)
endforeach()
foreach ( LIB ${LIBRARIES} )
add_custom_command ( TARGET ${TARGET}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${LIB}>" "${APPIMAGE_LIBRARY_DIR}"
)
endforeach()
# Copy the binary to AppDir
add_custom_command ( TARGET ${TARGET}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${TARGET}>" "${APPIMAGE_BINARY_DIR}"
)
# Do the actual packaging step with AppImageKit
add_custom_command ( TARGET ${TARGET}
POST_BUILD
COMMAND "${APPIMAGE_ASSISTANT_PROGRAM}" "${APPIMAGE_INTERMEDIATE_DIR}" "${APPIMAGE_FINAL_NAME}"
)
install (
FILES
"${APPIMAGE_FINAL_NAME}"
DESTINATION
"${CMAKE_PACKAGED_OUTPUT_PREFIX}/linux-appimage"
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
)
endmacro()
@probonopd
Copy link

probonopd commented Jun 29, 2016

Thank you very much, may I place this as an example into the AppImageKit repository?
Currently fails due to 2 minor issues:

  1. The AppImageAssistant call fails due to spaces in /Hello\ GTK+\ 3.AppImage - are there quotes missing?
  2. deploy/linux-appimage/hello_gtk__3/AppRun doesn't have the execute bit set

Two more non-fatal issues:

  1. make clean seems not to be implemented
  2. Running make multiple times fails (before running AppImageAssistant should delete the target file if it already exists)

Note to self: I did

sudo apt-get -y install cmake libgtk-3-dev wget

wget https://gist.github.com/hbirchtree/afada1b4886a79abac3e2771773059e3/archive/c2ae252a8ec65b490242141b8ca47556eeccdcb3.zip
unzip afa*.zip
cd afa*/

wget -c https://github.com/probonopd/AppImageKit/releases/download/5/AppRun
wget -c https://github.com/probonopd/AppImageKit/releases/download/5/AppImageAssistant
chmod a+x AppImageAssistant AppRun

cmake . -DAPPIMAGE_APPRUN_PROGRAM=AppRun -DAPPIMAGE_ASSISTANT_PROGRAM=AppImageAssistant
make

@hbirchtree
Copy link
Author

hbirchtree commented Jun 29, 2016

@probonopd, I was not able to reproduce your issue with spaces. A sufficient amount of quotes seems to have been applied in the script to avoid this. I tested this with CMake 3.5.1 and Ubuntu 16.04, where the only issue I know of is that "make clean" will not wipe the generated files. (Which will be added soon)
Same goes for permissions, but I could add an extra step to ensure these permissions are set.

Edit:
I retraced your steps, and I would like to point out that the AppImageAssistant executable you used does not want to move the AppImage file into another directory. (Instead placing it under deploy/, not packaged/) I used a freshly compiled AppImageAssistant without issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment