Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makefile build options do not generate static binaries #94

Closed
atc0005 opened this issue Oct 2, 2020 · 10 comments · Fixed by #95
Closed

Makefile build options do not generate static binaries #94

atc0005 opened this issue Oct 2, 2020 · 10 comments · Fixed by #95
Assignees
Labels
bug Something isn't working builds license
Milestone

Comments

@atc0005
Copy link
Owner

atc0005 commented Oct 2, 2020

I learned today that what I've been using isn't sufficient to the task:

BUILDCMD = go build -mod=vendor -a -ldflags="-s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"

This was the recommended set:

GOOS=linux go build -tags 'osusergo netgo'

ldflags options were not mentioned, but presumably will still be needed if we want to strip out debugging information.

Credit:


EDIT: See also golang/go#38789 (comment) (may be needed for CGO builds)

@atc0005 atc0005 added bug Something isn't working builds labels Oct 2, 2020
@atc0005 atc0005 added this to the v0.2.5 milestone Oct 2, 2020
@atc0005 atc0005 self-assigned this Oct 2, 2020
@atc0005 atc0005 changed the title Update Makefile build options to generate static binaries Makefile build options do not generate static binaries Oct 3, 2020
@atc0005 atc0005 changed the title Makefile build options do not generate static binaries Makefile build options does not generate static binaries Oct 3, 2020
@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

diff --git a/Makefile b/Makefile
index 622cc88..d45ec58 100644
--- a/Makefile
+++ b/Makefile
@@ -42,7 +42,7 @@ VERSION                               = $(shell git describe --always --long --dirty)

 # The default `go build` process embeds debugging information. Building
 # without that debugging information reduces the binary size by around 28%.
-BUILDCMD                               =       go build -mod=vendor -a -ldflags="-s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"
+BUILDCMD                               =       go build -mod=vendor -tags 'osusergo netgo' -a -ldflags="-s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"
 GOCLEANCMD                             =       go clean -mod=vendor ./...
 GITCLEANCMD                            =       git clean -xfd
 CHECKSUMCMD                            =       sha256sum -b

This seems (as advertised) to produce the intended effect.

There are a ton of build options available, but I do not feel I am knowledgeable enough to pick the rights ones for all projects. For now, I'll probably want to limit the number of changes I made to just the ones here until I can learn of further issues.

I'll keep an eye on upstream issue 26492 and pivot build options across projects that I maintain accordingly.

atc0005 added a commit that referenced this issue Oct 3, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

- refs GH-94
- refs golang/go#38789
- refs golang/go#26492
atc0005 added a commit that referenced this issue Oct 3, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

- refs GH-94
- refs golang/go#38789
- refs golang/go#26492
@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

At least for this project, setting CGO_ENABLED=0 is sufficient to generate a static binary. I suspect that won't work for the atc0005/mysql2sqlite project which currently uses a CGO-required SQLite package.

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

At least for this project, setting CGO_ENABLED=0 is sufficient to generate a static binary. I suspect that won't work for the atc0005/mysql2sqlite project which currently uses a CGO-required SQLite package.

Specifying CGO_ENABLED=0 produced failures:

WARN[0000] github.com/atc0005/mysql2sqlite/internal/dbqs.VerifyDBConn: attempt 1 of 6 to verify database connection failed: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

Using this set of options:

go build -mod=vendor -tags 'osusergo,netgo' -a -ldflags "-linkmode=external -extldflags '-static' -s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"

within an Ubuntu 18.04 LTS (WSL) environment produces this output:

Building release assets for linux ...
Building check_imap_mailbox 386 binaries
# github.com/atc0005/check-mail/cmd/check_imap_mailbox
loadinternal: cannot find runtime/cgo
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/7/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/7/libgcc_eh.a when searching for -lgcc_eh
/usr/bin/ld: cannot find -lgcc_eh
/usr/bin/ld: skipping incompatible //usr/lib/x86_64-linux-gnu/libc.a when searching for -lc
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

Makefile:184: recipe for target 'linux' failed
make: *** [linux] Error 2

Running sudo apt-get install gcc-multilib and then re-running the Makefile build succeeded, somewhat?

