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

cmd/go: #cgo pkg-config: add conditional --static flag to pkg-config #12058

Open
kolyshkin opened this Issue Aug 6, 2015 · 18 comments

Comments

Projects
None yet
5 participants
@kolyshkin
Contributor

kolyshkin commented Aug 6, 2015

I found this case when working on Docker. Docker can be linked either statically or dynamically. For static linking, one has to specify all the libraries explicitly, including those required indirectly (i.e. by libraries that you use). For dynamic linking, one needs to specify only the libraries one uses directly. For example, when linking against libxml2 on Linux, for the case of dynamic linking you have to specify only -lxml2, while for the static linking case you have to also specify all the libraries used by libxml2 (like -lz -lm -llzma).

Fortunately, pkg-config supports this:

$ pkg-config --libs libxml-2.0
-lxml2 
$ pkg-config --libs --static libxml-2.0
-lxml2 -lz -llzma -lm 

I was expecting Go to add --static flag when the result is going to be statically linked, unfortunately it never happens. My current workaround is to do this:

// #cgo pkg-config: --static libxml-2.0

It solves my issues, but the problem with this approach is this leads to "overlinking" in the dynamic case, as described e.g. here: https://wiki.openmandriva.org/en/Overlinking_issues_in_packaging

Is it possible to implement conditionally adding --static to pkg-config invocation?

@ianlancetaylor ianlancetaylor changed the title from #cgo pkg-config: add conditional --static flag to pgk-config to cmd/go: #cgo pkg-config: add conditional --static flag to pgk-config Aug 6, 2015

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Aug 6, 2015

It's not immediately obvious to me how we can know whether we are going to be linking statically or linking dynamically. Are you suggesting that we look for the presence of --static in the -ldflags option?

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Aug 6, 2015

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Aug 6, 2015

@ianlancetaylor That is the biggest obstacle to me as I'm not an expert, that's why I filed an issue rather than sent a pull request. I looked around for ways to tell go to produce a static binary with cgo or gccgo, and it looks like they all end up with passing -static flag.

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Aug 6, 2015

At the very least, it makes sense to add --static flag to pkg-config unconditionally, this will greatly improve the chances of making the build work.

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Aug 6, 2015

One example I just came across: gosqlite package which says
#cgo LDFLAGS: -lsqlite3
If you try to build a binary with it dynamically, everything works. If you try to build it statically, it complains about missing pthread* and dlopen/dlsym/etc symbols. Let's look at pkg-config:

$ pkg-config --libs sqlite3
-lsqlite3  
$ pkg-config --libs --static sqlite3
-lsqlite3 -ldl -lpthread 

So, it's all there they way it should be. One would thing that everything that is needed to fix it would be this:

-#cgo LDFLAGS: -lsqlite3
+#cgo pkg-config: sqlite3

But unfortunately it won't work either for static linking case. One either needs to add --static unconditionally (leading to overlinking in the dynamic case), or wish that cmd/go would do it for them, which is the subject of the issue.

If there is any other way to fix it, please let me know. I am only aware of an overlinking workaround, which is to pass -Wl,--as-needed, but with it parameters to linker needs to be in a proper order ($FLAGS $OBJECTS $LIBS), and it can also break some specific cases.

kolyshkin added a commit to kolyshkin/moby that referenced this issue Aug 6, 2015

make binary: do not ignore unresolved symbols
TL;DR: stop building static binary that may fail

Linker flag --unresolved-symbols=ignore-in-shared-libs was added
in commit 06d0843 two years ago for the static build case, presumably
to avoid dealing with problem of missing libraries.

For the record, this is what ld(1) man page says:

> --unresolved-symbols=method
>    Determine how to handle unresolved symbols.  There are four
>    possible values for method:
> .........
>    ignore-in-shared-libs
>        Report unresolved symbols that come from regular object files,
>        but ignore them if they come from shared libraries.  This can
>        be useful when creating a dynamic binary and it is known that
>        all the shared libraries that it should be referencing are
>        included on the linker's command line.

