| #!/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() |