#!/usr/bin/env python3 import os import sys from os import path from sys import argv import urllib from subprocess import call, check_output import shutil import pathlib from urllib import request from urllib.request import urlretrieve import lddwrap import argparse from resolve_library import resolve as resolve_library basedir = path.realpath(path.dirname(__file__)) def download_always(url: str, filename: str) -> None: urlretrieve(url, filename) def download_if_not_found(url: str, filename: str) -> None: if path.exists(filename): return download_always(url, filename) def download_appimagetool(): url = "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" filename = "appimagetool" download_if_not_found(url, filename) def build(*args: list[str]): call(args=["./build.sh", *args]) def remove_recursive(inpath: str): print("remove_recursive(%s)" % inpath) if path.isdir(inpath) and not path.islink(inpath): for inner in os.listdir(inpath): remove_recursive(path.join(inpath, inner)) print("os.removedirs(%s)" % inpath) os.removedirs(inpath) elif path.islink(inpath): print("os.unlink(%s)" % inpath) os.unlink(inpath) else: print("os.remove(%s)" % inpath) os.remove(inpath) def force_link(src: str, dst: str): if path.exists(dst): remove_recursive(dst) os.symlink(src, dst) def force_copy(src: str, dst: str): print("force_copy(%s, %s)" % (src, dst)) if path.exists(dst) and path.isdir(dst): dst = path.join(dst, path.basename(src)) if path.exists(dst): remove_recursive(dst) shutil.copy(src, dst) def copy_libraries(libpath: str, previous: list[str] = []): print("Getting libraries for '%s'..." % libpath) for lib in lddwrap.list_dependencies(pathlib.Path(libpath)): if str(lib.path) in previous: continue print(" - Library %s" % lib.soname, end="") if lib.path == None: print("") continue print(" (%s)" % lib.path) inpaths = resolve_library(str(lib.path)) for inpath in inpaths: outpath = path.join("AppDir/lib", path.basename(inpath)) force_copy(inpath, outpath) previous.append(str(lib.path)) copy_libraries(str(lib.path), previous) def overwrite_file(dst: str, contents: str): if path.exists(dst): remove_recursive(dst) with open(dst, "wt+") as f: f.write(contents) def main() -> None: P = argparse.ArgumentParser() P.add_argument("-j", "--parallel", action=argparse._StoreAction, default=0, type=int, help="Specifies the number of jobs to use. Set to 1 to disable parallelism", dest="parallel") P.add_argument("-D", "--define", default=[], action=argparse._AppendAction, help="Defines a CMake variable", dest="cmake_vars") p = P.parse_args(argv[1:]) old_dir = os.curdir os.chdir(basedir) os.makedirs("build", exist_ok=True) os.chdir("build") args=["cmake", ".."] for definition in p.cmake_vars: args.append("-D%s" % definition) ret = call(args); if ret != 0: exit(ret) parallel = p.parallel if parallel == 0: parallel = os.cpu_count() args=["cmake", "--build", ".", "-j%d" % parallel] ret = call(args) if ret != 0: exit(ret) download_appimagetool() os.makedirs("AppDir", exist_ok=True) for dir in ["bin", "lib", "share"]: os.makedirs(path.join("AppDir", dir), exist_ok=True) force_link(".", "AppDir/usr") force_link(".", "AppDir/local") force_link("lib", "AppDir/lib64") force_copy("looper", "AppDir/bin") copy_libraries("looper") force_copy(path.join(basedir, "assets/com.complecwaft.Looper.desktop"), "AppDir") force_copy(path.join(basedir, "assets/icon.svg"), "AppDir/looper.svg") force_copy(path.join(basedir, "assets/icon.png"), "AppDir/looper.png") overwrite_file("AppDir/AppRun", """#!/bin/bash export LD_LIBRARY_PATH="$APPDIR/lib" if [ "$1" = "--gdb" ]; then shift exec gdb --args "$APPDIR/usr/bin/looper" "$@" else exec "$APPDIR/usr/bin/looper" "$@" fi""") os.chmod("AppDir/AppRun", 0o777) arch = check_output(["uname", "-m"]) print("Architecture: %s" % arch.decode()) os.environ["ARCH"] = arch.decode().removesuffix("\n") call(args=["./appimagetool", "AppDir", "Looper.AppImage"]) os.chdir(old_dir) if __name__ == "__main__": main()