Here, the flag is not used for its purpose ("creating a dynamic binary")
and does more harm than good. Instead of complaining about missing symbols
as it should do if some libraries are missing from LIBS/LDFLAGS, it lets
ld create a binary with unresolved symbols, ike this:

 $ readelf -s bundles/1.7.1/binary/docker-1.7.1 | grep -w UND
 ........
 21029: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlopen
 .........

Such binary is working just fine -- until code calls one of those
functions, then it crashes (for apparently no reason, i.e. it is
impossible to tell why from the diagnistics printed).

In other words, adding this flag allows to build a static binary
with missing libraries, hiding the problem from both a developer
(who forgot to add a library to #cgo: LDFLAGS -- I was one such
developer a few days ago when I was working on ploop graphdriver)
and from a user (who expects the binary to work without crashing,
and it does that until the code calls a function in one of those
libraries).

Removing the flag immediately unveils the problem (as it should):

	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlError':
	(.text+0x20971): undefined reference to `dlerror'
	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlClose':
	(.text+0x8814): undefined reference to `dlclose'

The problem is, gosqlite package says:

	#cgo LDFLAGS: -lsqlite3

which is enough for dynamic linking, as indirect dependencies (i.e.
libraries required by libsqlite3.so) are listed in .so file and will be
resolved dynamically by ldd upon executing the binary.

For static linking though, one has to list all the required libraries,
both direct and indirect. For libraries with pkgconfig support the
list of required libraries can be obtained with pkg-config:

	$ pkg-config --libs sqlite3 # dynamic linking case
	-lsqlite3
	$ pkg-config --libs --static sqlite3 # static case
	-lsqlite3 -ldl -lpthread

It seems that all one has to do is to fix gosqlite this way:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: sqlite3

