blob: 558760a8159c3c00f7d93231e831423a1f1796e6 [file] [log] [blame]
agsantos1e7736c2020-10-28 14:39:13 -04001#!/usr/bin/env python3
2#
3# Copyright (C) 2020 Savoir-faire Linux Inc.
4#
5# Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20# Creates packaging targets for a distribution and architecture.
21# This helps reduce the length of the top Makefile.
22#
23
24import os
25import sys
26import shutil
27import argparse
28import platform
29import subprocess
30from zipfile import ZipFile
31
32from sdkConstants import OS_IDS
33
34
35def getSystem():
36 system = platform.system().lower()
37 if system == "linux" or system == "linux2":
38 return OS_IDS["Linux"]
39 elif system == "darwin":
40 sys.exit("Plugins not supported on MacOS and IOS")
41 elif system == "windows":
42 return OS_IDS["Windows"]
43 sys.exit("Plugins SDK not supported on this system")
44
45
46def getJpls():
47 filePaths = input("\nInput jpls path you want to merge:\n")
48 filePaths = filePaths.replace(' ', ',').replace(",,", ',')
49 filePaths = filePaths.split(',')
50 if (len(filePaths) > 0):
51 print("\nJpl files to merge:")
52 for filePath in filePaths:
53 print(filePath)
54 return filePaths
55
56
57def checkValidityJpls(filePaths):
58 for filePath in filePaths:
59 if (not os.path.exists(filePath) or not filePath.endswith(".jpl")):
60 return False
61 return True
62
63
64class JPLStructure:
65 def __init__(self, paths):
66 self.paths = paths
67 self.outputName = ''
68 self.pluginNames = []
69 self.ZipObjcts = {}
70 self.getOutName()
71 self.discoverJPLs()
72 self.mergeJPLs()
73
74 def getOutName(self):
75 while (not self.outputName or not self.outputName.endswith(".jpl")):
76 self.outputName = input("\nWhere save the resulting JPL? ")
77 self.OutObj = ZipFile(self.outputName, 'w')
78
79 def discoverJPLs(self):
80 for path in self.paths:
81 name = os.path.split(path)[0].split('.')[0]
82 self.pluginNames.append(name)
83 self.ZipObjcts[path] = []
84 self.ZipObjcts[path].append(ZipFile(path, 'r'))
85 return
86
87 def mergeJPLs(self):
88 self.fileNames = []
89 for path in self.paths:
90 [obj] = self.ZipObjcts[path]
91 for item in obj.filelist:
92 if item.filename not in self.fileNames:
93 self.OutObj.writestr(item, obj.open(item).read())
94 self.fileNames.append(item.filename)
95 self.OutObj.close()
96
97
98def onerror(func, path, exc_info):
99 """
100 Error handler for ``shutil.rmtree``.
101
102 If the error is due to an access error (read only file)
103 it attempts to add write permission and then retries.
104
105 If the error is for another reason it re-raises the error.
106
107 Usage : ``shutil.rmtree(path, onerror=onerror)``
108 """
109 import stat
110 if not os.access(path, os.W_OK):
111 # Is the error an access error ?
112 os.chmod(path, stat.S_IWUSR)
113 func(path)
114 else:
115 raise
116
117
118def preAssemble(pluginName, distribution=''):
119 localSystem = getSystem()
120
121 osBuildPath = "build-local"
122 if localSystem == OS_IDS["Linux"]:
123 if (distribution != 'android'):
124 distribution = "x86_64-linux-gnu"
125 elif localSystem == OS_IDS["Darwin"]:
126 sys.exit("Plugins not supported on MacOS and IOS")
127 elif localSystem == OS_IDS["Windows"]:
128 distribution = "x64-windows"
129 osBuildPath = "msvc"
130
131 chDir = False
132 if (osBuildPath in os.getcwd()):
133 chDir = True
134 os.chdir("./../")
135 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/")):
136 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/jpl")):
137 shutil.rmtree(f"./../{pluginName}/{osBuildPath}/jpl", onerror=onerror)
138 else:
139 os.mkdir(f"./../{pluginName}/{osBuildPath}")
140 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl")
141 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib")
142 if (distribution != 'android'):
143 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{distribution}")
144 else:
145 if ("ANDROID_ABI" in os.environ.keys()):
146 for abi in os.environ["ANDROID_ABI"].split(' '):
147 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{abi}")
148
149 shutil.copytree(f"./../{pluginName}/data/",
150 f"./../{pluginName}/{osBuildPath}/jpl/data/")
151 shutil.copyfile(f"./../{pluginName}/manifest.json",
152 f"./../{pluginName}/{osBuildPath}/jpl/manifest.json")
153 if (os.path.exists(f"./../{pluginName}/data/preferences.json")):
154 shutil.copyfile(
155 f"./../{pluginName}/data/preferences.json",
156 f"./../{pluginName}/{osBuildPath}/jpl/data/preferences.json")
157 if (chDir):
158 os.chdir(f"./{osBuildPath}")
159
160
161def assemble(pluginName, extraPath='', distribution=''):
162 extraPath = '/' + extraPath
163 localSystem = getSystem()
164 root = os.path.dirname(os.path.abspath(__file__)) + "/.."
165 osBuildPath = "build-local"
166
167 if localSystem == OS_IDS["Linux"]:
168 if (distribution != 'android'):
169 distribution = "x86_64-linux-gnu"
170 elif localSystem == OS_IDS["Darwin"]:
171 sys.exit("Plugins not supported on MacOS and IOS")
172 elif localSystem == OS_IDS["Windows"]:
173 distribution = "x64-windows"
174 osBuildPath = 'msvc'
175 if (not os.path.exists(f"{root}/build")):
176 os.mkdir(f"{root}/build")
177 if (not os.path.exists(f"{root}/build/{distribution}")):
178 os.mkdir(f"{root}/build/{distribution}")
179 if (not os.path.exists(f"{root}/build/{distribution}{extraPath}")):
180 os.mkdir(f"{root}/build/{distribution}{extraPath}")
181 if (os.path.exists(f"./../build/{pluginName}.jpl")):
182 os.remove(f"./../build/{pluginName}.jpl")
183
184 outputJPL = f"{root}/build/{distribution}{extraPath}/{pluginName}.jpl"
185 outputBuild = f"{root}/{pluginName}/{osBuildPath}/jpl"
186
187 with ZipFile(outputJPL, 'w') as zipObj:
188 for folderName, subfolders, filenames in os.walk(outputBuild):
189 for filename in filenames:
190 filePath = os.path.join(folderName, filename)
191 zipObj.write(
192 filePath, f"{folderName.split('/jpl')[-1]}/{filename}")
193 zipObj.close()
194
195
196def build(pluginName):
197 currentDir = os.getcwd()
198 os.chdir('./../')
199 subprocess.run([
200 sys.executable, os.path.join(
201 os.getcwd(), "build-plugin.py"),
202 "--projects", pluginName
203 ], check=True)
204 os.chdir(currentDir)
205
206
207def parser():
208 parser = argparse.ArgumentParser(description='Build some plugins.')
209 parser.add_argument('--plugin', type=str,
210 help='Name of plugin to be build')
211 parser.add_argument('--extraPath', type=str, default="",
212 help='output intermediate Path')
213 parser.add_argument('--distribution', type=str, default='',
214 help="GNU/Linux or Windows, leave empty. Android, type android")
215 # to build or not to build
216 parser.add_argument('--build', action='store_true')
217 parser.add_argument(
218 '--preassemble',
219 action='store_true') # to preassemble or not
220 # to assemble jpl or not
221 parser.add_argument('--assemble', action='store_true')
222
223 args = parser.parse_args()
224 return args
225
226
227def main():
228 args = parser()
229
230 if args.preassemble:
231 preAssemble(args.plugin, args.distribution)
232 if (args.build):
233 build(args.plugin)
234 if (args.assemble):
235 assemble(args.plugin, args.extraPath, args.distribution)
236
237
238if __name__ == '__main__':
239 main()