From 08ca836ade97d84beb68e25862923a110d4adb4e Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Tue, 20 Oct 2020 16:41:38 +0200 Subject: [PATCH] [build] A working appimage build To generate the AppImage the libraries from the host system will be used (if it worked on my machine it should works on your machine). All libraries are copied into the AppImage, it should have a size of something like 100Mio. Trying to make the AppImage works on other computers, for now only works on debian machines, it's facheux for an AppImage --- .gitignore | 3 + Aegisub/Aegisub.desktop | 13 +++++ Aegisub/AppRun | 9 +++ Aegisub/aegisub-icon.png | Bin 0 -> 5030 bytes {appimage => Aegisub/usr/bin}/.gitkeep | 0 Aegisub/usr/lib/.gitkeep | 0 Makefile.target | 7 ++- configure.ac | 3 +- header.mk | 4 ++ tools/copy-libs.lua | 76 +++++++++++++++++++++++++ 10 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 Aegisub/Aegisub.desktop create mode 100755 Aegisub/AppRun create mode 100644 Aegisub/aegisub-icon.png rename {appimage => Aegisub/usr/bin}/.gitkeep (100%) create mode 100755 Aegisub/usr/lib/.gitkeep create mode 100755 tools/copy-libs.lua diff --git a/.gitignore b/.gitignore index 75b7f9586..45da25986 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ *.vsp *.y4m *.zip +*.DirIcon *~ /bin @@ -67,6 +68,8 @@ packages/desktop/aegisub.desktop packages/desktop/aegisub.desktop.template packages/win_installer/vendor src/aegisub +Aegisub/aegisub +Aegisub/usr/bin/aegisub src/libresrc/bitmap.cpp src/libresrc/bitmap.h src/libresrc/default_config.cpp diff --git a/Aegisub/Aegisub.desktop b/Aegisub/Aegisub.desktop new file mode 100644 index 000000000..c630bbaf8 --- /dev/null +++ b/Aegisub/Aegisub.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Aegisub +Icon=aegisub-icon +GenericName=Subtitle Editor +Comment=Create and edit subtitles for film and videos. +Keywords=subtitles;video;audio;text +Terminal=false +Categories=AudioVideo;AudioVideoEditing; +MimeType=application/x-srt;text/plain;text/x-ass;text/x-microdvd;text/x-ssa; +StartupNotify=true +Exec=aegisub diff --git a/Aegisub/AppRun b/Aegisub/AppRun new file mode 100755 index 000000000..27f3ec957 --- /dev/null +++ b/Aegisub/AppRun @@ -0,0 +1,9 @@ +#!/bin/sh + +HERE=$(dirname $(readlink -f "$0")) +export LC_ALL="en_US.UTF-8" +export LD_LIBRARY_PATH="$HERE/usr/lib" +EXEC=$(grep -e '^Exec=.*' "$HERE"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) +ldd $(which $EXEC) +export PATH="$HERE/usr/bin" +exec $EXEC $@ diff --git a/Aegisub/aegisub-icon.png b/Aegisub/aegisub-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fbbd14dc9f46796622c457b781c1388d45353788 GIT binary patch literal 5030 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 literal 0 HcmV?d00001 diff --git a/appimage/.gitkeep b/Aegisub/usr/bin/.gitkeep similarity index 100% rename from appimage/.gitkeep rename to Aegisub/usr/bin/.gitkeep diff --git a/Aegisub/usr/lib/.gitkeep b/Aegisub/usr/lib/.gitkeep new file mode 100755 index 000000000..e69de29bb diff --git a/Makefile.target b/Makefile.target index fd40d87bf..202cb590d 100644 --- a/Makefile.target +++ b/Makefile.target @@ -1,5 +1,5 @@ ifneq (yes, $(INCLUDING_CHILD_MAKEFILES)) -COMMANDS := all install clean distclean test depclean osx-bundle osx-dmg test-automation test-libaegisub style tags +COMMANDS := all install clean distclean test depclean osx-bundle osx-dmg test-automation test-libaegisub style tags appimage .PHONY: $(COMMANDS) .DEFAULT_GOAL := all @@ -95,6 +95,11 @@ style: tags: ./tools/tags.bash +appimage: src/aegisub + cp $^ Aegisub/usr/bin/aegisub + ./tools/copy-libs.lua Aegisub/usr/bin/aegisub Aegisub/usr/lib + ./tools/appimagetool.AppImage Aegisub + # The actual build rules .SUFFIXES: diff --git a/configure.ac b/configure.ac index cc202d8ea..658f066da 100644 --- a/configure.ac +++ b/configure.ac @@ -191,8 +191,9 @@ AC_ARG_ENABLE([appimage], [AEGISUB_APPIMAGE_ENABLED=no]) AS_IF([test "x$AEGISUB_APPIMAGE_ENABLED" = "xyes"], [ AC_MSG_CHECKING([Downloading AppImage creation tool]) - wget https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage \ + wget https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-`arch`.AppImage \ -O tools/appimagetool.AppImage -o config.wget.log + chmod 00700 tools/appimagetool.AppImage AS_IF([test $? -eq 0 ], [ AC_MSG_RESULT([done]) ], [ diff --git a/header.mk b/header.mk index a9ce1d778..c82d73974 100644 --- a/header.mk +++ b/header.mk @@ -38,6 +38,10 @@ DISTCLEANFILES += \ $(TOP)autom4te.cache \ $(TOP)aclocal.m4 \ +CLEANFILES += \ + $(TOP)Aegisub/usr/bin/aegisub \ + $(wildcard $(TOP)Aegisub/usr/lib/*) + define MKDIR_INSTALL @$(BIN_MKDIR_P) $(dir $@) $(BIN_INSTALL) -m644 $< $@ diff --git a/tools/copy-libs.lua b/tools/copy-libs.lua new file mode 100755 index 000000000..eb674ab20 --- /dev/null +++ b/tools/copy-libs.lua @@ -0,0 +1,76 @@ +#!/usr/bin/env lua +-- Needs awk and a shell (usually bash / sh) and ldd, which is a Linux utility. +-- Thus run only this script on a Linux env or where the .so files can be found +-- with the ldd command. + +if not arg or #arg ~= 2 then os.exit(1) end + +io.stdout:write(string.format('Running for file %s\n', arg[1])) +io.stdout:write(string.format('Dest folder is %s\n', arg[2])) + +-- Libs tables +LIBS_WRITE = {} +LIBS_READ = {} + +-- Capture the output of a command +function os.capture(cmd) + local f = assert(io.popen(cmd, 'r')) + local s = assert(f:read('*a')) + f:close() + return s +end + +-- Simple copy of a table, it doesn't work with metatables and recursive tables +function copy_simple(obj) + if type(obj) ~= 'table' then return obj end + local res = {} + for k, v in pairs(obj) do res[copy_simple(k)] = copy_simple(v) end + return res +end + +-- Add the content of t2 in t1 +function concatenate(t1, t2) + for name, file in pairs(t2) do + t1[name] = file + end +end + +-- Get the number of elements in a table +function tablelength(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count +end + +-- The ldd command line utility, but in lua +function ldd(file) + local libs = {} + local cmd = string.format('ldd %s | awk \'$2 = "=>" && $3 { print $1 " " $3 }\'', arg[1]) + local out = os.capture(cmd) + + for name, file in out:gmatch("([^\n ]*) ([^\n ]*)[\n]") do + libs[name] = file + end + + return libs +end + +-- Add NEEDS for each lib while there are some added. It's like a dataflow algorithme. +LIBS_WRITE = ldd(arg[1]) +while tablelength(LIBS_READ) ~= tablelength(LIBS_WRITE) do + LIBS_READ = copy_simple(LIBS_WRITE) + + for name, file in pairs(LIBS_READ) do + concatenate(LIBS_WRITE, ldd(file)) + end +end + +io.stdout:write(string.format("Cleaning %s", arg[2])) +os.execute(string.format("rm -f %s/*", arg[2])) + +for name, file in pairs(LIBS_WRITE) do + local cmd = string.format('cp %s %s/%s && chmod 555 %s/%s', + file, arg[2], name, arg[2], name) + os.execute(cmd) +end +io.stdout:write(string.format("Copied %d libraries to %s\n", tablelength(LIBS_WRITE), arg[2])) -- GitLab