2024-04-10 20:51:56 -04:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
import shutil
|
|
|
|
import sys
|
|
|
|
import platform
|
2024-04-21 08:03:30 -04:00
|
|
|
import pwd
|
2024-04-10 20:51:56 -04:00
|
|
|
|
|
|
|
def get_app_target(text):
|
|
|
|
return re.search(r'(APP_TARGET) +(\"(.*?)\")', text).group(3)
|
|
|
|
|
|
|
|
def get_app_ver(text):
|
|
|
|
return re.search(r'(APP_VERSION) +(\"(.*?)\")', text).group(3)
|
|
|
|
|
|
|
|
def get_app_name(text):
|
|
|
|
return re.search(r'(APP_NAME) +(\"(.*?)\")', text).group(3)
|
|
|
|
|
|
|
|
def get_qt_path():
|
|
|
|
try:
|
|
|
|
return str(subprocess.check_output(["qtpaths", "--binaries-dir"]), 'utf-8').strip()
|
|
|
|
|
|
|
|
except:
|
|
|
|
print("A direct call to 'qtpaths' has failed so automatic retrieval of the QT bin folder is not possible.")
|
|
|
|
|
|
|
|
return input("Please enter the QT bin path (leave blank to cancel the build): ")
|
|
|
|
|
|
|
|
def get_qt_from_cli():
|
|
|
|
for arg in sys.argv:
|
|
|
|
if arg == "-qt_dir":
|
|
|
|
index = sys.argv.index(arg)
|
|
|
|
|
|
|
|
try:
|
|
|
|
return sys.argv[index + 1]
|
|
|
|
|
|
|
|
except:
|
|
|
|
return ""
|
|
|
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def get_ver_header():
|
|
|
|
current_dir = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
if current_dir == "":
|
|
|
|
return "src" + os.sep + "common.h"
|
|
|
|
else:
|
|
|
|
return current_dir + os.sep + "src" + os.sep + "common.h"
|
|
|
|
|
|
|
|
def get_nearest_subdir(path, sub_name):
|
|
|
|
dir_list = os.listdir(path)
|
|
|
|
ret = ""
|
|
|
|
|
|
|
|
for entry in dir_list:
|
|
|
|
if sub_name in entry:
|
|
|
|
ret = entry
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def cd():
|
|
|
|
current_dir = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
if current_dir != "":
|
|
|
|
os.chdir(current_dir)
|
|
|
|
|
|
|
|
def verbose_copy(src, dst):
|
|
|
|
print("cpy: " + src + " --> " + dst)
|
|
|
|
|
|
|
|
if os.path.isdir(src):
|
|
|
|
if os.path.exists(dst) and os.path.isdir(dst):
|
|
|
|
shutil.rmtree(dst)
|
|
|
|
|
|
|
|
try:
|
|
|
|
# ignore errors thrown by shutil.copytree()
|
|
|
|
# it's likely not actually failing to copy
|
|
|
|
# the directory but still throws errors if
|
|
|
|
# it fails to apply the same file stats as
|
|
|
|
# the source. this type of error can be
|
|
|
|
# ignored.
|
|
|
|
shutil.copytree(src, dst)
|
|
|
|
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
elif os.path.exists(src):
|
|
|
|
shutil.copyfile(src, dst)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print("wrn: " + src + " does not exists. skipping.")
|
|
|
|
|
|
|
|
def linux_build_app_dir(app_ver, app_name, app_target, qt_bin):
|
|
|
|
if not os.path.exists("app_dir/lib"):
|
|
|
|
os.makedirs("app_dir/lib")
|
|
|
|
|
|
|
|
verbose_copy("build/" + app_target, "app_dir/" + app_target)
|
|
|
|
|
|
|
|
shutil.copyfile("build/" + app_target, "/tmp/" + app_target)
|
|
|
|
# copying the executable file from the build folder to
|
|
|
|
# temp bypasses any -noexe retrictions a linux file
|
|
|
|
# system may have. there is a chance temp is also
|
|
|
|
# restricted in this way but that kind of config is
|
|
|
|
# rare. ldd will not run correctly with -noexe
|
|
|
|
# enabled.
|
|
|
|
|
|
|
|
lines = str(subprocess.check_output(["ldd", "/tmp/" + app_target]), 'utf-8').split("\n")
|
|
|
|
|
|
|
|
os.remove("/tmp/" + app_target)
|
|
|
|
|
|
|
|
for line in lines:
|
2024-04-14 08:01:54 -04:00
|
|
|
if " => " in line and "libc" not in line:
|
2024-04-10 20:51:56 -04:00
|
|
|
#if ("libQt" in line) or ("libicu" in line) or ("libGL.so" in line) or ("libpcre16.so" in line) or ("libpcre.so" in line):
|
|
|
|
if " (0x0" in line:
|
|
|
|
start_index = line.index("> ") + 2
|
|
|
|
end_index = line.index(" (0x0")
|
|
|
|
src_file = line[start_index:end_index]
|
|
|
|
file_name = os.path.basename(src_file)
|
|
|
|
|
|
|
|
verbose_copy(src_file, "app_dir/lib/" + file_name)
|
|
|
|
|
|
|
|
if "/usr/lib/x86_64-linux-gnu/qt6/bin" == qt_bin:
|
|
|
|
verbose_copy(qt_bin + "/../../libQt6DBus.so.6", "app_dir/lib/libQt6DBus.so.6")
|
|
|
|
|
|
|
|
else:
|
|
|
|
verbose_copy(qt_bin + "/../lib/libQt6DBus.so.6", "app_dir/lib/libQt6DBus.so.6")
|
|
|
|
|
|
|
|
verbose_copy("templates/linux_run_script.sh", "app_dir/" + app_target + ".sh")
|
|
|
|
verbose_copy("templates/linux_uninstall.sh", "app_dir/uninstall.sh")
|
2024-04-21 08:03:30 -04:00
|
|
|
verbose_copy("templates/linux_service.service", "app_dir/" + app_target + ".service")
|
2024-04-10 20:51:56 -04:00
|
|
|
|
|
|
|
complete(app_ver, app_target)
|
|
|
|
|
|
|
|
def complete(app_ver, app_target):
|
|
|
|
print("Build complete for version: " + app_ver)
|
|
|
|
print("You can now run the install.py script to install onto this machine or create an installer.")
|
|
|
|
|
|
|
|
def get_like_distro():
|
|
|
|
info = platform.freedesktop_os_release()
|
|
|
|
ids = [info["ID"]]
|
|
|
|
|
|
|
|
if "ID_LIKE" in info:
|
|
|
|
# ids are space separated and ordered by precedence
|
|
|
|
ids.extend(info["ID_LIKE"].split())
|
|
|
|
|
|
|
|
return ids
|
|
|
|
|
|
|
|
def list_installed_packages():
|
|
|
|
like_distro = get_like_distro()
|
|
|
|
|
|
|
|
if ("ubuntu" in like_distro) or ("debian" in like_distro) or ("linuxmint" in like_distro):
|
|
|
|
return str(subprocess.check_output(["apt", "list", "--installed"]), 'utf-8')
|
|
|
|
|
|
|
|
elif ("fedora" in like_distro) or ("rhel" in like_distro):
|
|
|
|
return str(subprocess.check_output(["dnf", "list", "installed"]), 'utf-8')
|
|
|
|
|
|
|
|
elif ("arch" in like_distro):
|
|
|
|
return str(subprocess.check_output(["pacman", "-Q"]), 'utf-8')
|
|
|
|
|
|
|
|
else:
|
|
|
|
print("Warning: unable to determine a package manager for this platform.")
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
def list_of_words_in_text(list_of_words, text_body):
|
|
|
|
for word in list_of_words:
|
|
|
|
if not word in text_body:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
2024-04-21 08:03:30 -04:00
|
|
|
|
|
|
|
def user_exists(user_name):
|
|
|
|
try:
|
|
|
|
pwd.getpwnam(user_name)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
except KeyError:
|
|
|
|
return False
|
2024-04-10 20:51:56 -04:00
|
|
|
|
|
|
|
def platform_setup():
|
|
|
|
ins_packages = list_installed_packages()
|
|
|
|
like_distro = get_like_distro()
|
|
|
|
dep_pkgs_a = ["pkg-config", "make", "g++"]
|
|
|
|
dep_pkgs_b = ["ffmpeg", "libfuse-dev", "fuse3", "imagemagick"]
|
|
|
|
|
|
|
|
if not list_of_words_in_text(dep_pkgs_a, ins_packages) or not list_of_words_in_text(dep_pkgs_b, ins_packages):
|
|
|
|
if ("ubuntu" in like_distro) or ("debian" in like_distro) or ("linuxmint" in like_distro):
|
|
|
|
subprocess.run(["sudo", "apt", "update", "-y"])
|
|
|
|
subprocess.run(["sudo", "apt", "install", "-y"] + dep_pkgs_a)
|
|
|
|
subprocess.run(["sudo", "apt", "install", "-y"] + dep_pkgs_b)
|
|
|
|
|
|
|
|
elif ("fedora" in like_distro) or ("rhel" in like_distro):
|
|
|
|
subprocess.run(["sudo", "dnf", "install", "-y"] + dep_pkgs_a)
|
|
|
|
subprocess.run(["sudo", "dnf", "install", "-y"] + dep_pkgs_b)
|
|
|
|
|
|
|
|
elif ("arch" in like_distro):
|
|
|
|
subprocess.run(["sudo", "pacman", "-S", "--noconfirm"] + dep_pkgs_a)
|
|
|
|
subprocess.run(["sudo", "pacman", "-S", "--noconfirm"] + dep_pkgs_b)
|
|
|
|
|
2024-04-21 08:03:30 -04:00
|
|
|
if not user_exists("jmotion"):
|
|
|
|
subprocess.run(["sudo", "useradd", "-r", "jmotion"])
|
|
|
|
subprocess.run(["sudo", "usermod", "-aG", "video", "jmotion"])
|
|
|
|
|
2024-04-10 20:51:56 -04:00
|
|
|
def main():
|
|
|
|
platform_setup()
|
|
|
|
|
|
|
|
with open(get_ver_header()) as file:
|
|
|
|
text = file.read()
|
|
|
|
|
|
|
|
app_target = get_app_target(text)
|
|
|
|
app_ver = get_app_ver(text)
|
|
|
|
app_name = get_app_name(text)
|
|
|
|
qt_bin = get_qt_from_cli()
|
|
|
|
|
|
|
|
if qt_bin == "":
|
|
|
|
qt_bin = get_qt_path()
|
|
|
|
|
|
|
|
if qt_bin != "":
|
|
|
|
print("app_target = " + app_target)
|
|
|
|
print("app_version = " + app_ver)
|
|
|
|
print("app_name = " + app_name)
|
|
|
|
print("qt_bin = " + qt_bin)
|
|
|
|
|
|
|
|
cd()
|
|
|
|
|
|
|
|
result = subprocess.run([qt_bin + os.sep + "qmake", "-config", "release"])
|
|
|
|
|
|
|
|
if result.returncode == 0:
|
|
|
|
result = subprocess.run(["make"])
|
|
|
|
|
|
|
|
if result.returncode == 0:
|
|
|
|
if os.path.exists("app_dir"):
|
|
|
|
shutil.rmtree("app_dir")
|
|
|
|
|
|
|
|
os.makedirs("app_dir")
|
|
|
|
|
|
|
|
with open("app_dir" + os.sep + "info.txt", "w") as info_file:
|
|
|
|
info_file.write(app_target + "\n")
|
|
|
|
info_file.write(app_ver + "\n")
|
|
|
|
info_file.write(app_name + "\n")
|
|
|
|
|
|
|
|
linux_build_app_dir(app_ver, app_name, app_target, qt_bin)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|