Linking golang statically

If you are not familiar with Golang, do take the go tour or read some of the docs first.

There are a number of reasons that folks are in love with golang. One the most mentioned is the static linking.

As long as the source being compiled is native go, the go compiler will statically link the executable. Though when you need to use cgo, then the compiler has to use its external linker.

Pure go

// code-pure.go
package main

import "fmt"

func main() {
        fmt.Println("hello, world!")
}

Straight forward example. Let’s compile it.

$> go build ./code-pure.go
$> ldd ./code-pure
        not a dynamic executable
$> file ./code-pure
./code-pure: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped

cgo

Using a contrived, but that passes through the C barrier:

// code-cgo.go
package main

/*
char* foo(void) { return "hello, world!"; }
*/
import "C"

import "fmt"

func main() {
  fmt.Println(C.GoString(C.foo()))
}

Seems simple enough. Let’s compile it

$> go build ./code-cgo.go
$> file ./code-cgo
./code-cgo: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
$> ldd ./code-cgo
        linux-vdso.so.1 (0x00007fff07339000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5e62737000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f5e6236e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5e62996000)
$> ./code-cgo
hello, world!

wait, what?

That code that is using cgo is not statically linked. Why not?

The compile for this does not wholly use golang’s internal linker, and has to use the external linker. So, this is not surprising, since this is not unlike simple `gcc -o hello-world.c`, which is default to dynamically linked.

// hello-world.c

int main() {
        puts("hello, world!");
}

$> gcc -o ./hello-world ./hello-world.c                                            
$> ./hello-world                                                                   
hello, world!                                                                      
$> file ./he                                                                       
hello-world    hello-world.c  hex.go                                               
$> file ./hello-world                                                              
./hello-world: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped 
$> ldd ./hello-world
        linux-vdso.so.1 (0x00007fff5f109000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0906e53000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f090725e000)

But for that example, we just have to add the '-static' flag to gcc (and ensure that glibc-static package is available).

$> gcc -o ./hello-world -static ./hello-world.c
$ file ./hello-world
./hello-world: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), statically linked, not stripped
$ ldd ./hello-world
        not a dynamic executable

Let's apply that same logic to our `go build`

static cgo

Using same code-cgo.go source, let's apply that gcc flag, but using the go build command.

$> go build --ldflags '-extldflags "-static"' ./code-cgo.go
$> file ./code-cgo
./code-cgo: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), statically linked, not stripped
$> ldd ./code-cgo
        not a dynamic executable
$> ./code-cgo
hello, world!

Cool! Here we've let the go compiler use the external linker, and that linker linked statically from libc.

An explanation of the flags here.

--ldflags is passed to the go linker. It takes a string of arguments.
On my linux-x86_64 machine, that is the 6l tool (5l for arm and 8l for ix86). To see the tools available on your host, call go tool, and then get help on that tool with go tool 6l --help

'-extldflags ...' is a flag for the 6l linker, to pass additional flags to the external linker (in my situation, that is gcc).

"-static" is the argument to gcc (also to ld) to link statically.

gccgo love

Say you have a use case for using/needing the gccgo compiler, instead of the go compiler.
Again, using our same code-cgo.go source, let's compile the code statically using gccgo.

$> go build -compiler gccgo --gccgoflags "-static" ./code-cgo.go
$> file ./code-cgo
./code-cgo: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), statically linked, not stripped
$> ldd ./code-cgo
        not a dynamic executable
$> ./code-cgo
hello, world!

Huzzah! Still a static binary, using cgo and giving gccgo a whirl. A quick run-down of these flags.

-compiler gccgo instructs the build to use gccgo instead of the go compiler (gc).

--gccgoflags ... are additional arguments passed to the gccgo command. See also the gccgo man page.

"-static" similar to gcc, this is the same flag the instructs gccgo to link the executable statically.

more info

If you're curious to what is happening behind the scenes of your compile, the go build has an -x flag that prints out the commands that it is running. This is often helpful if you are following what is linked in, or to see the commands used during compile such that you can find where and how to insert arguments needed.

ruby 1.9.3 is released, and slackware packages are here

Ruby 1.9.3 is *finally* released. Their NEWS and ChangeLog are available.


And I have packages built for slackware-current and slackware64-current here:

ruby-1.9.3_p0-i486-1_vb.txz [MD5] [ASC]

ruby-1.9.3_p0-x86_64-1_vb.txz [MD5] [ASC]


