2024-06-19 16:48:18 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
2024-01-19 14:44:50 +00:00
|
|
|
import os
|
2024-06-19 16:48:18 +00:00
|
|
|
from lib import windows, cmd_utils
|
2024-01-19 14:44:50 +00:00
|
|
|
import sys
|
|
|
|
|
import argparse
|
2024-06-14 15:32:47 +00:00
|
|
|
import traceback
|
|
|
|
|
|
|
|
|
|
config_file = "deps.yml"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class YamlError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PlatformError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PathError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import yaml # type: ignore
|
|
|
|
|
except ImportError:
|
|
|
|
|
# this is fairly common in earlier versions of python3,
|
|
|
|
|
# which is normally what you find on mac and windows.
|
|
|
|
|
print("Python yaml module missing, please install: pip install pyyaml")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
2024-01-19 14:44:50 +00:00
|
|
|
|
|
|
|
|
def main():
|
2024-06-14 15:32:47 +00:00
|
|
|
"""Entry point for the script."""
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--pause-on-exit", action="store_true", help="Useful on Windows"
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--only", type=str, help="Only install the specified dependency"
|
|
|
|
|
)
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
deps = Dependencies(args.only)
|
|
|
|
|
deps.install()
|
|
|
|
|
except Exception:
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
if args.pause_on_exit:
|
|
|
|
|
input("Press enter to continue...")
|
|
|
|
|
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def get_os():
|
|
|
|
|
"""Detects the operating system."""
|
|
|
|
|
if sys.platform == "win32":
|
|
|
|
|
return "windows"
|
|
|
|
|
elif sys.platform == "darwin":
|
|
|
|
|
return "mac"
|
|
|
|
|
elif sys.platform.startswith("linux"):
|
|
|
|
|
return "linux"
|
2024-01-19 14:44:50 +00:00
|
|
|
else:
|
2024-06-14 15:32:47 +00:00
|
|
|
raise PlatformError(f"Unsupported platform: {sys.platform}")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
|
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def get_linux_distro():
|
|
|
|
|
"""Detects the Linux distro."""
|
|
|
|
|
os_file = "/etc/os-release"
|
|
|
|
|
if os.path.isfile(os_file):
|
|
|
|
|
with open(os_file) as f:
|
|
|
|
|
for line in f:
|
|
|
|
|
if line.startswith("ID="):
|
|
|
|
|
return line.strip().split("=")[1].strip('"')
|
|
|
|
|
return None
|
2024-01-19 14:44:50 +00:00
|
|
|
|
|
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
class Config:
|
|
|
|
|
"""Reads the dependencies configuration file."""
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def __init__(self):
|
|
|
|
|
with open(config_file, "r") as f:
|
|
|
|
|
data = yaml.safe_load(f)
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
os_name = get_os()
|
|
|
|
|
try:
|
|
|
|
|
root = data["dependencies"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} for: dependencies")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
try:
|
|
|
|
|
self.os = root[os_name]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} for: {os_name}")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def get_qt_config(self):
|
|
|
|
|
try:
|
|
|
|
|
return self.os["qt"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} for: qt")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def get_packages_file(self):
|
|
|
|
|
try:
|
|
|
|
|
return self.os["packages"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} for: packages")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
def get_linux_package_command(self, distro):
|
|
|
|
|
try:
|
|
|
|
|
distro_data = self.os[distro]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} for: {distro}")
|
2024-01-19 14:44:50 +00:00
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
try:
|
|
|
|
|
command_base = distro_data["command"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"No package command found in {config_file} for: {distro}")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
package_data = distro_data["packages"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"No package list found in {config_file} for: {distro}")
|
|
|
|
|
|
|
|
|
|
packages = " ".join(package_data)
|
|
|
|
|
return f"{command_base} {packages}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Dependencies:
|
|
|
|
|
|
|
|
|
|
def __init__(self, only):
|
|
|
|
|
self.config = Config()
|
|
|
|
|
self.only = only
|
|
|
|
|
|
|
|
|
|
def install(self):
|
|
|
|
|
"""Installs dependencies for the current platform."""
|
|
|
|
|
|
|
|
|
|
os = get_os()
|
|
|
|
|
if os == "windows":
|
|
|
|
|
self.windows()
|
|
|
|
|
elif os == "mac":
|
|
|
|
|
self.mac()
|
|
|
|
|
elif os == "linux":
|
|
|
|
|
self.linux()
|
|
|
|
|
else:
|
|
|
|
|
raise PlatformError(f"Unsupported platform: {os}")
|
|
|
|
|
|
|
|
|
|
def windows(self):
|
|
|
|
|
"""Installs dependencies on Windows."""
|
|
|
|
|
|
|
|
|
|
if not windows.is_admin():
|
|
|
|
|
windows.relaunch_as_admin(__file__)
|
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
|
|
ci_env = os.environ.get("CI")
|
|
|
|
|
if ci_env:
|
|
|
|
|
print("CI environment detected")
|
|
|
|
|
|
|
|
|
|
only_qt = self.only == "qt"
|
|
|
|
|
|
|
|
|
|
# for ci, skip qt; we install qt separately so we can cache it.
|
|
|
|
|
if not ci_env or only_qt:
|
2024-06-19 16:48:18 +00:00
|
|
|
qt = windows.WindowsQt(self.config.get_qt_config(), config_file)
|
2024-06-14 15:32:47 +00:00
|
|
|
qt_install_dir = qt.get_install_dir()
|
|
|
|
|
if qt_install_dir:
|
|
|
|
|
print(f"Skipping Qt, already installed at: {qt_install_dir}")
|
|
|
|
|
else:
|
|
|
|
|
qt.install()
|
|
|
|
|
|
|
|
|
|
if only_qt:
|
|
|
|
|
return
|
|
|
|
|
|
2024-06-19 16:48:18 +00:00
|
|
|
choco = windows.WindowsChoco()
|
2024-06-14 15:32:47 +00:00
|
|
|
if ci_env:
|
|
|
|
|
choco.config_ci_cache()
|
|
|
|
|
|
2024-06-19 16:48:18 +00:00
|
|
|
try:
|
|
|
|
|
ci_skip = self.config.os["ci"]["skip"]
|
|
|
|
|
choco_config_file = ci_skip["edit-config"]
|
|
|
|
|
remove_packages = ci_skip["packages"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Bad mapping in {config_file} on Windows for: ci")
|
|
|
|
|
|
|
|
|
|
choco.remove_from_config(choco_config_file, remove_packages)
|
|
|
|
|
|
2024-06-14 15:32:47 +00:00
|
|
|
try:
|
|
|
|
|
command = self.config.os["command"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} on Windows for: command")
|
|
|
|
|
|
|
|
|
|
choco.install(command, ci_env)
|
|
|
|
|
|
|
|
|
|
def mac(self):
|
|
|
|
|
"""Installs dependencies on macOS."""
|
|
|
|
|
try:
|
|
|
|
|
command = self.config.os["command"]
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise YamlError(f"Nothing found in {config_file} on Mac for: command")
|
|
|
|
|
|
2024-06-19 16:48:18 +00:00
|
|
|
cmd_utils.run(command)
|
2024-06-14 15:32:47 +00:00
|
|
|
|
|
|
|
|
def linux(self):
|
|
|
|
|
"""Installs dependencies on Linux."""
|
|
|
|
|
|
|
|
|
|
distro = get_linux_distro()
|
|
|
|
|
if not distro:
|
|
|
|
|
raise PlatformError("Unable to detect Linux distro")
|
|
|
|
|
|
|
|
|
|
command = self.config.get_linux_package_command(distro)
|
2024-06-19 16:48:18 +00:00
|
|
|
cmd_utils.run(command)
|
2024-01-19 14:44:50 +00:00
|
|
|
|
|
|
|
|
|
2024-06-19 16:48:18 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|