blob: 960bc171a09dbdf9c9456200120754b2eb5f04ac [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
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":
agsantos1bbc7cc2021-05-20 16:43:35 -040040 return OS_IDS["Darwin"]
agsantos1e7736c2020-10-28 14:39:13 -040041 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:
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040065 def __init__(self, paths, output = "", is_merge = True):
agsantos1e7736c2020-10-28 14:39:13 -040066 self.paths = paths
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -030067 self.outputName = output
agsantos1e7736c2020-10-28 14:39:13 -040068 self.pluginNames = []
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040069 self.ZipObjcts: dict[str, list[ZipFile]] = {}
70 if is_merge:
71 self.getOutName()
agsantos1e7736c2020-10-28 14:39:13 -040072 self.discoverJPLs()
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040073 if is_merge:
74 self.mergeJPLs()
agsantos1e7736c2020-10-28 14:39:13 -040075
76 def getOutName(self):
77 while (not self.outputName or not self.outputName.endswith(".jpl")):
Xavier Jouslin de Noray3b1411d2023-06-01 14:41:17 -040078 self.outputName = input("\nWhere to save the resulting JPL? ")
agsantos1e7736c2020-10-28 14:39:13 -040079 self.OutObj = ZipFile(self.outputName, 'w')
80
81 def discoverJPLs(self):
82 for path in self.paths:
83 name = os.path.split(path)[0].split('.')[0]
84 self.pluginNames.append(name)
85 self.ZipObjcts[path] = []
86 self.ZipObjcts[path].append(ZipFile(path, 'r'))
87 return
88
89 def mergeJPLs(self):
90 self.fileNames = []
91 for path in self.paths:
92 [obj] = self.ZipObjcts[path]
93 for item in obj.filelist:
94 if item.filename not in self.fileNames:
95 self.OutObj.writestr(item, obj.open(item).read())
96 self.fileNames.append(item.filename)
97 self.OutObj.close()
98
99
100def onerror(func, path, exc_info):
101 """
102 Error handler for ``shutil.rmtree``.
103
104 If the error is due to an access error (read only file)
105 it attempts to add write permission and then retries.
106
107 If the error is for another reason it re-raises the error.
108
109 Usage : ``shutil.rmtree(path, onerror=onerror)``
110 """
111 import stat
112 if not os.access(path, os.W_OK):
113 # Is the error an access error ?
114 os.chmod(path, stat.S_IWUSR)
115 func(path)
116 else:
117 raise
118
119
120def preAssemble(pluginName, distribution=''):
121 localSystem = getSystem()
122
123 osBuildPath = "build-local"
124 if localSystem == OS_IDS["Linux"]:
125 if (distribution != 'android'):
126 distribution = "x86_64-linux-gnu"
127 elif localSystem == OS_IDS["Darwin"]:
agsantos1bbc7cc2021-05-20 16:43:35 -0400128 distribution = "x86_64-apple-Darwin"
agsantos1e7736c2020-10-28 14:39:13 -0400129 elif localSystem == OS_IDS["Windows"]:
130 distribution = "x64-windows"
131 osBuildPath = "msvc"
132
133 chDir = False
134 if (osBuildPath in os.getcwd()):
135 chDir = True
136 os.chdir("./../")
137 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/")):
138 if (os.path.exists(f"./../{pluginName}/{osBuildPath}/jpl")):
139 shutil.rmtree(f"./../{pluginName}/{osBuildPath}/jpl", onerror=onerror)
140 else:
141 os.mkdir(f"./../{pluginName}/{osBuildPath}")
142 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl")
143 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib")
144 if (distribution != 'android'):
145 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{distribution}")
146 else:
147 if ("ANDROID_ABI" in os.environ.keys()):
148 for abi in os.environ["ANDROID_ABI"].split(' '):
149 os.mkdir(f"./../{pluginName}/{osBuildPath}/jpl/lib/{abi}")
150
151 shutil.copytree(f"./../{pluginName}/data/",
152 f"./../{pluginName}/{osBuildPath}/jpl/data/")
153 shutil.copyfile(f"./../{pluginName}/manifest.json",
154 f"./../{pluginName}/{osBuildPath}/jpl/manifest.json")
155 if (os.path.exists(f"./../{pluginName}/data/preferences.json")):
156 shutil.copyfile(
157 f"./../{pluginName}/data/preferences.json",
158 f"./../{pluginName}/{osBuildPath}/jpl/data/preferences.json")
159 if (chDir):
160 os.chdir(f"./{osBuildPath}")
161
162
163def assemble(pluginName, extraPath='', distribution=''):
164 extraPath = '/' + extraPath
165 localSystem = getSystem()
166 root = os.path.dirname(os.path.abspath(__file__)) + "/.."
167 osBuildPath = "build-local"
168
169 if localSystem == OS_IDS["Linux"]:
170 if (distribution != 'android'):
171 distribution = "x86_64-linux-gnu"
172 elif localSystem == OS_IDS["Darwin"]:
agsantos1bbc7cc2021-05-20 16:43:35 -0400173 distribution = "x86_64-apple-Darwin"
agsantos1e7736c2020-10-28 14:39:13 -0400174 elif localSystem == OS_IDS["Windows"]:
175 distribution = "x64-windows"
176 osBuildPath = 'msvc'
177 if (not os.path.exists(f"{root}/build")):
178 os.mkdir(f"{root}/build")
179 if (not os.path.exists(f"{root}/build/{distribution}")):
180 os.mkdir(f"{root}/build/{distribution}")
181 if (not os.path.exists(f"{root}/build/{distribution}{extraPath}")):
182 os.mkdir(f"{root}/build/{distribution}{extraPath}")
183 if (os.path.exists(f"./../build/{pluginName}.jpl")):
184 os.remove(f"./../build/{pluginName}.jpl")
185
186 outputJPL = f"{root}/build/{distribution}{extraPath}/{pluginName}.jpl"
187 outputBuild = f"{root}/{pluginName}/{osBuildPath}/jpl"
188
189 with ZipFile(outputJPL, 'w') as zipObj:
190 for folderName, subfolders, filenames in os.walk(outputBuild):
191 for filename in filenames:
192 filePath = os.path.join(folderName, filename)
193 zipObj.write(
194 filePath, f"{folderName.split('/jpl')[-1]}/{filename}")
195 zipObj.close()
196
197
198def build(pluginName):
199 currentDir = os.getcwd()
200 os.chdir('./../')
201 subprocess.run([
202 sys.executable, os.path.join(
203 os.getcwd(), "build-plugin.py"),
204 "--projects", pluginName
205 ], check=True)
206 os.chdir(currentDir)
207
208
209def parser():
210 parser = argparse.ArgumentParser(description='Build some plugins.')
211 parser.add_argument('--plugin', type=str,
212 help='Name of plugin to be build')
213 parser.add_argument('--extraPath', type=str, default="",
214 help='output intermediate Path')
215 parser.add_argument('--distribution', type=str, default='',
216 help="GNU/Linux or Windows, leave empty. Android, type android")
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300217
agsantos1e7736c2020-10-28 14:39:13 -0400218 # to build or not to build
219 parser.add_argument('--build', action='store_true')
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300220
221 # to preassemble or not
222 parser.add_argument('--preassemble', action='store_true')
223
agsantos1e7736c2020-10-28 14:39:13 -0400224 # to assemble jpl or not
225 parser.add_argument('--assemble', action='store_true')
226
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300227 # to assemble jpl or not
228 parser.add_argument('--merge', action='store_true')
229
230 # to merge two or more jpl
231 parser.add_argument('--path', nargs='*', required=False,
232 help="Jpl full path")
233 parser.add_argument('--output', type=str, default='',
234 help="Jpl output full path")
235
agsantos1e7736c2020-10-28 14:39:13 -0400236 args = parser.parse_args()
237 return args
238
239
240def main():
241 args = parser()
242
243 if args.preassemble:
244 preAssemble(args.plugin, args.distribution)
245 if (args.build):
246 build(args.plugin)
247 if (args.assemble):
248 assemble(args.plugin, args.extraPath, args.distribution)
Aline Gondim Santos028f3ee2022-08-10 13:16:43 -0300249 if (args.merge):
250 JPLStructure(args.path, args.output)
agsantos1e7736c2020-10-28 14:39:13 -0400251
252
253if __name__ == '__main__':
254 main()