Again, these are built on the -current development branch, so use at your own risk. :)


Take care,
vb

Tastes in Languages: an internal dialogue

This has been a point of contention for me, ever since I have had a desire to learn a “language” other than shell scripting. Which language would be most practical, valuable, powerful, reach the most receptive audience, designed with the ideals you share, what pays the bills, etc. Some, or all, of these aspects can conflict at any given point.

As for being practical or powerful, these measurements are based on your use of the language, which vary more than there are languages, so it is a continually refining target. As I continue to learn more languages, and deepen my knowledge of others, it is evident that no one language can be the end-all. Learning their benefits and drawbacks is a large part of efficient implementation.

As for valuable, this can be in a business sense, or marketability since. For me, this is the first real point of indecision. Fortunately AND unfortunately, this measurement has a callback to another measurement, “What are the ideals and motives of the language’s design?”. Business sense can be a fuzzy option sometimes. If you are a business unit that is exclusively a Java shop, it does not mean that all glue and helpers must also be java. Inversely, just because Perl is flexible and powerful, does not mean it needs to be built into a megalithic solution. The marketability of a language though, can relate more to the individual developer.

The evolution of all the available languages comes due to varying factors and motivation, and that motivation assists greatly in the type of community and reputation that a language accrues. These are the ideals that a language is evolved with. This is the perception that can be reflected back on a developer. Like how PHP was formed by a loose group of code hackers, perl was an overly flexible parsing and report language, ruby was started by a single humble person seeking to please others. Thus is the seed that grows the community. As soon as you state what language you write in, the other person immediately conjures stereotypes to cast over you. Regardless of good or bad, it is another expression of the eight mundane concerns. If it is blame or disapproval that you seek to avoid, then you find yourself not associating with a broader audience. And seeking praise and approval, you turn in towards like minded folks to reaffirm your expressed position. This may work out just fine for many, but it does put you at a great chance of clinging to an us-and-them mentality, which can be poisonous for you and the community at large. I’m not going to expand on that greatly, you can find more insight on that, starting by reading on ingroups and outgroups

And for many, they may not be an advocate of the language they know best, but it is what has been taught abd/or what they are paid to write in. That is okay, because you can learn other languages, despite the stereotypes others cast on you from what you’ve written in. There are soon likely to be a multitude of .Net folks, regardless whether loyalist or indifferent, that need to branch out to new languages. Thankfully for the open source communities at large, these folks have fodder to learn from, and become involved with to broaden their own experience.

While I have languages that I am more comfortable with, than others, ultimately I am an advocate for being a language generalist. Determining the best tool for the job requires having a broad idea of the pros/cons of many options. Forcing a project into the box you are most familiar with, is not always the most efficient or effective approach.

Hacking on KDE: part 1

In a personal brainstorm of how to better facilitate folks that want to have an ideal hacking environment, for X. The primitives of the idea need to be figured out, and often nothing happens because you can determine “If the person has enough desire, and know how, they’ll figure it out,” and most of the time this is a fine explanation.

When it comes to a project collection like KDE, compiling it and fiddling around can be supremely easy without the bounds of package dependencies, but still manageable packages. Although, there are now a lot a projects in the KDE Software Collection, and they are all modular. Even within the Slackware community, alienBob has already updated the build process for his KDE SC 4.7 packages to be modular. With the migration from SVN to git, it has clarified some aspects of the build, but it has now made a segregated landscape of projects. If someone wants to check out a new project, the latest development in it, it seems like a hidden process.

Being agnostic of which Linux distribution I am running, if, as a developer, I want to be able to easily manage working from the git repositories of the projects, installing them, and possibly even packaging the artifacts, this is a intricate process. But thankfully, it is a describable process, therefore we can automate it.

Last night I began working on a project, tentatively named ‘kappy’. With the K App, in mind, and it is written in Python, so having a py in there seems suitable.
The source code is currently living at http://hashbangbash.com/kappy.git, or browser viewable at http://hashbangbash.com/git/?p=kappy.git;a=summary

Initially it is just doing XML parsing of the projects available. Next plans are:

  • making a caching ground for cloning/updating git repositories
  • building the software
  • having user definable configurations for flags and install paths
  • making recipes, of a suite of software to build
  • having a manager to package, for a respective distribution

Update: I’ve added a bug tracker for this project http://redmine.hashbangbash.com/projects/kappy

If you have feedback, feel free to send it in.

Take care,
vb