Unfortunately, cmd/go doesn't know that it needs to pass --static
flag to pkg-config in case of static linking
(see golang/go#12058).

So, for one, one has to do one of these things:

1. Patch sqlite.go like this:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: --static sqlite3

(this is exactly what I do in goploop, see
kolyshkin/goploop@e9aa072)

2. Patch sqlite.go like this:
	-#cgo LDFLAGS: -lsqlite3
	+#cgo LDFLAGS: -lsqlite3 -ldl -lpthread

(I would submit this patch to gosqlite but it seems that
https://code.google.com/p/gosqlite/ is deserted and not maintained,
and patching it here is not right as it is "vendored")

3. Explicitly add -ldl for the static link case.
This is what this patch does.

4. Fork sqlite to github and maintain it there. Personally I am not
ready for that, as I'm neither a Go expert nor gosqlite user.

Now, moby#3 doesn't look like a clear solution, but nevertheless it makes
the build much better than it was before.

Signed-off-by: Kir Kolyshkin <kir@openvz.org>

kolyshkin added a commit to kolyshkin/moby that referenced this issue Aug 7, 2015

make binary: do not ignore unresolved symbols
TL;DR: stop building static binary that may fail

Linker flag --unresolved-symbols=ignore-in-shared-libs was added
in commit 06d0843 two years ago for the static build case, presumably
to avoid dealing with problem of missing libraries.

For the record, this is what ld(1) man page says:

> --unresolved-symbols=method
>    Determine how to handle unresolved symbols.  There are four
>    possible values for method:
> .........
>    ignore-in-shared-libs
>        Report unresolved symbols that come from regular object files,
>        but ignore them if they come from shared libraries.  This can
>        be useful when creating a dynamic binary and it is known that
>        all the shared libraries that it should be referencing are
>        included on the linker's command line.

Here, the flag is not used for its purpose ("creating a dynamic binary")
and does more harm than good. Instead of complaining about missing symbols
as it should do if some libraries are missing from LIBS/LDFLAGS, it lets
ld create a binary with unresolved symbols, ike this:

 $ readelf -s bundles/1.7.1/binary/docker-1.7.1 | grep -w UND
 ........
 21029: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlopen
 .........

Such binary is working just fine -- until code calls one of those
functions, then it crashes (for apparently no reason, i.e. it is
impossible to tell why from the diagnistics printed).

In other words, adding this flag allows to build a static binary
with missing libraries, hiding the problem from both a developer
(who forgot to add a library to #cgo: LDFLAGS -- I was one such
developer a few days ago when I was working on ploop graphdriver)
and from a user (who expects the binary to work without crashing,
and it does that until the code calls a function in one of those
libraries).

Removing the flag immediately unveils the problem (as it should):

	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlError':
	(.text+0x20971): undefined reference to `dlerror'
	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlClose':
	(.text+0x8814): undefined reference to `dlclose'

The problem is, gosqlite package says:

	#cgo LDFLAGS: -lsqlite3

which is enough for dynamic linking, as indirect dependencies (i.e.
libraries required by libsqlite3.so) are listed in .so file and will be
resolved dynamically by ldd upon executing the binary.

For static linking though, one has to list all the required libraries,
both direct and indirect. For libraries with pkgconfig support the
list of required libraries can be obtained with pkg-config:

	$ pkg-config --libs sqlite3 # dynamic linking case
	-lsqlite3
	$ pkg-config --libs --static sqlite3 # static case
	-lsqlite3 -ldl -lpthread

It seems that all one has to do is to fix gosqlite this way:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: sqlite3

Unfortunately, cmd/go doesn't know that it needs to pass --static
flag to pkg-config in case of static linking
(see golang/go#12058).

So, for one, one has to do one of these things:

1. Patch sqlite.go like this:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: --static sqlite3

(this is exactly what I do in goploop, see
kolyshkin/goploop@e9aa072)

2. Patch sqlite.go like this:
	-#cgo LDFLAGS: -lsqlite3
	+#cgo LDFLAGS: -lsqlite3 -ldl -lpthread

(I would submit this patch to gosqlite but it seems that
https://code.google.com/p/gosqlite/ is deserted and not maintained,
and patching it here is not right as it is "vendored")

3. Explicitly add -ldl for the static link case.
This is what this patch does.

4. Fork sqlite to github and maintain it there. Personally I am not
ready for that, as I'm neither a Go expert nor gosqlite user.

Now, moby#3 doesn't look like a clear solution, but nevertheless it makes
the build much better than it was before.

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Aug 7, 2015

@kolyshkin Sorry, I didn't mean to suggest that you should fix this. I'm trying to understand what you are suggesting. Let me try this: when you say "Docker can be linked either statically or dynamically" what do you mean? How does one decide to link Docker statically? How does one decide to link it dynamically?

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Aug 7, 2015

@ianlancetaylor sure! Looking into Docker build scripts, it's something like this (simplified for clarity):
go build -ldflags '-extldflags "-static"' ...
and when using gccgo this is:
go build -compiler gccgo --gccgoflags "-static" ...

@mattn

This comment has been minimized.

Member

mattn commented Aug 7, 2015

s/pgk-config/pkg-config/g

@kolyshkin kolyshkin changed the title from cmd/go: #cgo pkg-config: add conditional --static flag to pgk-config to cmd/go: #cgo pkg-config: add conditional --static flag to pkg-config Aug 7, 2015

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Aug 7, 2015

Sure it would be easier just to do something like
go build -static
and let cmd/go construct the proper flags depending on whether cgo or gccgo or something else is used. That would also make C static linking case detection easier. But I don't know enough to propose it.

jessfraz added a commit to jessfraz/docker that referenced this issue Sep 4, 2015

make binary: do not ignore unresolved symbols
TL;DR: stop building static binary that may fail

Linker flag --unresolved-symbols=ignore-in-shared-libs was added
in commit 06d0843 two years ago for the static build case, presumably
to avoid dealing with problem of missing libraries.

For the record, this is what ld(1) man page says:

> --unresolved-symbols=method
>    Determine how to handle unresolved symbols.  There are four
>    possible values for method:
> .........
>    ignore-in-shared-libs
>        Report unresolved symbols that come from regular object files,
>        but ignore them if they come from shared libraries.  This can
>        be useful when creating a dynamic binary and it is known that
>        all the shared libraries that it should be referencing are
>        included on the linker's command line.

Here, the flag is not used for its purpose ("creating a dynamic binary")
and does more harm than good. Instead of complaining about missing symbols
as it should do if some libraries are missing from LIBS/LDFLAGS, it lets
ld create a binary with unresolved symbols, ike this:

 $ readelf -s bundles/1.7.1/binary/docker-1.7.1 | grep -w UND
 ........
 21029: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlopen
 .........

Such binary is working just fine -- until code calls one of those
functions, then it crashes (for apparently no reason, i.e. it is
impossible to tell why from the diagnistics printed).

In other words, adding this flag allows to build a static binary
with missing libraries, hiding the problem from both a developer
(who forgot to add a library to #cgo: LDFLAGS -- I was one such
developer a few days ago when I was working on ploop graphdriver)
and from a user (who expects the binary to work without crashing,
and it does that until the code calls a function in one of those
libraries).

Removing the flag immediately unveils the problem (as it should):

	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlError':
	(.text+0x20971): undefined reference to `dlerror'
	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlClose':
	(.text+0x8814): undefined reference to `dlclose'

The problem is, gosqlite package says:

	#cgo LDFLAGS: -lsqlite3

which is enough for dynamic linking, as indirect dependencies (i.e.
libraries required by libsqlite3.so) are listed in .so file and will be
resolved dynamically by ldd upon executing the binary.

For static linking though, one has to list all the required libraries,
both direct and indirect. For libraries with pkgconfig support the
list of required libraries can be obtained with pkg-config:

	$ pkg-config --libs sqlite3 # dynamic linking case
	-lsqlite3
	$ pkg-config --libs --static sqlite3 # static case
	-lsqlite3 -ldl -lpthread

It seems that all one has to do is to fix gosqlite this way:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: sqlite3

Unfortunately, cmd/go doesn't know that it needs to pass --static
flag to pkg-config in case of static linking
(see golang/go#12058).

So, for one, one has to do one of these things:

1. Patch sqlite.go like this:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: --static sqlite3

(this is exactly what I do in goploop, see
kolyshkin/goploop@e9aa072)

2. Patch sqlite.go like this:
	-#cgo LDFLAGS: -lsqlite3
	+#cgo LDFLAGS: -lsqlite3 -ldl -lpthread

(I would submit this patch to gosqlite but it seems that
https://code.google.com/p/gosqlite/ is deserted and not maintained,
and patching it here is not right as it is "vendored")

3. Explicitly add -ldl for the static link case.
This is what this patch does.

4. Fork sqlite to github and maintain it there. Personally I am not
ready for that, as I'm neither a Go expert nor gosqlite user.

Now, #3 doesn't look like a clear solution, but nevertheless it makes
the build much better than it was before.

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Sep 9, 2015

@ianlancetaylor please let me know what do you think about this suggestion

@minux

This comment has been minimized.

Member

minux commented Sep 9, 2015

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 10, 2015

@kolyshkin I don't like the idea of adding a -static option to go build.

Minux's suggestion SGTM.

I would be OK with adding a -pkgconfigflags option to go build. This would provide a list of options that would be passed to pkg-config.

@mattn

This comment has been minimized.

Member

mattn commented Sep 10, 2015

pkg-config --static is same as just adding LDFLAGS --static ?

http://linux.die.net/man/1/pkg-config

--static
Output libraries suitable for static linking. That means including any private libraries in the output. This relies on proper tagging in the .pc files, else a too large number of libraries will ordinarily be output.

Do you know what is private libraries meaning? AFAICS, they are not same.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 10, 2015

Right: the pkg-config command takes a --static option; see the man page. I'm not sure what you mean by LDFLAGS --static, but that is not the same as the --static option to the pkg-config command.

The reference to private libraries is because when linking statically you need to explicitly list all the libraries you need. Shared libraries include a list of their dependencies, so you only have to link against the main shared library. Static libraries do not include such a list, so you need to link against all of them.

@xlab

This comment has been minimized.

xlab commented Sep 12, 2015

Adding -static to LDFLAGS will force a fully static build which is impossible on OS X. So this option shouldn't necessarily come with --static for the pkg-config.

darstahl added a commit to Microsoft/docker that referenced this issue Sep 17, 2015

make binary: do not ignore unresolved symbols
TL;DR: stop building static binary that may fail

Linker flag --unresolved-symbols=ignore-in-shared-libs was added
in commit 06d0843 two years ago for the static build case, presumably
to avoid dealing with problem of missing libraries.

For the record, this is what ld(1) man page says:

> --unresolved-symbols=method
>    Determine how to handle unresolved symbols.  There are four
>    possible values for method:
> .........
>    ignore-in-shared-libs
>        Report unresolved symbols that come from regular object files,
>        but ignore them if they come from shared libraries.  This can
>        be useful when creating a dynamic binary and it is known that
>        all the shared libraries that it should be referencing are
>        included on the linker's command line.

Here, the flag is not used for its purpose ("creating a dynamic binary")
and does more harm than good. Instead of complaining about missing symbols
as it should do if some libraries are missing from LIBS/LDFLAGS, it lets
ld create a binary with unresolved symbols, ike this:

 $ readelf -s bundles/1.7.1/binary/docker-1.7.1 | grep -w UND
 ........
 21029: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlopen
 .........

Such binary is working just fine -- until code calls one of those
functions, then it crashes (for apparently no reason, i.e. it is
impossible to tell why from the diagnistics printed).

In other words, adding this flag allows to build a static binary
with missing libraries, hiding the problem from both a developer
(who forgot to add a library to #cgo: LDFLAGS -- I was one such
developer a few days ago when I was working on ploop graphdriver)
and from a user (who expects the binary to work without crashing,
and it does that until the code calls a function in one of those
libraries).

Removing the flag immediately unveils the problem (as it should):

	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlError':
	(.text+0x20971): undefined reference to `dlerror'
	/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libsqlite3.a(sqlite3.o):
	In function `unixDlClose':
	(.text+0x8814): undefined reference to `dlclose'

The problem is, gosqlite package says:

	#cgo LDFLAGS: -lsqlite3

which is enough for dynamic linking, as indirect dependencies (i.e.
libraries required by libsqlite3.so) are listed in .so file and will be
resolved dynamically by ldd upon executing the binary.

For static linking though, one has to list all the required libraries,
both direct and indirect. For libraries with pkgconfig support the
list of required libraries can be obtained with pkg-config:

	$ pkg-config --libs sqlite3 # dynamic linking case
	-lsqlite3
	$ pkg-config --libs --static sqlite3 # static case
	-lsqlite3 -ldl -lpthread

It seems that all one has to do is to fix gosqlite this way:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: sqlite3

Unfortunately, cmd/go doesn't know that it needs to pass --static
flag to pkg-config in case of static linking
(see golang/go#12058).

So, for one, one has to do one of these things:

1. Patch sqlite.go like this:

	-#cgo LDFLAGS: -lsqlite3
	+#cgo pkg-config: --static sqlite3

(this is exactly what I do in goploop, see
kolyshkin/goploop@e9aa072)

2. Patch sqlite.go like this:
	-#cgo LDFLAGS: -lsqlite3
	+#cgo LDFLAGS: -lsqlite3 -ldl -lpthread

(I would submit this patch to gosqlite but it seems that
https://code.google.com/p/gosqlite/ is deserted and not maintained,
and patching it here is not right as it is "vendored")

3. Explicitly add -ldl for the static link case.
This is what this patch does.

4. Fork sqlite to github and maintain it there. Personally I am not
ready for that, as I'm neither a Go expert nor gosqlite user.

Now, #3 doesn't look like a clear solution, but nevertheless it makes
the build much better than it was before.

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Oct 5, 2015

@mattn

pkg-config --static is same as just adding LDFLAGS --static ?

No, these are totally different things.

pkg-config --libs NAME (with or without --static) provides you with compiler options needed to link against NAME).

LDFLAGS += -static is a flag to C linker instructing it to produce a statically linked binary.

Do you know what is private libraries meaning? AFAICS, they are not same.

In this context "private libraries" means "all the libraries that this library itself uses/needs". Let me give you an example.

If we want to build something dynamically with libsqlite, we add -lsqlite to CFLAGS (or CXXFLAGS, doesn't matter). Note we don't need to explicitly list the libraries that are used by libsqlite itself (such as libdl), as this is something that dynamic linker will care about (these dependencies are already embedded into libsqlite.so). We can list them explicitly, but that would lead to so-called overlinking (https://wiki.mageia.org/en/Overlinking_issues_in_packaging), so we'd rather not do that.

Now, if we want to build something statically, we need to list all the libraries explicitly in CFLAGS, including the libraries that we need, and the libraries that those libraries need.

So, for dynamic build of something with libsqlite, we need CLFAGS += -lsqlite, while for static build we need CFLAGS += -lsqlite -ldl. This is why pkg-config adds support for --static flag.

@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Oct 5, 2015

Why not just add a new cgo file protected by a build tag, say, static?

This sort of works for me. The only problem I see is a need to ask everyone who's using --gccgoflags "-static" or --ldflags '-extldflags "-static"' to their go build command to also add -tags static. It would be great if such a tag (or any other we could use) will magically appear itself (similar to $GOOS, $GOARCH or say cgo tags), so we won't have to modify all the building scripts.

If the above is impossible, I guess we can close this issue.

@minux

This comment has been minimized.

Member

minux commented Oct 5, 2015

On Mon, Oct 5, 2015 at 5:25 PM, Kirill Kolyshkin notifications@github.com
wrote:

Why not just add a new cgo file protected by a build tag, say, static?

This sort of works for me. The only problem I see is a need to ask
everyone who's using --gccgoflags "-static" or --ldflags '-extldflags
"-static"' to theirgo buildcommand to also add-tags static. It would be
great if such a tag (or any other we could use) will magically appear
itself (similar to $GOOS, $GOARCH or saycgo` tags), so we won't have to
modify all the building scripts.

My proposed solution doesn't require the user to pass extra -ldflags or
-gccgoflags
because it includes "#cgo LDFLAGS: -static". (there is a bug preventing
gccgo
from working correctly in this case, but that's a separate issue.)

see #12058 (comment)

kolyshkin added a commit to kolyshkin/goploop that referenced this issue Oct 5, 2015

Use correct libs for static and dynamic link
Go (well, cgo) supports pkg-config directive so it's easier
to figure out which libs we need to link against. Note that
in case of static linking the list of libraries is larger
(as we also need to include the libraries needed by libraries
we use). Fortunately, there is --static flag to pkg-config to
aim in this.

Unfortunately, cgo doesn't know whether to pass this flag or not,
neither do we, so we have to ask the user to indicate they are
building statically by providing "static" build flag.

This solves the problem of "overlinking" the non-static binary.

Before:
 $ objdump -p goploop.test | grep NEEDED
  NEEDED               libploop.so.1
  NEEDED               librt.so.1
  NEEDED               libpthread.so.0
  NEEDED               libxml2.so.2
  NEEDED               libz.so.1
  NEEDED               liblzma.so.5
  NEEDED               libm.so.6
  NEEDED               libc.so.6

After:
 $ objdump -p goploop.test | grep NEEDED
  NEEDED               libploop.so.1
  NEEDED               libpthread.so.0
  NEEDED               libc.so.6

So, the libraries that are used by libploop are not explicitly
listed now.

For a discussion leading to this change, please see
golang/go#12058

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
@kolyshkin

This comment has been minimized.

Contributor

kolyshkin commented Oct 5, 2015

My proposed solution doesn't require the user to pass extra -ldflags or -gccgoflags
because it includes "#cgo LDFLAGS: -static".

@minux Sorry, I overlooked it. Looks like it's a good way to go!

kolyshkin added a commit to kolyshkin/goploop that referenced this issue Oct 5, 2015

Simplify static build.
It's simpler than I initially thought! We just have to use -tags static,
there's no need to pass linker flags as we can set LDFLAGS for cgo
right from go source file.

See golang/go#12058 (comment)
for discussion about it.

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment