blob: 8846367c2e2a9a5492c332ea5749e0dedb020138 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (C) 2020-2021 Savoir-faire Linux Inc.
#
# Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Creates packaging targets for a distribution and architecture.
# This helps reduce the length of the top Makefile.
#
import os
import sys
import shutil
import typing
import argparse
import platform
import subprocess
from zipfile import ZipFile
from sdkConstants import OS_IDS
def getSystem():
system = platform.system().lower()
if system == "linux" or system == "linux2":
return OS_IDS["Linux"]
elif system == "darwin":
return OS_IDS["Darwin"]
elif system == "windows":
return OS_IDS["Windows"]
sys.exit("Plugins SDK not supported on this system")
def getJpls():
filePaths = input("\nInput jpls path you want to merge:\n")
filePaths = filePaths.replace(' ', ',').replace(",,", ',')
filePaths = filePaths.split(',')
if (len(filePaths) > 0):
print("\nJpl files to merge:")
for filePath in filePaths:
print(filePath)
return filePaths
def checkValidityJpls(filePaths):
for filePath in filePaths:
if (not os.path.exists(filePath) or not filePath.endswith(".jpl")):
return False
return True
class JPLStructure:
def __init__(self, paths, output = "", is_merge = True):
self.paths = paths
self.outputName = output
self.pluginNames = []
self.ZipObjcts: typing.Dict[str, list[ZipFile]] = {}
if is_merge:
self.getOutName()
self.discoverJPLs()
if is_merge:
self.mergeJPLs()
def getOutName(self):
while (not self.outputName or not self.outputName.endswith(".jpl")):
self.outputName = input("\nWhere to save the resulting JPL? ")
self.OutObj = ZipFile(self.outputName, 'w')
def discoverJPLs(self):
for path in self.paths:
name = os.path.split(path)[0].split('.')[0]
self.pluginNames.append(name)
self.ZipObjcts[path] = []
self.ZipObjcts[path].append(ZipFile(path, 'r'))
return
def mergeJPLs(self):
self.fileNames = []
for path in self.paths:
[obj] = self.ZipObjcts[path]
for item in obj.filelist:
if item.filename not in self.fileNames:
self.OutObj.writestr(item, obj.open(item).read())
self.fileNames.append(item.filename)
self.OutObj.close()
def onerror(func, path, exc_info):
"""
Error handler for ``shutil.rmtree``.
If the error is due to an access error (read only file)
it attempts to add write permission and then retries.
If the error is for another reason it re-raises the error.
Usage : ``shutil.rmtree(path, onerror=onerror)``
"""
import stat
if not os.access(path, os.W_OK):
# Is the error an access error ?
os.chmod(path, stat.S_IWUSR)
func(path)
else:
raise
def preAssemble(pluginName, distribution=''):
localSystem = getSystem()
osBuildPath = "build-local"
if localSystem == OS_IDS["Linux"]:
if (distribution != 'android'):
distribution = "x86_64-linux-gnu"
elif localSystem == OS_IDS["Darwin"]:
distribution = "x86_64-apple-Darwin"
elif localSystem == OS_IDS["Windows"]:
distribution = "x64-windows"
osBuildPath = "msvc"
chDir = False
if (osBuildPath in os.getcwd()):
chDir = True
os.chdir("./../")
if (os.path.exists(f"./../{pluginName}/{osBuildPath}/")):
if (os.path.exists(f"./../{pluginName}/{osBuildPath}/jpl")):
shutil.rmtree(f"./../{pluginName}/{osBuildPath}/jpl", onerror=onerror)
else:
os.mkdir(f"./../{pluginName}/{osBuildPath}")
os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl")
os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib")
if (distribution != 'android'):
os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{distribution}")
else:
if ("ANDROID_ABI" in os.environ.keys()):
for abi in os.environ["ANDROID_ABI"].split(' '):
os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{abi}")
shutil.copytree(f"./../{pluginName}/data/",
f"./../{pluginName}/{osBuildPath}/jpl/data/")
shutil.copyfile(f"./../{pluginName}/manifest.json",
f"./../{pluginName}/{osBuildPath}/jpl/manifest.json")
if (os.path.exists(f"./../{pluginName}/data/preferences.json")):
shutil.copyfile(
f"./../{pluginName}/data/preferences.json",
f"./../{pluginName}/{osBuildPath}/jpl/data/preferences.json")
if (chDir):
os.chdir(f"./{osBuildPath}")
def assemble(pluginName, extraPath='', distribution=''):
extraPath = '/' + extraPath
localSystem = getSystem()
root = os.path.dirname(os.path.abspath(__file__)) + "/.."
osBuildPath = "build-local"
if localSystem == OS_IDS["Linux"]:
if (distribution != 'android'):
distribution = "x86_64-linux-gnu"
elif localSystem == OS_IDS["Darwin"]:
distribution = "x86_64-apple-Darwin"
elif localSystem == OS_IDS["Windows"]:
distribution = "x64-windows"
osBuildPath = 'msvc'
if (not os.path.exists(f"{root}/build")):
os.mkdir(f"{root}/build")
if (not os.path.exists(f"{root}/build/{distribution}")):
os.mkdir(f"{root}/build/{distribution}")
if (not os.path.exists(f"{root}/build/{distribution}{extraPath}")):
os.mkdir(f"{root}/build/{distribution}{extraPath}")
if (os.path.exists(f"./../build/{pluginName}.jpl")):
os.remove(f"./../build/{pluginName}.jpl")
outputJPL = f"{root}/build/{distribution}{extraPath}/{pluginName}.jpl"
outputBuild = f"{root}/{pluginName}/{osBuildPath}/jpl"
with ZipFile(outputJPL, 'w') as zipObj:
for folderName, subfolders, filenames in os.walk(outputBuild):
for filename in filenames:
filePath = os.path.join(folderName, filename)
zipObj.write(
filePath, f"{folderName.split('/jpl')[-1]}/{filename}")
zipObj.close()
def build(pluginName):
currentDir = os.getcwd()
os.chdir('./../')
subprocess.run([
sys.executable, os.path.join(
os.getcwd(), "build-plugin.py"),
"--projects", pluginName
], check=True)
os.chdir(currentDir)
def parser():
parser = argparse.ArgumentParser(description='Build some plugins.')
parser.add_argument('--plugin', type=str,
help='Name of plugin to be build')
parser.add_argument('--extraPath', type=str, default="",
help='output intermediate Path')
parser.add_argument('--distribution', type=str, default='',
help="GNU/Linux or Windows, leave empty. Android, type android")
# to build or not to build
parser.add_argument('--build', action='store_true')
# to preassemble or not
parser.add_argument('--preassemble', action='store_true')
# to assemble jpl or not
parser.add_argument('--assemble', action='store_true')
# to assemble jpl or not
parser.add_argument('--merge', action='store_true')
# to merge two or more jpl
parser.add_argument('--path', nargs='*', required=False,
help="Jpl full path")
parser.add_argument('--output', type=str, default='',
help="Jpl output full path")
args = parser.parse_args()
return args
def main():
args = parser()
if args.preassemble:
preAssemble(args.plugin, args.distribution)
if (args.build):
build(args.plugin)
if (args.assemble):
assemble(args.plugin, args.extraPath, args.distribution)
if (args.merge):
JPLStructure(args.path, args.output)
if __name__ == '__main__':
main()