blob: 8846367c2e2a9a5492c332ea5749e0dedb020138 [file] [log] [blame]
agsantos1e7736c2020-10-28 14:39:13 -04001#!/usr/bin/env python3
2#
Sébastien Blincb783e32021-02-12 11:34:10 -05003# Copyright (C) 2020-2021 Savoir-faire Linux Inc.
agsantos1e7736c2020-10-28 14:39:13 -04004#
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
Xavier Jouslin de Norayd0f1cb42023-06-09 10:02:25 -040027import typing
agsantos1e7736c2020-10-28 14:39:13 -040028import argparse
29import platform
30import subprocess
31from zipfile import ZipFile
32
33from sdkConstants import OS_IDS
34
35
36def getSystem():
37 system = platform.system().lower()
38 if system == "linux" or system == "linux2":
39 return OS_IDS["Linux"]
40 elif system == "darwin":
agsantos1bbc7cc2021-05-20 16:43:35 -040041 return OS_IDS["Darwin"]
agsantos1e7736c2020-10-28 14:39:13 -040042 elif system == "windows":
43 return OS_IDS["Windows"]
44 sys.exit("Plugins SDK not supported on this system")
45
46
47def getJpls():
48 filePaths = input("\nInput jpls path you want to merge:\n")
49 filePaths = filePaths.replace(' ', ',').replace(",,", ',')
50 filePaths = filePaths.split(',')
51 if (len(filePaths) > 0):
52 print("\nJpl files to merge:")
53 for filePath in filePaths:
54 print(filePath)
55 return filePaths
56
57
58def checkValidityJpls(filePaths):
59 for filePath in filePaths:
60 if (not os.path.exists(filePath) or not filePath.endswith(".jpl")):
61 return False
62 return True
63
64
65class JPLStructure:
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040066 def __init__(self, paths, output = "", is_merge = True):
agsantos1e7736c2020-10-28 14:39:13 -040067 self.paths = paths
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -030068 self.outputName = output
agsantos1e7736c2020-10-28 14:39:13 -040069 self.pluginNames = []
Xavier Jouslin de Norayd0f1cb42023-06-09 10:02:25 -040070 self.ZipObjcts: typing.Dict[str, list[ZipFile]] = {}
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040071 if is_merge:
72 self.getOutName()
agsantos1e7736c2020-10-28 14:39:13 -040073 self.discoverJPLs()
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040074 if is_merge:
75 self.mergeJPLs()
agsantos1e7736c2020-10-28 14:39:13 -040076
77 def getOutName(self):
78 while (not self.outputName or not self.outputName.endswith(".jpl")):
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040079 self.outputName = input("\nWhere to save the resulting JPL? ")
agsantos1e7736c2020-10-28 14:39:13 -040080 self.OutObj = ZipFile(self.outputName, 'w')
81
82 def discoverJPLs(self):
83 for path in self.paths:
84 name = os.path.split(path)[0].split('.')[0]
85 self.pluginNames.append(name)
86 self.ZipObjcts[path] = []
87 self.ZipObjcts[path].append(ZipFile(path, 'r'))
88 return
89
90 def mergeJPLs(self):
91 self.fileNames = []
92 for path in self.paths:
93 [obj] = self.ZipObjcts[path]
94 for item in obj.filelist:
95 if item.filename not in self.fileNames:
96 self.OutObj.writestr(item, obj.open(item).read())
97 self.fileNames.append(item.filename)
98 self.OutObj.close()
99
100
101def onerror(func, path, exc_info):
102 """
103 Error handler for ``shutil.rmtree``.
104
105 If the error is due to an access error (read only file)
106 it attempts to add write permission and then retries.
107
108 If the error is for another reason it re-raises the error.
109
110 Usage : ``shutil.rmtree(path, onerror=onerror)``
111 """
112 import stat
113 if not os.access(path, os.W_OK):
114 # Is the error an access error ?
115 os.chmod(path, stat.S_IWUSR)
116 func(path)
117 else:
118 raise
119
120
121def preAssemble(pluginName, distribution=''):
122 localSystem = getSystem()
123
124 osBuildPath = "build-local"
125 if localSystem == OS_IDS["Linux"]:
126 if (distribution != 'android'):
127 distribution = "x86_64-linux-gnu"
128 elif localSystem == OS_IDS["Darwin"]:
agsantos1bbc7cc2021-05-20 16:43:35 -0400129 distribution = "x86_64-apple-Darwin"
agsantos1e7736c2020-10-28 14:39:13 -0400130 elif localSystem == OS_IDS["Windows"]:
131 distribution = "x64-windows"
132 osBuildPath = "msvc"
133
134 chDir = False
135 if (osBuildPath in os.getcwd()):
136 chDir = True
137 os.chdir("./../")
138 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/")):
139 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/jpl")):
140 shutil.rmtree(f"./../{pluginName}/{osBuildPath}/jpl", onerror=onerror)
141 else:
142 os.mkdir(f"./../{pluginName}/{osBuildPath}")
143 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl")
144 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib")
145 if (distribution != 'android'):
146 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{distribution}")
147 else:
148 if ("ANDROID_ABI" in os.environ.keys()):
149 for abi in os.environ["ANDROID_ABI"].split(' '):
150 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{abi}")
151
152 shutil.copytree(f"./../{pluginName}/data/",
153 f"./../{pluginName}/{osBuildPath}/jpl/data/")
154 shutil.copyfile(f"./../{pluginName}/manifest.json",
155 f"./../{pluginName}/{osBuildPath}/jpl/manifest.json")
156 if (os.path.exists(f"./../{pluginName}/data/preferences.json")):
157 shutil.copyfile(
158 f"./../{pluginName}/data/preferences.json",
159 f"./../{pluginName}/{osBuildPath}/jpl/data/preferences.json")
160 if (chDir):
161 os.chdir(f"./{osBuildPath}")
162
163
164def assemble(pluginName, extraPath='', distribution=''):
165 extraPath = '/' + extraPath
166 localSystem = getSystem()
167 root = os.path.dirname(os.path.abspath(__file__)) + "/.."
168 osBuildPath = "build-local"
169
170 if localSystem == OS_IDS["Linux"]:
171 if (distribution != 'android'):
172 distribution = "x86_64-linux-gnu"
173 elif localSystem == OS_IDS["Darwin"]:
agsantos1bbc7cc2021-05-20 16:43:35 -0400174 distribution = "x86_64-apple-Darwin"
agsantos1e7736c2020-10-28 14:39:13 -0400175 elif localSystem == OS_IDS["Windows"]:
176 distribution = "x64-windows"
177 osBuildPath = 'msvc'
178 if (not os.path.exists(f"{root}/build")):
179 os.mkdir(f"{root}/build")
180 if (not os.path.exists(f"{root}/build/{distribution}")):
181 os.mkdir(f"{root}/build/{distribution}")
182 if (not os.path.exists(f"{root}/build/{distribution}{extraPath}")):
183 os.mkdir(f"{root}/build/{distribution}{extraPath}")
184 if (os.path.exists(f"./../build/{pluginName}.jpl")):
185 os.remove(f"./../build/{pluginName}.jpl")
186
187 outputJPL = f"{root}/build/{distribution}{extraPath}/{pluginName}.jpl"
188 outputBuild = f"{root}/{pluginName}/{osBuildPath}/jpl"
189
190 with ZipFile(outputJPL, 'w') as zipObj:
191 for folderName, subfolders, filenames in os.walk(outputBuild):
192 for filename in filenames:
193 filePath = os.path.join(folderName, filename)
194 zipObj.write(
195 filePath, f"{folderName.split('/jpl')[-1]}/{filename}")
196 zipObj.close()
197
198
199def build(pluginName):
200 currentDir = os.getcwd()
201 os.chdir('./../')
202 subprocess.run([
203 sys.executable, os.path.join(
204 os.getcwd(), "build-plugin.py"),
205 "--projects", pluginName
206 ], check=True)
207 os.chdir(currentDir)
208
209
210def parser():
211 parser = argparse.ArgumentParser(description='Build some plugins.')
212 parser.add_argument('--plugin', type=str,
213 help='Name of plugin to be build')
214 parser.add_argument('--extraPath', type=str, default="",
215 help='output intermediate Path')
216 parser.add_argument('--distribution', type=str, default='',
217 help="GNU/Linux or Windows, leave empty. Android, type android")
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300218
agsantos1e7736c2020-10-28 14:39:13 -0400219 # to build or not to build
220 parser.add_argument('--build', action='store_true')
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300221
222 # to preassemble or not
223 parser.add_argument('--preassemble', action='store_true')
224
agsantos1e7736c2020-10-28 14:39:13 -0400225 # to assemble jpl or not
226 parser.add_argument('--assemble', action='store_true')
227
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300228 # to assemble jpl or not
229 parser.add_argument('--merge', action='store_true')
230
231 # to merge two or more jpl
232 parser.add_argument('--path', nargs='*', required=False,
233 help="Jpl full path")
234 parser.add_argument('--output', type=str, default='',
235 help="Jpl output full path")
236
agsantos1e7736c2020-10-28 14:39:13 -0400237 args = parser.parse_args()
238 return args
239
240
241def main():
242 args = parser()
243
244 if args.preassemble:
245 preAssemble(args.plugin, args.distribution)
246 if (args.build):
247 build(args.plugin)
248 if (args.assemble):
249 assemble(args.plugin, args.extraPath, args.distribution)
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300250 if (args.merge):
251 JPLStructure(args.path, args.output)
agsantos1e7736c2020-10-28 14:39:13 -0400252
253
254if __name__ == '__main__':
255 main()