diff --git a/.gitignore b/.gitignore index a72e0bd5bcd8634022c431725065d542a5d1d087..e8a873187121a803de6f8ace362389e28b7b8d74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.App +*.AppImage *.[oadi] *.ass *.avi @@ -36,6 +37,7 @@ *.vsp *.y4m *.zip +*.DirIcon *~ /bin @@ -66,6 +68,7 @@ packages/desktop/aegisub.desktop packages/desktop/aegisub.desktop.template packages/win_installer/vendor src/aegisub +Aegisub/ src/libresrc/bitmap.cpp src/libresrc/bitmap.h src/libresrc/default_config.cpp @@ -75,6 +78,7 @@ svn-revision.h svn_revision tests/*.json tests/run +tools/linuxdeploy tools/osx-bundle-restart-helper tools/osx-bundle.sed tools/repack-thes-dict @@ -98,5 +102,3 @@ vendor/luajit/src/luajit *.tmp cscope.files tags -config.guess -config.sub diff --git a/Makefile.inc.in b/Makefile.inc.in index be9a686ff7ac642c3991953f269f830336c73e7a..62178ddab1d7ac13e217348e78ce5a39d81e8e0c 100644 --- a/Makefile.inc.in +++ b/Makefile.inc.in @@ -21,6 +21,7 @@ LIB := $(LIB) # PLATFORM SETTINGS ################### BUILD_DARWIN = @build_darwin@ +BUILD_LINUX = @build_linux@ ####### # FLAGS @@ -118,23 +119,29 @@ PRECOMPILED_HEADER = @enable_gcc_prec@ ########## # BINARIES ########## -BIN_AR = ar -BIN_RANLIB = ranlib -BIN_LN = ln -BIN_RM = rm -BIN_SHELL = @SHELL@ -BIN_MV = mv -BIN_SED = sed -BIN_INSTALL = @INSTALL@ -BIN_MSGMERGE = @MSGMERGE@ -BIN_XGETTEXT = @XGETTEXT@ -BIN_MSGFMT = @MSGFMT@ -BIN_CC = @CC@ -BIN_CXX = @CXX@ -BIN_CP = cp -BIN_MKDIR = mkdir -BIN_MKDIR_P = mkdir -p -BIN_ECHO = echo -BIN_TOUCH = touch -BIN_LUA = @LUA@ +BIN_AR = ar +BIN_RANLIB = ranlib +BIN_LN = ln +BIN_RM = rm +BIN_SHELL = @SHELL@ +BIN_MV = mv +BIN_SED = sed +BIN_INSTALL = @INSTALL@ +BIN_MSGMERGE = @MSGMERGE@ +BIN_XGETTEXT = @XGETTEXT@ +BIN_MSGFMT = @MSGFMT@ +BIN_CC = @CC@ +BIN_CXX = @CXX@ +BIN_CP = cp +BIN_MKDIR = mkdir +BIN_MKDIR_P = mkdir -p +BIN_ECHO = echo +BIN_TOUCH = touch +BIN_LUA = @LUA@ BIN_WX_CONFIG = @WX_CONFIG_PATH@ + +################ +# APPIMAGE TOOLS +################ +TOOL_LINUXDEPLOY = $(TOM)tools/linuxdeploy +TOOL_APPIMAGE = $(TOP)tools/appimagetool.AppImage diff --git a/Makefile.target b/Makefile.target index fd40d87bfe92fcac59f3b8719433ab3308e6ee25..d0ad20cbeab342b269175296a093d20cfdeec43e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -1,5 +1,8 @@ ifneq (yes, $(INCLUDING_CHILD_MAKEFILES)) COMMANDS := all install clean distclean test depclean osx-bundle osx-dmg test-automation test-libaegisub style tags +ifeq (yes, $(BUILD_LINUX)) +COMMANDS := $(COMMANDS) appimage +endif .PHONY: $(COMMANDS) .DEFAULT_GOAL := all @@ -41,10 +44,9 @@ endef $(foreach target,$(LIB),$(eval $(call set_target_flags,$(target),$(TOP)lib/lib$(target).a))) $(foreach target,$(PROGRAM),$(eval $(call set_target_flags,$(notdir $(target)),$(target)))) -# Create the build and install targets for programs -# Not done with a pattern rule since the pattern would be just %: and doing that -# leads to make trying to use gcc to make any nonexistent targets rather than -# erroring +# Create the build and install targets for programs. Not done with a pattern +# rule since the pattern would be just %: and doing that leads to make trying +# to use gcc to make any nonexistent targets rather than erroring define create_program_targets ifdef $1_INSTALLNAME install: $(DESTDIR)$(P_BINDIR)/$($1_INSTALLNAME) @@ -80,6 +82,7 @@ all: $(LIB_TARGETS) clean: $(BIN_RM) -f $(OBJ) $(CLEANFILES) $(LIB_TARGETS) + $(BIN_RM) -rf $(CLEANDIRS) distclean: clean $(BIN_RM) -rf $(DISTCLEANFILES) $(DEP) @@ -90,16 +93,20 @@ depclean: clean install: style: - ./tools/astyle.bash + $(TOP)tools/astyle.bash tags: - ./tools/tags.bash + $(TOP)tools/tags.bash + +appimage: src/aegisub packages/desktop/Aegisub.desktop packages/desktop/aegisub.png install + $(TOOL_LINUXDEPLOY) --appdir Aegisub --desktop-file packages/desktop/Aegisub.desktop --icon-file packages/desktop/aegisub.png --executable src/aegisub + $(TOOL_APPIMAGE) Aegisub # The actual build rules .SUFFIXES: CXX_CMD = $(CXX_ENV) $(BIN_CXX) $(CFLAGS_DEP) $(CPPFLAGS) -CC_CMD = $(CXX_ENV) $(BIN_CC) $(CFLAGS_DEP) $(CPPFLAGS) +CC_CMD = $(CXX_ENV) $(BIN_CC) $(CFLAGS_DEP) $(CPPFLAGS) POST_FLAGS = $($@_FLAGS) -c -o $@ $< %.o: %.c ; $(CC_CMD) $(CFLAGS) $(POST_FLAGS) @@ -115,9 +122,9 @@ POST_FLAGS = $($@_FLAGS) -c -o $@ $< .SECONDEXPANSION: -# Libraries contain all object files they depend on (but they may depend on other files) -# Not using libtool on OS X because it has an unsilenceable warning about a -# compatibility issue with BSD 4.3 (wtf) +# Libraries contain all object files they depend on (but they may depend on +# other files). Not using libtool on OS X because it has an unsilenceable +# warning about a compatibility issue with BSD 4.3 (wtf) lib%.a: $$($$*_OBJ) @$(BIN_MKDIR_P) $(dir $@) $(BIN_AR) cru $@ $(filter %.o,$^) diff --git a/README.md b/README.md index 02d7240232ab9e5cc8ee7c798718b7048b1d850f..8632f33e60b197764fd29685e8b5c9d391b1e8b8 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,15 @@ On debian buster, the packages are the following: - libboost-thread-dev - astyle +### Build the binary + Once all the dependencies are installed, run: ```bash autoreconf -./configure --enable-debug --with-libpulse +./configure --enable-debug --enable-debug-exceptions --with-libpulse --disable-update-checker --enable-silent-rules --without-system-luajit make -j$(nproc) +make install ``` You may also consider the following rules: @@ -71,6 +74,24 @@ You may also consider the following rules: - `make tags` to build the ctags and cscope databases - `make style` to format your code with the right style +### Build an appimage + +First, install `patchelf` (`apt install patchelf` or similar for your distro) +and [linuxdeploy](https://github.com/linuxdeploy/linuxdeploy). An AppImage of +linuxdeploy can be found [here](https://martinm.iiens.net/linuxdeploy). You +will also need to download the appimagetool binary and save it to the +[tools](tools) folder. If you don't do it manually, it will be done for you at +some point by the build scripts. + +To build the AppImage, juste use the following commands: + +```bash +autoreconf +./configure --with-libpulse --enable-silent-rules --disable-update-checker --without-system-luajit --enable-appimage +make -j$(nproc) +make appimage +``` + ### Windows Prerequisites: diff --git a/config.guess b/config/config.guess similarity index 100% rename from config.guess rename to config/config.guess diff --git a/config.sub b/config/config.sub similarity index 100% rename from config.sub rename to config/config.sub diff --git a/install-sh b/config/install-sh similarity index 100% rename from install-sh rename to config/install-sh diff --git a/configure.ac b/configure.ac index 2c1e2d9f51ee8d04d1ec29a270715ae872fdda28..f27177baf7f1d37f1534df9e5a35846f0b975eb3 100644 --- a/configure.ac +++ b/configure.ac @@ -7,12 +7,21 @@ AC_INIT([Aegisub], [aegisub_version],, [aegisub]) : ${CFLAGS=""} : ${CXXFLAGS=""} AC_CONFIG_SRCDIR([src/main.cpp]) +AC_CONFIG_AUX_DIR([config]) AC_CONFIG_HEADER([acconf.h]) AC_CONFIG_MACRO_DIR([m4macros]) AC_GNU_SOURCE AC_CANONICAL_HOST AM_SILENT_RULES([yes]) +########################## +# Only run from source dir +########################## +AEGISUB_PATH_SOURCE="$(dirname $(readlink -f "$0"))" +AEGISUB_PATH_BUILD="$(pwd)" +AS_IF([! test "$AEGISUB_PATH_BUILD" = "$AEGISUB_PATH_BUILD"], + [AC_MSG_ERROR([The build directory must be the same as the source directory])]) + ################### # Required packages ################### @@ -41,6 +50,7 @@ AS_CASE([$host], [*-*-linux*], [build_linux="yes"]) AC_SUBST(build_darwin) +AC_SUBST(build_linux) ######################## # Configurable variables @@ -75,6 +85,48 @@ AC_SUBST(P_ICON) # set it to $ac_default_prefix if it hasn't been supplied. AS_CASE([x$prefix], [xNONE | x], [prefix="$ac_default_prefix"], []) +# Build with appimage support +# Do this here because we will override the install path +AC_ARG_ENABLE([appimage], + [AS_HELP_STRING([--enable-appimage], [Build Aegisub as an AppImage. Defaults to no])], + [AEGISUB_APPIMAGE_ENABLED=$enableval], + [AEGISUB_APPIMAGE_ENABLED=no]) +AS_IF([test "x$AEGISUB_APPIMAGE_ENABLED" = "xyes"], [ + # Check more binaries + AC_PATH_PROG([PATCHELF], [patchelf]) + AC_PATH_PROG([WGET], [wget]) + AC_PATH_PROG([CHMOD], [chmod]) + + AS_IF([test "$PATCHELF" = "notfound"], [AC_MSG_ERROR([patchelf is required for AppImage generation])]) + AS_IF([test "$WGET" = "notfound"], [AC_MSG_ERROR([wget is required for AppImage generation])]) + AS_IF([test "$CHMOD" = "notfound"], [AC_MSG_ERROR([chmod is required for AppImage generation])]) + + # Download the AppImage creation tool, transforms the AppDir into an AppImage + AC_MSG_CHECKING([Downloading AppImage creation tool]) + $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]) + ], [ + AC_MSG_FAILURE([failed]) + ]) + + # Downlaod the AppDir management tool, create the AppDir + AC_MSG_CHECKING([Downloading LinuxDeploy creation tool]) + $WGET https://martinm.iiens.net/linuxdeploy -O tools/linuxdeploy -a config.wget.log + $CHMOD 00700 tools/linuxdeploy + AS_IF([test $? -eq 0 ], [ + AC_MSG_RESULT([done]) + ], [ + AC_MSG_FAILURE([failed]) + ]) + + # Override prefix + prefix="$PWD/Aegisub/usr" +], [ + AC_MSG_NOTICE([Don't build with AppImage support]) +]) + # Install prefix used by wxStandardPaths::SetInstallPrefix. AC_DEFINE_UNQUOTED([INSTALL_PREFIX], ["$prefix"], [Default install prefix, or --prefix.]) diff --git a/header.mk b/header.mk index a9ce1d77872210a4a51f4d7794ab138ffe33756c..e9c7721b2ff196f4e2d34f1fff264cb594a1e60c 100644 --- a/header.mk +++ b/header.mk @@ -33,11 +33,22 @@ DISTCLEANFILES += \ $(TOP)build/git_version.h \ $(TOP)Makefile.inc \ $(TOP)config.log \ + $(TOP)config.wget.log \ $(TOP)acconf.h.in \ $(TOP)config.status \ $(TOP)autom4te.cache \ $(TOP)aclocal.m4 \ +CLEANFILES += \ + $(wildcard $(TOP)Aegisub/usr/lib/*) \ + $(TOP)Aegisub-x86_64.AppImage \ + $(TOP)cscope.files \ + $(TOP)cscope.out \ + $(TOP)tags \ + +CLEANDIRS += \ + $(TOP)Aegisub \ + define MKDIR_INSTALL @$(BIN_MKDIR_P) $(dir $@) $(BIN_INSTALL) -m644 $< $@ diff --git a/libaegisub/lua/modules/lfs.cpp b/libaegisub/lua/modules/lfs.cpp index 38f29d7928852a64ba247379c0ff366c067b6220..8053b6893a76fc28af0a6a77d308c5a86af398c8 100644 --- a/libaegisub/lua/modules/lfs.cpp +++ b/libaegisub/lua/modules/lfs.cpp @@ -112,7 +112,7 @@ DirectoryIterator *dir_new(const char *path, char **err) const char *get_mode(const char *path, char **err) { - return wrap(err, [ = ]() -> const char * { + return wrap(err, [ = ]() -> const char* { switch (bfs::status(path).type()) { case bfs::file_not_found: return nullptr; break; diff --git a/packages/desktop/Aegisub.desktop b/packages/desktop/Aegisub.desktop new file mode 100644 index 0000000000000000000000000000000000000000..e39d8570e59ae2516a7a70b16ba09cd95751908e --- /dev/null +++ b/packages/desktop/Aegisub.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Aegisub +Icon=aegisub +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/packages/desktop/aegisub.png b/packages/desktop/aegisub.png new file mode 120000 index 0000000000000000000000000000000000000000..078e90af053092ec5cfbd41bcabc28fbaa7eb43e --- /dev/null +++ b/packages/desktop/aegisub.png @@ -0,0 +1 @@ +64x64.png \ No newline at end of file diff --git a/src/mkv_wrap.cpp b/src/mkv_wrap.cpp index acb4be0e7c9732b0be224ea1f3ad2bdc0c26c282..bc9aa58d97a978112a6e5279b3822a6574cb01a3 100644 --- a/src/mkv_wrap.cpp +++ b/src/mkv_wrap.cpp @@ -105,7 +105,7 @@ struct MkvStdIO final : InputStream { read = &MkvStdIO::Read; scan = &MkvStdIO::Scan; getcachesize = [](InputStream *) -> unsigned int { return 16 * 1024 * 1024; }; - geterror = [](InputStream * st) -> const char * { return ((MkvStdIO *)st)->error.c_str(); }; + geterror = [](InputStream * st) -> const char* { return ((MkvStdIO *)st)->error.c_str(); }; memalloc = [](InputStream *, size_t size) { return malloc(size); }; memrealloc = [](InputStream *, void *mem, size_t size) { return realloc(mem, size); }; memfree = [](InputStream *, void *mem) { free(mem); }; diff --git a/tools/copy-libs.lua b/tools/copy-libs.lua new file mode 100755 index 0000000000000000000000000000000000000000..eb674ab20a795f66a19b7279d08a502e8b72311b --- /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]))