Build a govips application for Windows on Linux using Docker, MinGW and MSYSY2. Binaries running native on Windows without WSL.
Setup inspired by:
Build a govips application for Windows on Linux using Docker, MinGW and MSYSY2. Binaries running native on Windows without WSL.
Setup inspired by:
FROM golang:1.16-alpine as builder-linux | |
RUN apk add \ | |
vips-dev \ | |
gcc \ | |
musl-dev | |
RUN mkdir /go/pkg \ | |
&& mkdir /tmp/go-cache \ | |
&& chmod ugo=rwX /go/pkg /tmp/go-cache | |
ENV GOCACHE=/tmp/go-cache | |
VOLUME /go/pkg | |
VOLUME /tmp/go-cache | |
FROM builder-linux as builder-windows | |
RUN apk add \ | |
mingw-w64-gcc \ | |
pacman | |
RUN mkdir /usr/share/pacman/keyrings/ \ | |
&& wget "https://raw.githubusercontent.com/msys2/MSYS2-keyring/master/msys2-revoked" -O /usr/share/pacman/keyrings/msys2-revoked \ | |
&& wget "https://raw.githubusercontent.com/msys2/MSYS2-keyring/master/msys2-trusted" -O /usr/share/pacman/keyrings/msys2-trusted \ | |
&& wget "https://raw.githubusercontent.com/msys2/MSYS2-keyring/master/msys2.gpg" -O /usr/share/pacman/keyrings/msys2.gpg \ | |
&& pacman-key --init \ | |
&& pacman-key --populate msys2 | |
RUN echo -e "## msys2.org\\nServer = http://repo.msys2.org/mingw/x86_64\\nServer = https://downloads.sourceforge.net/project/msys2/REPOS/MINGW/x86_64" \ | |
> /etc/pacman.d/mirrorlist.mingw64 | |
RUN echo -e "\\n\\n[mingw64]\\nInclude = /etc/pacman.d/mirrorlist.mingw64" \ | |
>> /etc/pacman.conf | |
RUN pacman --noconfirm -Sy mingw-w64-x86_64-libvips \ | |
&& pacman --noconfirm -Sc | |
COPY objcopy.sh /usr/local/bin/ | |
ENV GOOS=windows | |
ENV GOARCH=amd64 | |
ENV CGO_ENABLED=1 | |
ENV CC=x86_64-w64-mingw32-gcc | |
ENV CXX=x86_64-w64-mingw32-g++ | |
ENV PKG_CONFIG_PATH=/mingw64/lib/pkgconfig |
#!/bin/bash | |
set -euo pipefail | |
src="${1:-}" | |
dst="${2:-}" | |
if [[ -z "${src}" ]] || [[ ! -f "${src}" ]] || [[ ! -d "${dst}" ]]; then | |
echo "Usage $0 [object file] [destination]" | |
echo "Script to copy dynamically linked windows binary with their import dependencies" | |
exit 1 | |
fi | |
deps=( ) | |
stack=( "${src}" ) | |
analyzed=( ) | |
ignore=( | |
"KERNEL32.dll" | |
"msvcrt.dll" | |
"ADVAPI32.dll" | |
"SHELL32.dll" | |
"USER32.dll" | |
"WS2_32.dll" | |
"ole32.dll" | |
"GDI32.dll" | |
"MSIMG32.dll" | |
"DNSAPI.dll" | |
"IPHLPAPI.DLL" | |
"SHLWAPI.dll" | |
"USERENV.dll" | |
"RPCRT4.dll" | |
"USP10.dll" | |
"gdiplus.dll" | |
) | |
paths=( | |
"." | |
"/mingw64/bin/" | |
) | |
while [[ ${#stack[@]} -gt 0 ]]; do | |
dep="${stack[0]}" | |
analyzed+=( "${dep}" ) | |
found=false | |
for p in "${paths[@]}"; do | |
if [[ -f "${p}/${dep}" ]]; then | |
dep="$( readlink -f "${p}/${dep}" )" | |
found=true | |
break | |
fi | |
done | |
if ! $found; then | |
echo "Error: Could not locate dependency \"${dep}\"." | |
exit 2 | |
fi | |
echo "Analyze \"${dep}\"" | |
while IFS='' read -r line; do stack+=("${line}"); done < \ | |
<( comm -13 \ | |
<( printf "%s\n" "${ignore[@]}" "${analyzed[@]}" "${stack[@]}" | uniq | sort ) \ | |
<( objdump --private-headers "${dep}" \ | |
| sed -n 's/^\s*DLL Name: \(.*\.dll\)$/\1/Ip' \ | |
| uniq | sort ) ) | |
deps+=( "${dep}" ) | |
stack=( "${stack[@]:1}" ) | |
done | |
cp -uv "${deps[@]}" "${dst}" | |
echo -e "\nCopied ${#deps[@]} dependencies" |