Skip to content

Commit b0de1a1

Browse files
committed
fix: trying to fix building extras on macOS
1 parent 5544df6 commit b0de1a1

File tree

1 file changed

+99
-152
lines changed

1 file changed

+99
-152
lines changed

aw.spec

+99-152
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,59 @@ from pathlib import Path
1010
import aw_core
1111
import flask_restx
1212

13+
14+
def build_analysis(name, location, binaries=[], datas=[], hiddenimports=[]):
15+
name_py = name.replace("-", "_")
16+
location_candidates = [
17+
location / f"{name_py}/__main__.py",
18+
location / f"src/{name_py}/__main__.py",
19+
]
20+
try:
21+
location = next(p for p in location_candidates if p.exists())
22+
except StopIteration:
23+
raise Exception(f"Could not find {name} location from {location_candidates}")
24+
25+
return Analysis(
26+
[location],
27+
pathex=[],
28+
binaries=binaries,
29+
datas=datas,
30+
hiddenimports=hiddenimports,
31+
hookspath=[],
32+
runtime_hooks=[],
33+
excludes=[],
34+
win_no_prefer_redirects=False,
35+
win_private_assemblies=False,
36+
)
37+
38+
39+
def build_collect(analysis, name, console=True):
40+
"""Used to build the COLLECT statements for each module"""
41+
pyz = PYZ(analysis.pure, analysis.zipped_data)
42+
exe = EXE(
43+
pyz,
44+
analysis.scripts,
45+
exclude_binaries=True,
46+
name=name,
47+
debug=False,
48+
strip=False,
49+
upx=True,
50+
console=console,
51+
entitlements_file=entitlements_file,
52+
codesign_identity=codesign_identity,
53+
)
54+
return COLLECT(
55+
exe,
56+
analysis.binaries,
57+
analysis.zipfiles,
58+
analysis.datas,
59+
strip=False,
60+
upx=True,
61+
name=name,
62+
)
63+
64+
65+
# Get the current release version
1366
current_release = subprocess.run(
1467
shlex.split("git describe --tags --abbrev=0"),
1568
stdout=subprocess.PIPE,
@@ -18,6 +71,7 @@ current_release = subprocess.run(
1871
).stdout.strip()
1972
print("bundling activitywatch version " + current_release)
2073

74+
# Get entitlements and codesign identity
2175
entitlements_file = Path(".") / "scripts" / "package" / "entitlements.plist"
2276
codesign_identity = os.environ.get("APPLE_PERSONALID", "").strip()
2377
if not codesign_identity:
@@ -32,69 +86,42 @@ aw_server_rust_bin = aw_server_rust_location / "target/package/aw-server-rust"
3286
aw_qt_location = Path("aw-qt")
3387
awa_location = Path("aw-watcher-afk")
3488
aww_location = Path("aw-watcher-window")
89+
awi_location = Path("aw-watcher-input")
90+
aw_notify_location = Path("aw-notify")
3591

3692
if platform.system() == "Darwin":
3793
icon = aw_qt_location / "media/logo/logo.icns"
3894
else:
3995
icon = aw_qt_location / "media/logo/logo.ico"
40-
block_cipher = None
41-
42-
extra_pathex = []
43-
if platform.system() == "Windows":
44-
# The Windows version includes paths to Qt binaries which are
45-
# not automatically found due to bug in PyInstaller 3.2.
46-
# See: https://github.com/pyinstaller/pyinstaller/issues/2152
47-
import PyQt5
48-
49-
pyqt_path = os.path.dirname(PyQt5.__file__)
50-
extra_pathex.append(pyqt_path + "\\Qt\\bin")
5196

5297
skip_rust = False
5398
if not aw_server_rust_bin.exists():
5499
skip_rust = True
55100
print("Skipping Rust build because aw-server-rust binary not found.")
56101

57-
aw_server_a = Analysis(
58-
["aw-server/__main__.py"],
59-
pathex=[],
60-
binaries=None,
61-
datas=[
62-
(aws_location / "aw_server/static", "aw_server/static"),
63-
(restx_path / "templates", "flask_restx/templates"),
64-
(restx_path / "static", "flask_restx/static"),
65-
(aw_core_path / "schemas", "aw_core/schemas"),
66-
],
67-
hiddenimports=[],
68-
hookspath=[],
69-
runtime_hooks=[],
70-
excludes=[],
71-
win_no_prefer_redirects=False,
72-
win_private_assemblies=False,
73-
cipher=block_cipher,
74-
)
75102

76-
aw_qt_a = Analysis(
77-
[aw_qt_location / "aw_qt/__main__.py"],
78-
pathex=[] + extra_pathex,
103+
aw_qt_a = build_analysis(
104+
"aw-qt",
105+
aw_qt_location,
79106
binaries=[(aw_server_rust_bin, ".")] if not skip_rust else [],
80107
datas=[
81108
(aw_qt_location / "resources/aw-qt.desktop", "aw_qt/resources"),
82109
(aw_qt_location / "media", "aw_qt/media"),
83110
],
84-
hiddenimports=[],
85-
hookspath=[],
86-
runtime_hooks=[],
87-
excludes=[],
88-
win_no_prefer_redirects=False,
89-
win_private_assemblies=False,
90-
cipher=block_cipher,
91111
)
92-
93-
aw_watcher_afk_a = Analysis(
94-
[awa_location / "aw_watcher_afk/__main__.py"],
95-
pathex=[],
96-
binaries=None,
97-
datas=None,
112+
aw_server_a = build_analysis(
113+
"aw-server",
114+
aws_location,
115+
datas=[
116+
(aws_location / "aw_server/static", "aw_server/static"),
117+
(restx_path / "templates", "flask_restx/templates"),
118+
(restx_path / "static", "flask_restx/static"),
119+
(aw_core_path / "schemas", "aw_core/schemas"),
120+
],
121+
)
122+
aw_watcher_afk_a = build_analysis(
123+
"aw_watcher_afk",
124+
awa_location,
98125
hiddenimports=[
99126
"Xlib.keysymdef.miscellany",
100127
"Xlib.keysymdef.latin1",
@@ -117,17 +144,11 @@ aw_watcher_afk_a = Analysis(
117144
"pynput.keyboard._darwin",
118145
"pynput.mouse._darwin",
119146
],
120-
hookspath=[],
121-
runtime_hooks=[],
122-
excludes=[],
123-
win_no_prefer_redirects=False,
124-
win_private_assemblies=False,
125-
cipher=block_cipher,
126147
)
127-
128-
aw_watcher_window_a = Analysis(
129-
[aww_location / "aw_watcher_window/__main__.py"],
130-
pathex=[],
148+
aw_watcher_input_a = build_analysis("aw_watcher_input", awi_location)
149+
aw_watcher_window_a = build_analysis(
150+
"aw_watcher_window",
151+
aww_location,
131152
binaries=[
132153
(
133154
aww_location / "aw_watcher_window/aw-watcher-window-macos",
@@ -139,13 +160,9 @@ aw_watcher_window_a = Analysis(
139160
datas=[
140161
(aww_location / "aw_watcher_window/printAppStatus.jxa", "aw_watcher_window")
141162
],
142-
hiddenimports=[],
143-
hookspath=[],
144-
runtime_hooks=[],
145-
excludes=[],
146-
win_no_prefer_redirects=False,
147-
win_private_assemblies=False,
148-
cipher=block_cipher,
163+
)
164+
aw_notify_a = build_analysis(
165+
"aw_notify", aw_notify_location, hiddenimports=["desktop_notifier.resources"]
149166
)
150167

151168
# https://pythonhosted.org/PyInstaller/spec-files.html#multipackage-bundles
@@ -156,110 +173,40 @@ MERGE(
156173
(aw_qt_a, "aw-qt", "aw-qt"),
157174
(aw_watcher_afk_a, "aw-watcher-afk", "aw-watcher-afk"),
158175
(aw_watcher_window_a, "aw-watcher-window", "aw-watcher-window"),
176+
(aw_watcher_input_a, "aw-watcher-input", "aw-watcher-input"),
177+
(aw_notify_a, "aw-notify", "aw-notify"),
159178
)
160179

161-
aww_pyz = PYZ(
162-
aw_watcher_window_a.pure, aw_watcher_window_a.zipped_data, cipher=block_cipher
163-
)
164-
aww_exe = EXE(
165-
aww_pyz,
166-
aw_watcher_window_a.scripts,
167-
exclude_binaries=True,
168-
name="aw-watcher-window",
169-
debug=False,
170-
strip=False,
171-
upx=True,
172-
console=True,
173-
entitlements_file=entitlements_file,
174-
codesign_identity=codesign_identity,
175-
)
176-
aww_coll = COLLECT(
177-
aww_exe,
178-
aw_watcher_window_a.binaries,
179-
aw_watcher_window_a.zipfiles,
180-
aw_watcher_window_a.datas,
181-
strip=False,
182-
upx=True,
183-
name="aw-watcher-window",
184-
)
185180

186-
awa_pyz = PYZ(aw_watcher_afk_a.pure, aw_watcher_afk_a.zipped_data, cipher=block_cipher)
187-
awa_exe = EXE(
188-
awa_pyz,
189-
aw_watcher_afk_a.scripts,
190-
exclude_binaries=True,
191-
name="aw-watcher-afk",
192-
debug=False,
193-
strip=False,
194-
upx=True,
195-
console=True,
196-
entitlements_file=entitlements_file,
197-
codesign_identity=codesign_identity,
198-
)
199-
awa_coll = COLLECT(
200-
awa_exe,
201-
aw_watcher_afk_a.binaries,
202-
aw_watcher_afk_a.zipfiles,
203-
aw_watcher_afk_a.datas,
204-
strip=False,
205-
upx=True,
206-
name="aw-watcher-afk",
207-
)
181+
# aw-server
182+
aws_coll = build_collect(aw_server_a, "aw-server")
208183

209-
aws_pyz = PYZ(aw_server_a.pure, aw_server_a.zipped_data, cipher=block_cipher)
184+
# aw-watcher-window
185+
aww_coll = build_collect(aw_watcher_window_a, "aw-watcher-window")
210186

211-
aws_exe = EXE(
212-
aws_pyz,
213-
aw_server_a.scripts,
214-
exclude_binaries=True,
215-
name="aw-server",
216-
debug=False,
217-
strip=False,
218-
upx=True,
219-
console=True,
220-
entitlements_file=entitlements_file,
221-
codesign_identity=codesign_identity,
222-
)
223-
aws_coll = COLLECT(
224-
aws_exe,
225-
aw_server_a.binaries,
226-
aw_server_a.zipfiles,
227-
aw_server_a.datas,
228-
strip=False,
229-
upx=True,
230-
name="aw-server",
231-
)
187+
# aw-watcher-afk
188+
awa_coll = build_collect(aw_watcher_afk_a, "aw-watcher-afk")
232189

233-
awq_pyz = PYZ(aw_qt_a.pure, aw_qt_a.zipped_data, cipher=block_cipher)
234-
awq_exe = EXE(
235-
awq_pyz,
236-
aw_qt_a.scripts,
237-
exclude_binaries=True,
238-
name="aw-qt",
239-
debug=True,
240-
strip=False,
241-
upx=True,
242-
icon=icon,
190+
# aw-qt
191+
awq_coll = build_collect(
192+
aw_qt_a,
193+
"aw-qt",
243194
console=False if platform.system() == "Windows" else True,
244-
entitlements_file=entitlements_file,
245-
codesign_identity=codesign_identity,
246-
)
247-
awq_coll = COLLECT(
248-
awq_exe,
249-
aw_qt_a.binaries,
250-
aw_qt_a.zipfiles,
251-
aw_qt_a.datas,
252-
strip=False,
253-
upx=True,
254-
name="aw-qt",
255195
)
256196

197+
# aw-watcher-input
198+
awi_coll = build_collect(aw_watcher_input_a, "aw-watcher-input")
199+
200+
aw_notify_coll = build_collect(aw_notify_a, "aw-notify")
201+
257202
if platform.system() == "Darwin":
258203
app = BUNDLE(
259204
awq_coll,
205+
aws_coll,
260206
aww_coll,
261207
awa_coll,
262-
aws_coll,
208+
awi_coll,
209+
aw_notify_coll,
263210
name="ActivityWatch.app",
264211
icon=icon,
265212
bundle_identifier="net.activitywatch.ActivityWatch",

0 commit comments

Comments
 (0)