@@ -36,17 +36,19 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
3636version=" "
3737os=" ${GOOS:- linux} "
3838arch=" ${GOARCH:- amd64} "
39+ output_path=" "
3940slim=" ${CODER_SLIM_BUILD:- 0} "
41+ agpl=" ${CODER_BUILD_AGPL:- 0} "
4042sign_darwin=" ${CODER_SIGN_DARWIN:- 0} "
4143sign_windows=" ${CODER_SIGN_WINDOWS:- 0} "
42- bin_ident=" com.coder.cli"
43- output_path=" "
44- agpl=" ${CODER_BUILD_AGPL:- 0} "
4544boringcrypto=${CODER_BUILD_BORINGCRYPTO:- 0}
46- debug=0
4745dylib=0
46+ windows_resources=" ${CODER_WINDOWS_RESOURCES:- 0} "
47+ debug=0
48+
49+ bin_ident=" com.coder.cli"
4850
49- args=" $( getopt -o " " -l version:,os:,arch:,output:,slim,agpl,sign-darwin,boringcrypto,dylib,debug -- " $@ " ) "
51+ args=" $( getopt -o " " -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows, boringcrypto,dylib,windows-resources ,debug -- " $@ " ) "
5052eval set -- " $args "
5153while true ; do
5254 case " $1 " in
@@ -79,6 +81,10 @@ while true; do
7981 sign_darwin=1
8082 shift
8183 ;;
84+ --sign-windows)
85+ sign_windows=1
86+ shift
87+ ;;
8288 --boringcrypto)
8389 boringcrypto=1
8490 shift
@@ -87,6 +93,10 @@ while true; do
8793 dylib=1
8894 shift
8995 ;;
96+ --windows-resources)
97+ windows_resources=1
98+ shift
99+ ;;
90100 --debug)
91101 debug=1
92102 shift
@@ -115,11 +125,13 @@ if [[ "$sign_darwin" == 1 ]]; then
115125 dependencies rcodesign
116126 requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
117127fi
118-
119128if [[ " $sign_windows " == 1 ]]; then
120129 dependencies java
121130 requiredenvs JSIGN_PATH EV_KEYSTORE EV_KEY EV_CERTIFICATE_PATH EV_TSA_URL GCLOUD_ACCESS_TOKEN
122131fi
132+ if [[ " $windows_resources " == 1 ]]; then
133+ dependencies go-winres
134+ fi
123135
124136ldflags=(
125137 -X " 'github.com/coder/coder/v2/buildinfo.tag=$version '"
@@ -204,10 +216,100 @@ if [[ "$boringcrypto" == 1 ]]; then
204216 goexp=" boringcrypto"
205217fi
206218
219+ # On Windows, we use go-winres to embed the resources into the binary.
220+ if [[ " $windows_resources " == 1 ]] && [[ " $os " == " windows" ]]; then
221+ # Convert the version to a format that Windows understands.
222+ # Remove any trailing data after a "+" or "-".
223+ version_windows=$version
224+ version_windows=" ${version_windows% +* } "
225+ version_windows=" ${version_windows% -* } "
226+ # If there wasn't any extra data, add a .0 to the version. Otherwise, add
227+ # a .1 to the version to signify that this is not a release build so it can
228+ # be distinguished from a release build.
229+ non_release_build=0
230+ if [[ " $version_windows " == " $version " ]]; then
231+ version_windows+=" .0"
232+ else
233+ version_windows+=" .1"
234+ non_release_build=1
235+ fi
236+
237+ if [[ ! " $version_windows " =~ ^[0-9]+\. [0-9]+\. [0-9]+\. [0-1]$ ]]; then
238+ error " Computed invalid windows version format: $version_windows "
239+ fi
240+
241+ # File description changes based on slimness, AGPL status, and architecture.
242+ file_description=" Coder"
243+ if [[ " $agpl " == 1 ]]; then
244+ file_description+=" AGPL"
245+ fi
246+ if [[ " $slim " == 1 ]]; then
247+ file_description+=" CLI"
248+ fi
249+ if [[ " $non_release_build " == 1 ]]; then
250+ file_description+=" (development build)"
251+ fi
252+
253+ # Because this writes to a file with the OS and arch in the filename, we
254+ # don't support concurrent builds for the same OS and arch (irregardless of
255+ # slimness or AGPL status).
256+ #
257+ # This is fine since we only embed resources during dogfood and release
258+ # builds, which use make (which will build all slim targets in parallel,
259+ # then all non-slim targets in parallel).
260+ expected_rsrc_file=" ./buildinfo/resources/resources_windows_${arch} .syso"
261+ if [[ -f " $expected_rsrc_file " ]]; then
262+ rm " $expected_rsrc_file "
263+ fi
264+ touch " $expected_rsrc_file "
265+
266+ pushd ./buildinfo/resources
267+ GOARCH=" $arch " go-winres simply \
268+ --arch " $arch " \
269+ --out " resources" \
270+ --product-version " $version_windows " \
271+ --file-version " $version_windows " \
272+ --manifest " cli" \
273+ --file-description " $file_description " \
274+ --product-name " Coder" \
275+ --copyright " Copyright $( date +%Y) Coder Technologies Inc." \
276+ --original-filename " coder.exe" \
277+ --icon ../../scripts/win-installer/coder.ico
278+ popd
279+
280+ if [[ ! -f " $expected_rsrc_file " ]]; then
281+ error " Failed to generate $expected_rsrc_file "
282+ fi
283+ fi
284+
285+ set +e
207286GOEXPERIMENT=" $goexp " CGO_ENABLED=" $cgo " GOOS=" $os " GOARCH=" $arch " GOARM=" $arm_version " \
208287 go build \
209288 " ${build_args[@]} " \
210289 " $cmd_path " 1>&2
290+ exit_code=$?
291+ set -e
292+
293+ # Clean up the resources file if it was generated.
294+ if [[ " $windows_resources " == 1 ]] && [[ " $os " == " windows" ]]; then
295+ rm " $expected_rsrc_file "
296+ fi
297+
298+ if [[ " $exit_code " != 0 ]]; then
299+ exit " $exit_code "
300+ fi
301+
302+ # If we did embed resources, verify that they were included.
303+ if [[ " $windows_resources " == 1 ]] && [[ " $os " == " windows" ]]; then
304+ winres_dir=$( mktemp -d)
305+ if ! go-winres extract --dir " $winres_dir " " $output_path " 1>&2 ; then
306+ rm -rf " $winres_dir "
307+ error " Compiled binary does not contain embedded resources"
308+ fi
309+ # If go-winres didn't return an error, it means it did find embedded
310+ # resources.
311+ rm -rf " $winres_dir "
312+ fi
211313
212314if [[ " $sign_darwin " == 1 ]] && [[ " $os " == " darwin" ]]; then
213315 execrelative ./sign_darwin.sh " $output_path " " $bin_ident " 1>&2
0 commit comments