-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathMakefile
More file actions
257 lines (253 loc) · 12 KB
/
Makefile
File metadata and controls
257 lines (253 loc) · 12 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
BUILD_DATE := $(shell date +%y%m%d)
BUILD_TIME := $(shell date +%H%m%S)
BUILD_VERSION := $(shell grep version package.json | head -1 | cut -c 15- | rev | cut -c 3- | rev)
BUILD_NUMBER := $(shell git rev-list --count $(shell git rev-parse --abbrev-ref HEAD))
REVISION_INDEX := $(shell git --no-pager log --pretty=format:%h -n 1)
site := $(or $(site),main)
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
KEYCHAIN_NAME := bai-build-$(shell openssl rand -hex 16 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{12})/\1-\2-\3-\4-\5/').keychain
BAI_APP_SIGN_KEYCHAIN_FILE := $(shell mktemp -d)/keychain.p12
BAI_APP_SIGN_KEYCHAIN =
RED := \033[0;31m
GREEN := \033[0;32m
YELLOW := \033[1;33m
BLUE := \033[1;34m
MAGENTA := \033[1;35m
CYAN := \033[1;36m
WHITE := \033[1;37m
BBLUE := \033[38;5;123m
BWHITE := \033[38;5;231m
BRED := \033[0;91m
BGREEN := \033[0;92m
BYELLOW := \033[1;93m
NC := \033[0m
test_web:
@pnpm run dev
test_electron: dep
@pnpm run electron:d
test_electron_hmr: dep # For development with HMR, you have to run dev first
@pnpm run electron:d:hmr
proxy:
@node ./src/wsproxy/local_proxy.js
versiontag:
@printf "$(GREEN)Tagging version number / index...$(NC)\n"
@echo '{ "package": "${BUILD_VERSION}", "buildNumber": "${BUILD_NUMBER}", "buildDate": "${BUILD_DATE}.${BUILD_TIME}", "revision": "${REVISION_INDEX}" }' > version.json
@sed -i -E 's/globalThis.packageVersion = "\([^"]*\)"/globalThis.packageVersion = "${BUILD_VERSION}"/g' index.html
@sed -i -E 's/"version": "\([^"]*\)"/"version": "${BUILD_VERSION}"/g' manifest.json
@sed -i -E 's/"version": "\([^"]*\)"/"version": "${BUILD_VERSION}"/g' react/package.json
@sed -i -E 's/"version": "\([^"]*\)"/"version": "${BUILD_VERSION}"/g' packages/backend.ai-ui/package.json
@sed -i -E 's/"version": "\([^"]*\)"/"version": "${BUILD_VERSION}"/g' electron-app/package.json
@sed -i -E 's/globalThis.buildNumber = "\([^"]*\)"/globalThis.buildNumber = "${BUILD_NUMBER}"/g' index.html
@printf "$(YELLOW)Finished$(NC)\n"
compile_keepversion:
@pnpm run build
compile: versiontag
@if [ ! -f "./config.toml" ]; then \
cp config.toml.sample config.toml; \
fi
@pnpm run build
clean_client_node_ts:
@printf "$(CYAN)Cleaning backend.ai-client-node.js...$(NC)\n"
@rm -f ./src/lib/backend.ai-client-node.js
compile_client_node_ts: clean_client_node_ts
@printf "$(GREEN)Compiling backend.ai-client-node.ts...$(NC)\n"
@./node_modules/typescript/bin/tsc src/lib/backend.ai-client-node.ts --outDir src/lib --target es2018 --module commonjs --allowJs true --moduleResolution node --resolveJsonModule true --esModuleInterop false --experimentalDecorators true --allowSyntheticDefaultImports true --skipLibCheck true --lib es6,dom,es2016,es2017,es2020 --strict false --strictNullChecks false --strictFunctionTypes false --strictBindCallApply false --strictPropertyInitialization false --noImplicitThis false --alwaysStrict false --noUnusedLocals false --noImplicitReturns false --noFallthroughCasesInSwitch false
@printf "$(YELLOW)backend.ai-client-node.js compiled$(NC)\n"
compile_wsproxy: compile_client_node_ts
@pnpm -w exec webpack-cli --config src/wsproxy/webpack.config.js
all: dep
@make compile_all_localproxy
@make mac_x64
@make mac_arm64
@make win_x64
@make win_arm64
@make linux_x64
@make linux_arm64
@make bundle
# Build all local proxy binaries in parallel (saves ~3-4 min vs sequential)
compile_all_localproxy:
@printf "$(GREEN)Compiling all local proxy binaries in parallel...$(NC)\n"
@make compile_localproxy os=macos arch=x64 local_proxy_postfix= & \
make compile_localproxy os=macos arch=arm64 local_proxy_postfix= & \
make compile_localproxy os=win arch=x64 local_proxy_postfix=.exe & \
make compile_localproxy os=win arch=arm64 local_proxy_postfix=.exe & \
make compile_localproxy os=linux arch=x64 local_proxy_postfix= & \
make compile_localproxy os=linux arch=arm64 local_proxy_postfix= & \
wait
@printf "$(YELLOW)All local proxy binaries compiled$(NC)\n"
# Build only the web bundle (no Electron setup). Used by CI web job.
# Also ensures src/wsproxy/dist/wsproxy.js exists, since dep_electron copies it.
dep_web:
@if [ ! -f "./config.toml" ]; then \
cp config.toml.sample config.toml; \
fi
@mkdir -p ./app
@if [ ! -d "./build/web/" ]; then \
make compile; \
fi
@if [ ! -f "./src/wsproxy/dist/wsproxy.js" ]; then \
make compile_wsproxy; \
fi
# Prepare the Electron app directory. Requires dep_web to have run first.
# Uses publicPath patching instead of a full second React build (~4-8 min savings).
#
# Idempotent: skips when `build/electron-app/app/index.html` already carries
# the patched `es6://assets/` marker. This mirrors the original
# Makefile's skip semantics so downstream targets that re-declare `dep` as a
# prerequisite (e.g. `mac_x64`, `win_x64`) do not repeatedly re-copy the web
# bundle. Set `FORCE_DEP_ELECTRON=1` to force a re-sync.
dep_electron: dep_web
@if [ -f "./build/electron-app/app/index.html" ] && grep -q 'es6://assets/' ./build/electron-app/app/index.html && [ "$(FORCE_DEP_ELECTRON)" != "1" ]; then \
printf "$(YELLOW)Electron app already prepared, skipping$(NC)\n"; \
else \
if [ ! -d "./build/electron-app" ]; then \
mkdir -p build/electron-app; \
cp -r electron-app/* build/electron-app/; \
cp electron-app/.npmrc build/electron-app/; \
pnpm i --prefix ./build/electron-app --ignore-workspace; \
fi && \
rm -rf build/electron-app/app build/electron-app/resources build/electron-app/manifest && \
cp -Rp build/web build/electron-app/app && \
cp -Rp build/web/resources build/electron-app && \
cp -Rp build/web/manifest build/electron-app && \
node scripts/patch-electron-publicpath.js build/electron-app/app && \
mkdir -p ./build/electron-app/app/wsproxy && \
cp ./src/wsproxy/dist/wsproxy.js ./build/electron-app/app/wsproxy/wsproxy.js && \
cp ./preload.js ./build/electron-app/preload.js; \
fi
dep: dep_electron
web:
@if [ ! -d "./build/web/" ];then \
make compile; \
fi
@mkdir -p ./deploy/$(site)
@cd deploy/$(site); rm -rf ./*; mkdir webui
@cp -Rp build/web/* deploy/$(site)/webui
@cp ./configs/$(site).toml deploy/$(site)/webui/config.toml
@if [ -f "./configs/$(site).css" ];then \
cp ./configs/$(site).css deploy/$(site)/webui/resources/custom.css; \
fi
mac_load_keychain:
ifeq ($(BAI_APP_SIGN_KEYCHAIN),)
ifdef BAI_APP_SIGN_KEYCHAIN_B64
ifndef BAI_APP_SIGN_KEYCHAIN_PASSWORD
$(error BAI_APP_SIGN_KEYCHAIN_PASSWORD is not defined)
endif # BAI_APP_SIGN_KEYCHAIN_PASSWORD
security create-keychain -p "" "${KEYCHAIN_NAME}"
security set-keychain-settings -lut 21600 "${KEYCHAIN_NAME}"
security unlock-keychain -p "" "${KEYCHAIN_NAME}"
$(shell echo "${BAI_APP_SIGN_KEYCHAIN_B64}" | base64 -d -o "${BAI_APP_SIGN_KEYCHAIN_FILE}")
security import "${BAI_APP_SIGN_KEYCHAIN_FILE}" -A -P "${BAI_APP_SIGN_KEYCHAIN_PASSWORD}" -k "${KEYCHAIN_NAME}"
security list-keychain -d user -s login.keychain
security list-keychain -d user -s "${KEYCHAIN_NAME}"
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" "${KEYCHAIN_NAME}"
$(eval BAI_APP_SIGN_KEYCHAIN := ${KEYCHAIN_NAME})
echo Keychain ${KEYCHAIN_NAME} created for build
endif # BAI_APP_SIGN_KEYCHAIN_B64
endif # BAI_APP_SIGN_KEYCHAIN
# Concurrency-safe: each (os, arch) build uses a unique staging directory so
# multiple invocations can run in parallel without overwriting each other's
# intermediate file (`backend.ai-local-proxy[.exe]`) packed into the ZIP.
#
# Idempotent: skips rebuild when the output ZIP already exists, so `make all`
# can pre-build everything via `compile_all_localproxy` and downstream targets
# (`mac_x64`, `win_x64`, ...) can reuse the cached artifact without
# re-compiling. Set `FORCE_COMPILE_LOCALPROXY=1` to force a rebuild.
compile_localproxy:
@if [ -f "./app/backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch).zip" ] && [ "$(FORCE_COMPILE_LOCALPROXY)" != "1" ]; then \
printf "$(YELLOW)local-proxy $(os)-$(arch) already built, skipping$(NC)\n"; \
else \
rm -rf ./app/backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch)$(local_proxy_postfix); \
pnpm exec pkg ./src/wsproxy/local_proxy.js --targets node18-$(os)-$(arch) --output ./app/backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch)$(local_proxy_postfix) --compress Brotli; \
rm -rf ./app/_lp-stage-$(os)-$(arch); \
mkdir -p ./app/_lp-stage-$(os)-$(arch); \
cp ./app/backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch)$(local_proxy_postfix) ./app/_lp-stage-$(os)-$(arch)/backend.ai-local-proxy$(local_proxy_postfix); \
rm -f ./app/backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch).zip; \
(cd ./app/_lp-stage-$(os)-$(arch); zip -r -6 ../backend.ai-local-proxy-$(BUILD_VERSION)-$(os)-$(arch).zip "./backend.ai-local-proxy$(local_proxy_postfix)"); \
rm -rf ./app/_lp-stage-$(os)-$(arch); \
fi
package_zip:
@printf "$(GREEN)Packaging as ZIP archive...$(NC)"
@cp ./configs/$(site).toml ./build/electron-app/app/config.toml
@node ./app-packager.js $(os) $(arch)
@cd app; zip -r -6 ./backend.ai-desktop-$(os)-$(arch)-$(BUILD_DATE).zip "./Backend.AI Desktop-$(os_api)-$(arch)"
ifeq ($(site),main)
@mv ./app/backend.ai-desktop-$(os)-$(arch)-$(BUILD_DATE).zip ./app/backend.ai-desktop-$(BUILD_VERSION)-$(os)-$(arch).zip
else
@mv ./app/backend.ai-desktop-$(os)-$(arch)-$(BUILD_DATE).zip ./app/backend.ai-desktop-$(os)-$(arch)-$(BUILD_VERSION)-$(site).zip
endif
@printf "$(YELLOW)Finished$(NC)\n"
package_dmg:
@printf "$(GREEN)Packaging as DMG file...$(NC)"
@cp ./configs/$(site).toml ./build/electron-app/app/config.toml
@BAI_APP_SIGN_KEYCHAIN="${BAI_APP_SIGN_KEYCHAIN}" node ./app-packager.js darwin $(arch)
ifdef BAI_APP_SIGN_KEYCHAIN
@security default-keychain -s login.keychain
endif
@rm -rf ./app/backend.ai-desktop-$(os)-$(arch)
@cd app; mv "Backend.AI Desktop-darwin-$(arch)" backend.ai-desktop-$(os)-$(arch);
@npx electron-installer-dmg './app/backend.ai-desktop-$(os)-$(arch)/Backend.AI Desktop.app' ./app/backend.ai-desktop-$(arch)-$(BUILD_DATE) --overwrite --icon=manifest/backend-ai.icns --title=Backend.AI
ifeq ($(site),main)
@mv ./app/backend.ai-desktop-$(arch)-$(BUILD_DATE).dmg ./app/backend.ai-desktop-$(BUILD_VERSION)-$(os)-$(arch).dmg
else
@mv ./app/backend.ai-desktop-$(arch)-$(BUILD_DATE).dmg ./app/backend.ai-desktop-$(BUILD_VERSION)-$(site)-$(os)-$(arch).dmg
endif
@printf "$(YELLOW)Finished$(NC)\n"
bundle: dep_web
@printf "$(GREEN)Bundling...$(NC)"
@mkdir -p ./app
@cd build/web; zip -r -6 ../../app/backend.ai-webui-bundle-$(BUILD_DATE).zip . > /dev/null
@mv ./app/backend.ai-webui-bundle-$(BUILD_DATE).zip ./app/backend.ai-webui-bundle-$(BUILD_VERSION).zip
@printf "$(YELLOW)Finished$(NC)\n"
mac: dep
@make mac_x64
@make mac_arm64
mac_x64: os := macos
mac_x64: arch := x64
mac_x64: local_proxy_postfix :=
mac_x64: dep mac_load_keychain compile_localproxy package_dmg
@printf "$(GREEN)Build finished$(NC): macOS x64\n"
mac_arm64: os := macos
mac_arm64: arch := arm64
mac_arm64: local_proxy_postfix :=
mac_arm64: dep mac_load_keychain compile_localproxy package_dmg
@printf "$(GREEN)Build finished$(NC): macOS arm64\n"
win: dep
@make win_x64
@make win_arm64
win_x64: os := win
win_x64: os_api := win32
win_x64: arch := x64
win_x64: local_proxy_postfix := .exe
win_x64: dep compile_localproxy package_zip
@printf "$(GREEN)Build finished$(NC): Windows x64\n"
win_arm64: os := win
win_arm64: os_api := win32
win_arm64: arch := arm64
win_arm64: local_proxy_postfix := .exe
win_arm64: dep compile_localproxy package_zip
@printf "$(GREEN)Build finished$(NC): Windows arm64\n"
linux: dep
@make linux_x64
@make linux_arm64
linux_x64: os := linux
linux_x64: os_api := linux
linux_x64: arch := x64
linux_x64: local_proxy_postfix :=
linux_x64: dep compile_localproxy package_zip
@printf "$(GREEN)Build finished$(NC): Linux x64\n"
linux_arm64: os := linux
linux_arm64: os_api := linux
linux_arm64: arch := arm64
linux_arm64: local_proxy_postfix :=
linux_arm64: dep compile_localproxy package_zip
@printf "$(GREEN)Build finished$(NC): Linux arm64\n"
build_docker: compile
docker build -t backend.ai-webui:$(BUILD_DATE) .
i18n:
@pnpm exec i18next-scanner --config ./i18n.config.js
clean:
@rm -rf ./app/backend*; rm -rf ./app/Backend*
@rm -rf ./build/unbundle ./build/bundle ./build/web ./build/electron-app
@rm -rf ./react/build