1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#!/usr/bin/env python3
# Copyright 2017-2021 The Meson development team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import subprocess
import shutil, sys, os
from glob import glob
import xml.etree.ElementTree as ET
sys.path.append(os.getcwd())
from mesonbuild import coredata
class PkgGenerator:
def __init__(self):
self.pkg_dir = 'macpkg'
self.sharedir = os.path.join(self.pkg_dir, 'usr/local/share')
self.bindir = os.path.join(self.pkg_dir, 'usr/local/bin')
self.product_name = 'Meson Build System'
self.identifier = 'com.mesonbuild.meson'
self.version = coredata.version.replace('dev', '')
self.mesonstashdir = os.path.join(self.sharedir, f'meson-{self.version}')
self.pkgname = 'meson.pkg'
self.productname = f'meson-{self.version}.pkg'
self.distribution_file = 'meson-distribution.xml'
self.resourcedir = 'packaging/macpages'
def build_dist(self):
if os.path.exists(self.pkg_dir):
shutil.rmtree(self.pkg_dir)
os.mkdir(self.pkg_dir)
pyinstaller_bin = glob('/Users/jpakkane/Library/Python/*/bin/pyinstaller')
if len(pyinstaller_bin) != 1:
sys.exit('Could not determine unique installer.')
pyinstaller_bin = pyinstaller_bin[0]
pyinst_cmd = [pyinstaller_bin,
'--clean',
'--additional-hooks-dir=packaging',
'--distpath',
self.pkg_dir]
pyinst_cmd += ['meson.py']
subprocess.check_call(pyinst_cmd)
tmpdir = os.path.join(self.pkg_dir, 'meson')
shutil.move(tmpdir, self.mesonstashdir)
os.makedirs(self.bindir)
ln_base = os.path.relpath(self.mesonstashdir, self.bindir)
ninja_bin = shutil.which('ninja')
assert ninja_bin
shutil.copy(ninja_bin, self.bindir)
subprocess.check_call(['strip', os.path.join(self.bindir, 'ninja')])
os.symlink(os.path.join(ln_base, 'meson'), os.path.join(self.bindir, 'meson'))
def build_package(self):
subprocess.check_call(['pkgbuild',
'--root',
self.pkg_dir,
'--identifier',
self.identifier,
self.pkgname])
self.generate_distribution()
subprocess.check_call(['productbuild',
'--distribution',
self.distribution_file,
'--resources',
self.resourcedir,
self.productname])
def generate_distribution(self):
root = ET.Element('installer-gui-script', {'minSpecVersion': '1'})
ET.SubElement(root, 'welcome', {'file': 'welcome.html',
'mime-type': 'text/html'})
ET.SubElement(root, 'license', {'file': 'license.html',
'mime-type': 'text/html'})
ET.SubElement(root, 'conclusion', {'file': 'conclusion.html',
'mime-type': 'text/html'})
ET.SubElement(root, 'pkg-ref', {'id': self.identifier})
ET.SubElement(root, 'options', {'customize': 'never',
'require-scripts': 'false',
'hostArchitectures': 'x86_64,arm64'})
choices_outline = ET.SubElement(root, 'choices-outline')
line = ET.SubElement(choices_outline, 'line', {'choice': 'default'})
ET.SubElement(line, 'line', {'choice': self.identifier})
ET.SubElement(root, 'choice', {'id': 'default'})
choice = ET.SubElement(root, 'choice', {'id': self.identifier, 'visible': 'false'})
ET.SubElement(choice, 'pkg-ref', {'id': self.identifier})
ET.SubElement(root, 'pkg-ref', {'id': self.identifier,
'version': '0', # self.version,
'onConclusion': 'none'}).text = self.pkgname
ET.ElementTree(root).write(self.distribution_file, encoding='utf-8', xml_declaration=True)
# ElementTree cannot do pretty-printing, so do it manually
import xml.dom.minidom
doc = xml.dom.minidom.parse(self.distribution_file)
with open(self.distribution_file, 'w') as open_file:
open_file.write(doc.toprettyxml())
def remove_tempfiles(self):
shutil.rmtree('macpkg')
os.unlink('meson-distribution.xml')
os.unlink('meson.pkg')
os.unlink('meson.spec')
if __name__ == '__main__':
if not os.path.exists('meson.py'):
sys.exit(print('Run me in the top level source dir.'))
subprocess.check_call(['pip3', 'install', '--user', '--upgrade', 'pyinstaller'])
pg = PkgGenerator()
pg.build_dist()
pg.build_package()
pg.remove_tempfiles()
|