Go down a rabbit hole of trying to statically compile on linux
parent
b2d3111d7c
commit
56ba80c935
|
@ -0,0 +1,14 @@
|
|||
FROM alpine:latest
|
||||
|
||||
RUN apk add --no-cache \
|
||||
gcc musl-dev make go \
|
||||
alsa-lib libxrandr \
|
||||
sdl2-dev sdl2_mixer-dev sdl2_image-dev sdl2_ttf-dev
|
||||
|
||||
WORKDIR /home
|
||||
|
||||
COPY . .
|
||||
|
||||
#RUN make release_static
|
||||
|
||||
#COPY ./project-ely ./project-ely-static
|
38
Makefile
38
Makefile
|
@ -1,42 +1,52 @@
|
|||
EXECUTABLE=project-ely
|
||||
|
||||
GO=go
|
||||
MINGW64=x86_64-w64-mingw32-gcc
|
||||
MINGW32=i686-w64-mingw32-gcc
|
||||
MUSL_GCC="${HOME}/musl/bin/musl-gcc -static"
|
||||
|
||||
GO_BUILD=build -x -v
|
||||
GO_BUILD_DEBUG=${GO_BUILD} -gcflags=all="-N -l"
|
||||
GO_BUILD_RELEASE=${GO_BUILD} -trimpath -tags static -ldflags "-s -w"
|
||||
GO_BUILD_RELEASE_WINDOWS=${GO_BUILD} -trimpath -tags static -ldflags "-s -w -H windowsgui"
|
||||
GO_BUILD_RELEASE=${GO_BUILD} -trimpath -ldflags '-s -w'
|
||||
GO_BUILD_RELEASE_STATIC=${GO_BUILD} -trimpath -ldflags '-s -w -linkmode external -extldflags "-static"'
|
||||
|
||||
all: release
|
||||
|
||||
dependencies:
|
||||
${GO} mod tidy
|
||||
|
||||
debug: linter dependencies
|
||||
prebuild: dependencies
|
||||
|
||||
debug: prebuild
|
||||
${GO} ${GO_BUILD_DEBUG}
|
||||
|
||||
release: linter dependencies
|
||||
release: prebuild
|
||||
${GO} ${GO_BUILD_RELEASE}
|
||||
|
||||
# release_static only works on Alpine, see the Dockerfile
|
||||
release_static: prebuild
|
||||
CGO_ENABLED=1 \
|
||||
CGO_LDFLAGS="-Wl,-rpath -L${HOME}/pkg/lib -L/usr/lib -L/usr/lib/x86_64-linux-gnu" \
|
||||
${GO} ${GO_BUILD_RELEASE_STATIC}
|
||||
|
||||
linter:
|
||||
golangci-lint run
|
||||
|
||||
clean:
|
||||
rm -f ${EXECUTABLE}
|
||||
rm -f ${EXECUTABLE}-*
|
||||
rm -f output.log
|
||||
rm -f cpu.prof
|
||||
|
||||
cross_windows:
|
||||
CGO_ENABLED=1 \
|
||||
CC=x86_64-w64-mingw32-gcc \
|
||||
GOOS=windows \
|
||||
GOARCH=amd64 \
|
||||
${GO} ${GO_BUILD_RELEASE}
|
||||
CC=${MINGW64} \
|
||||
NAME=${EXECUTABLE} \
|
||||
./scripts/build-windows-amd64.sh
|
||||
|
||||
cross_windows_x86:
|
||||
CGO_ENABLED=1 \
|
||||
CC=i686-w64-mingw32-gcc \
|
||||
GOOS=windows \
|
||||
GOARCH=386 \
|
||||
${GO} ${GO_BUILD_RELEASE}
|
||||
CC=${MINGW32} \
|
||||
NAME=${EXECUTABLE} \
|
||||
./scripts/build-windows-386.sh
|
||||
|
||||
goimports_everything:
|
||||
find . -name "*.go" -exec goimports -w {} \;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# Linux Static Release Build
|
||||
|
||||
Because we're depending on SDL and X11 libraries, we can't easily
|
||||
build a completely statically-linked binary using musl unless we
|
||||
recompile those library dependencies also using musl. I was able to
|
||||
build something that was mostly statically-linked except for libc, but
|
||||
then it didn't run in a base Fedora Docker container.
|
||||
|
||||
The workaround for this is to use something where everything is
|
||||
already compiled with musl, like an Alpine Linux Docker container.
|
||||
|
||||
To build a fully statically-linked binary, use the `Dockerfile` in the
|
||||
root directory.
|
||||
|
||||
```sh
|
||||
docker build -t project-ely-build .
|
||||
```
|
||||
|
||||
This should spit out an executable called `project-ely-static`.
|
||||
|
||||
## Attempts on Debian
|
||||
|
||||
I tried installing musl on Debian.
|
||||
|
||||
I installed it to my home directory. I also specified my pkgsrc version of GCC.
|
||||
```sh
|
||||
CC=$HOME/pkg/gcc10/bin/gcc
|
||||
./configure --disabled-shared --prefix=$HOME/musl
|
||||
make -j4
|
||||
make install
|
||||
```
|
||||
|
||||
Then I had to symlink the X11 include dir.
|
||||
|
||||
```sh
|
||||
cd musl-install/include
|
||||
ln -s /usr/include/X11 X11
|
||||
```
|
||||
|
||||
I ran into an issue where it was unable to find many basic libraries
|
||||
like Xrandr and asound. But then I hit that same issue with the Alpine
|
||||
container =(
|
||||
|
||||
## References
|
||||
|
||||
Before giving up and using Alpine, I found these cool links that
|
||||
suggest you could do this more easily if we only depended on the C std
|
||||
library stuff, no external dependencies like X11 and SDL.
|
||||
|
||||
* https://honnef.co/posts/2015/06/statically_compiled_go_programs__always__even_with_cgo__using_musl/
|
||||
* https://github.com/golang/go/issues/26492
|
|
@ -0,0 +1,16 @@
|
|||
# Windows Static Release Build
|
||||
|
||||
You can build a statically-linked binary on Windows that should run
|
||||
without requiring the SDL `*.dll` files.
|
||||
|
||||
```sh
|
||||
go build -x -v -trimpath -tags static -ldflags "-s -w -H windowsgui"
|
||||
```
|
||||
|
||||
There is a script called [build-windows-static.sh][1] in the scripts
|
||||
folder to make this easy from Git Bash.
|
||||
|
||||
The Makefile supports cross-compiling for this from Linux with the
|
||||
`cross_windows` target.
|
||||
|
||||
[1]: scripts/build-windows-static.sh
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
. common-build-windows.sh
|
||||
|
||||
build windows 386
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
. common-release-build.sh
|
||||
|
||||
build windows amd64
|
|
@ -1,19 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# This is intended to run in Git Bash on Windows.
|
||||
# This builds a statically-linked release version of the binary ready to be deployed.
|
||||
|
||||
OUTPUT=project-ely
|
||||
|
||||
build(){
|
||||
OS=$1
|
||||
ARCH=$2
|
||||
|
||||
CGO_ENABLED=1 \
|
||||
CC=gcc \
|
||||
GOOS=$OS \
|
||||
GOARCH=$ARCH \
|
||||
go build -x -v -trimpath -tags static -ldflags="-s -w -H windowsgui" -o "${OUTPUT}-${OS}-${ARCH}.exe"
|
||||
}
|
||||
|
||||
build windows amd64
|
|
@ -0,0 +1,38 @@
|
|||
# This is a generalized function to build a statically-linked release binary.
|
||||
# It specifies all the Go flags needed to make that happen depending on the platform.
|
||||
|
||||
build(){
|
||||
OS=$1
|
||||
ARCH=$2
|
||||
|
||||
if [ -z $NAME ]
|
||||
then
|
||||
NAME=output
|
||||
fi
|
||||
|
||||
if [ -z "${CC}" ]
|
||||
then
|
||||
export CC=gcc
|
||||
fi
|
||||
|
||||
LDFLAGS_WIN=""
|
||||
EXE=""
|
||||
if [ "${OS}" == "windows" ]
|
||||
then
|
||||
# Hide the windows console popup for SDL
|
||||
LDFLAGS_WIN="-H windowsgui"
|
||||
EXE=".exe"
|
||||
fi
|
||||
|
||||
OUTPUT="${NAME}-${OS}-${ARCH}${EXE}"
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export CC="${CC}"
|
||||
export GOOS=$OS
|
||||
export GOARCH=$ARCH
|
||||
go build -x -v \
|
||||
-trimpath \
|
||||
-tags static \
|
||||
-ldflags="-s -w ${LDFLAGS_WIN}" \
|
||||
-o "${OUTPUT}"
|
||||
}
|
Loading…
Reference in New Issue