mirror of
https://github.com/SynologyOpenSource/pkgscripts-ng.git
synced 2025-07-25 17:10:06 +00:00
299 lines
8.3 KiB
Python
299 lines
8.3 KiB
Python
#!/usr/bin/python3
|
|
# Copyright (c) 2000-2020 Synology Inc. All rights reserved.
|
|
|
|
import os
|
|
import glob
|
|
import subprocess
|
|
import tempfile
|
|
import shutil
|
|
import re
|
|
from subprocess import CalledProcessError
|
|
|
|
ScriptDir = os.path.realpath(os.path.dirname(__file__) + '/../../')
|
|
ScriptDirName = os.path.basename(ScriptDir)
|
|
SynoBase = os.path.dirname(ScriptDir)
|
|
SourceDir = SynoBase + "/source"
|
|
|
|
__IsPkgEnv = True
|
|
|
|
VIRTUAL_PROJECT_SEPARATOR = "-virtual-"
|
|
VIRINST_PROJECT_SEPARATOR = "-virinst-"
|
|
ConfDir = 'SynoBuildConf'
|
|
ProjectDependsName = "ProjectDepends.py"
|
|
|
|
__PkgEnvVersion = None
|
|
|
|
Prefix = SynoBase
|
|
|
|
|
|
def setEnvironmentVersion(version):
|
|
global __PkgEnvVersion
|
|
__PkgEnvVersion = version
|
|
|
|
|
|
def inChroot():
|
|
return os.path.isfile('/root/.chroot')
|
|
|
|
|
|
class Project:
|
|
def __init__(self, proj, allow_missing=False):
|
|
self.proj = proj
|
|
self.allow_missing = allow_missing
|
|
|
|
if inChroot():
|
|
project_src = deVirInst(self.proj)
|
|
else:
|
|
project_src = deVirtual(deVirInst(self.proj))
|
|
|
|
self.__project_dir = os.path.join(SourceDir, project_src)
|
|
|
|
@property
|
|
def build_script(self):
|
|
return self.__find_script('build')
|
|
|
|
@property
|
|
def install_script(self):
|
|
return self.__find_script('install')
|
|
|
|
@property
|
|
def installdev_script(self):
|
|
return self.__find_script('install-dev')
|
|
|
|
@property
|
|
def error_script(self):
|
|
return self.__find_script('error')
|
|
|
|
@property
|
|
def depends_script(self):
|
|
return self.__find_script('depends')
|
|
|
|
def settings(self, chroot=None):
|
|
return self.__find_script('settings', chroot)
|
|
|
|
|
|
def info(self, chroot=None):
|
|
return os.path.join(self.project_dir(chroot), 'INFO')
|
|
|
|
def project_dir(self, chroot=None):
|
|
project_dir = self.__project_dir
|
|
if chroot:
|
|
project_dir = os.path.join(chroot, os.path.basename(SourceDir), self.proj)
|
|
return project_dir
|
|
|
|
def __find_script(self, script_type, chroot=None):
|
|
for proj_name in [self.proj, self.proj.split("-32")[0], self.proj.split("-virtual-32")[0]]:
|
|
virtual_name = getVirtualProjectExtension(proj_name)
|
|
|
|
script = os.path.join(self.project_dir(chroot), ConfDir, script_type + virtual_name)
|
|
if os.path.isfile(script) or os.path.islink(script):
|
|
return script
|
|
|
|
if self.allow_missing:
|
|
return os.path.join(self.project_dir(chroot), ConfDir, script_type)
|
|
else:
|
|
return ""
|
|
|
|
|
|
class Chroot():
|
|
__platform = None
|
|
__version = None
|
|
|
|
def __init__(self, platform, version=None):
|
|
self.__platform = platform
|
|
self.__version = version
|
|
|
|
def MountProc(self):
|
|
return MountProc(self.__platform, self.__version)
|
|
|
|
def SynoBuild(self, args, **kwargs):
|
|
return executeChrootScript(self.__platform, "SynoBuild", ["--" + self.__platform] + args, self.__version, **kwargs)
|
|
|
|
def SynoInstall(self, args, **kwargs):
|
|
return executeChrootScript(self.__platform, "SynoInstall", ["--" + self.__platform] + args, self.__version, **kwargs)
|
|
|
|
def GetSynoBase(self):
|
|
return getChrootSynoBase(self.__platform, self.__version)
|
|
|
|
def GetSourceDir(self):
|
|
return getChrootSourceDir(self.__platform, self.__version)
|
|
|
|
def GetScriptDir(self):
|
|
return self.GetSynoBase() + "/" + ScriptDirName
|
|
|
|
def ExecuteCommand(self, cmd):
|
|
return executeChrootCommand(self.__platform, cmd, self.__version)
|
|
|
|
def ExecuteScript(self, script, args, **kwargs):
|
|
return executeChrootScript(self.__platform, script, args, self.__version, **kwargs)
|
|
|
|
def LinkProject(self, proj):
|
|
return LinkProject(proj, self.__platform, self.__version)
|
|
|
|
def LinkScript(self):
|
|
return LinkScript(self.__platform, self.__version)
|
|
|
|
|
|
class PlatformNotFoundException(RuntimeError):
|
|
pass
|
|
|
|
|
|
class BuildFailedError(RuntimeError):
|
|
pass
|
|
|
|
|
|
def getIncludeVariable(include_file, variable):
|
|
return subprocess.check_output(
|
|
'source %s/include/init; source %s/include/%s; echo $%s' % (ScriptDir, ScriptDir, include_file, variable),
|
|
shell=True,
|
|
executable='/bin/bash'
|
|
).decode().strip()
|
|
|
|
|
|
def getChrootSynoBase(platform, version=None, suffix=None):
|
|
if __IsPkgEnv:
|
|
env = 'build_env'
|
|
if suffix:
|
|
env += "-" + suffix
|
|
if version is None:
|
|
version = __PkgEnvVersion
|
|
return os.path.join(SynoBase, env, 'ds.'+platform+'-'+version)
|
|
return Prefix + '/ds.' + platform
|
|
|
|
|
|
def getChrootSourceDir(platform, version=None):
|
|
return getChrootSynoBase(platform, version) + "/source"
|
|
|
|
|
|
def executeChrootScript(platform, script, args, version=None, **kwargs):
|
|
envOpt = []
|
|
if 'env' in kwargs:
|
|
envOpt = ['env']
|
|
for k in kwargs['env']:
|
|
envOpt.append("%s=%s" % (k, kwargs['env'][k]))
|
|
|
|
return subprocess.check_call(
|
|
["chroot", getChrootSynoBase(platform, version)] + envOpt + ["/" + ScriptDirName + "/" + script] + args)
|
|
|
|
|
|
def executeChrootCommand(platform, cmd, version=None):
|
|
return subprocess.check_output(
|
|
["chroot", getChrootSynoBase(platform, version)] + cmd).decode()
|
|
|
|
|
|
def executeScript(script, args, **kwargs):
|
|
if "suppressOutput" in kwargs and kwargs["suppressOutput"]:
|
|
kwargs.pop("suppressOutput")
|
|
with open(os.devnull, "w") as null:
|
|
return subprocess.check_call([ScriptDir + "/" + script] + args, stdout=null, stderr=null, **kwargs)
|
|
else:
|
|
return subprocess.check_call([ScriptDir + "/" + script] + args, **kwargs)
|
|
|
|
|
|
def ProjectDepends(args):
|
|
return subprocess.check_output([ScriptDir + "/" + ProjectDependsName] + args).decode().rstrip().split()
|
|
|
|
|
|
|
|
def SynoBuild(platform, args, version=None):
|
|
try:
|
|
return executeChrootScript(platform, "SynoBuild", args, version)
|
|
except CalledProcessError:
|
|
raise BuildFailedError("Failed to SynoBuild(%s) on platform %s" % (str(args), platform))
|
|
|
|
|
|
def getList(listName):
|
|
ret = []
|
|
for config in ["projects", "config"]:
|
|
if os.path.exists(os.path.join(ScriptDir, 'include', config)):
|
|
ret = getIncludeVariable(config, listName).split()
|
|
|
|
if ret:
|
|
return ret
|
|
|
|
return None
|
|
|
|
def getPlatformVariable(platform, var):
|
|
return getIncludeVariable('platform.' + platform, var)
|
|
|
|
|
|
def isVirtualProject(proj):
|
|
return VIRTUAL_PROJECT_SEPARATOR in proj
|
|
|
|
|
|
def isVirInstProject(proj):
|
|
return VIRINST_PROJECT_SEPARATOR in proj
|
|
|
|
|
|
def deVirtual(proj):
|
|
return proj.split(VIRTUAL_PROJECT_SEPARATOR)[0]
|
|
|
|
|
|
def deVirInst(proj):
|
|
return proj.split(VIRINST_PROJECT_SEPARATOR)[0]
|
|
|
|
|
|
def getBasedProject(proj):
|
|
return deVirtual(deVirInst(proj))
|
|
|
|
|
|
def getVirtualName(proj):
|
|
if isVirtualProject(proj):
|
|
return proj.split(VIRTUAL_PROJECT_SEPARATOR)[1]
|
|
else:
|
|
return ""
|
|
|
|
|
|
def getVirInstName(proj):
|
|
if isVirInstProject(proj):
|
|
return proj.split(VIRINST_PROJECT_SEPARATOR)[1]
|
|
else:
|
|
return ""
|
|
|
|
|
|
def getVirtualProjectExtension(proj):
|
|
if isVirtualProject(proj):
|
|
return VIRTUAL_PROJECT_SEPARATOR + getVirtualName(proj)
|
|
if isVirInstProject(proj):
|
|
return VIRINST_PROJECT_SEPARATOR + getVirInstName(proj)
|
|
|
|
return ""
|
|
|
|
|
|
def EnvDeploy(args, **kwargs):
|
|
try:
|
|
return executeScript("EnvDeploy", args, **kwargs)
|
|
except CalledProcessError:
|
|
raise RuntimeError("Failed to EnvDeploy(%s) on " % str(args))
|
|
|
|
|
|
def PkgCreate(args, **kwargs):
|
|
try:
|
|
return executeScript("PkgCreate.py", args, **kwargs)
|
|
except CalledProcessError:
|
|
raise BuildFailedError("Failed to PkgCreate(%s) on " % str(args))
|
|
|
|
def __linkFolder(src, tgt):
|
|
if os.path.exists(tgt):
|
|
shutil.rmtree(tgt)
|
|
|
|
print("Link " + src + " -> " + tgt)
|
|
return subprocess.check_call(["cp", "-al", src, tgt])
|
|
|
|
|
|
def LinkProject(proj, platform, version=None):
|
|
return __linkFolder(SourceDir + "/" + deVirtual(proj), getChrootSourceDir(platform, version) + "/" + proj)
|
|
|
|
|
|
def LinkScript(platform, version=None):
|
|
return __linkFolder(ScriptDir, getChrootSynoBase(platform, version) + "/" + ScriptDirName)
|
|
|
|
|
|
def MountProc(platform, version=None):
|
|
mountpoint = getChrootSynoBase(platform, version) + "/proc"
|
|
if not os.path.ismount(mountpoint):
|
|
subprocess.check_call("mount -t proc none " + getChrootSynoBase(platform, version) + "/proc",
|
|
shell=True)
|
|
|
|
def get_namespace():
|
|
return os.path.basename(Prefix)
|