$ make clean && make linux && file release_assets/*/*-linux-amd64
Removing object files and cached files ...
Removing any existing release assets
Building release assets for linux ...
Building check_imap_mailbox 386 binaries
# github.com/atc0005/check-mail/cmd/check_imap_mailbox
loadinternal: cannot find runtime/cgo
Building check_imap_mailbox amd64 binaries
# github.com/atc0005/check-mail/cmd/check_imap_mailbox
loadinternal: cannot find runtime/cgo
Generating check_imap_mailbox checksum files
Completed build tasks for linux
release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=5ed02616b8d173f94b435db5418f77c1ed3beb71, stripped

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

Setting CGO_ENABLED=1 did not appear to make a difference.

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

$ make clean && CGO_ENABLED=1 make linux && file release_assets/*/*-linux-{386,amd64}
Removing object files and cached files ...
Removing any existing release assets
removed 'release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64'
removed 'release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-386'
removed 'release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64.sha256'
removed 'release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-386.sha256'
Building release assets for linux ...
Building check_imap_mailbox 386 binaries
# github.com/atc0005/check-mail/cmd/check_imap_mailbox
loadinternal: cannot find runtime/cgo
Building check_imap_mailbox amd64 binaries
# github.com/atc0005/check-mail/cmd/check_imap_mailbox
loadinternal: cannot find runtime/cgo
Generating check_imap_mailbox checksum files
Completed build tasks for linux
release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-386:   ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=d34d60c6d2461ba5a2edd873fd500d0bc426045a, stripped
release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=5ed02616b8d173f94b435db5418f77c1ed3beb71, stripped

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

Attempting to run the binary fails spectacularly:

$ release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64 --help
Trace/breakpoint trap (core dumped)

Dropping back to this build command works:

go build -mod=vendor -tags 'osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"

and seems to produce the intended effect:

release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-386:   ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

Dropping back to this build command works:

go build -mod=vendor -tags 'osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"

and seems to produce the intended effect

This is useful; I ended up submitting this as GH-95 a few hours ago.

For the time being this may have to be the "fix" until I learn a better way. I've already spent far too long on this one item.

@atc0005
Copy link
Owner Author

atc0005 commented Oct 3, 2020

Attempting to run the binary fails spectacularly:

$ release_assets/check_imap_mailbox/check_imap_mailbox-v0.2.4-17-g43a5535-dirty-linux-amd64 --help
Trace/breakpoint trap (core dumped)

This might be due to the WSL environment.

golang/go#14795

Either way, not worth fighting with right now.

atc0005 added a commit that referenced this issue Oct 3, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

I also include doc comments and reference links describing
the use of the updated build options list and some problems
that I encountered during testing of `linkmode=external`.

- refs GH-94
- refs golang/go 38789
- refs golang/go 26492
@atc0005 atc0005 changed the title Makefile build options does not generate static binaries Makefile build options do not generate static binaries Oct 3, 2020
@atc0005
Copy link
Owner Author

atc0005 commented Oct 6, 2020

Dropping back to this build command works:
go build -mod=vendor -tags 'osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w -X $(VERSION_VAR_PKG).version=$(VERSION)"
and seems to produce the intended effect

This is useful; I ended up submitting this as GH-95 a few hours ago.

For the time being this may have to be the "fix" until I learn a better way. I've already spent far too long on this one item.

Update:

I'm still digging into whether glibc is actually compiled into the static binary and how I would identify/confirm that. atc0005/mysql2sqlite#48 is tracking some of the research.

It appears that the static binaries do not contain glibc if you could the omission of (GNU/Linux), statically linked, for GNU/Linux 3.2.0 from the file output as such an indication (I still don't know).

FWIW:

https://play.golang.org/p/rr0hjBBDqhy

atc0005 added a commit that referenced this issue Oct 6, 2020
As far as I can tell, the v0.2.5 release provided binaries
that are *not* statically linked against glibc and thus
would not be held to LGPL license requirements. AFAICT.

Update Makefile to disable use of cgo for binary generation
in an effort to avoid potential inclusion in the future.

This is likely *not* the last time I'll need to update
the Makefile build options for static binary generation,
but hopefully this will do for now.

refs #94
refs atc0005/mysql2sqlite#48
@atc0005 atc0005 added the license label Oct 6, 2020
atc0005 added a commit to atc0005/check-cert that referenced this issue Oct 7, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

I also include doc comments and reference links describing
the use of the updated build options list and some problems
that I encountered during testing of `linkmode=external`.

- refs GH-92

- refs atc0005/check-mail#94
- refs atc0005/check-mail#95
- refs atc0005/check-mail#101

- refs golang/go 38789
- refs golang/go 26492
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working builds license
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

1 participant