Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use environment variables in a cgo CFLAGS comment?

Tags:

go

linker

cgo

I'm attempting to write some C bindings for the Go language, and have run into a sort of sticky situation when setting up the Cgo compilation in Windows. I have code that looks like the following:

// #cgo windows CFLAGS: -I C:/dev/extlibs/include/
// #cgo windows LDFLAGS: -lMyLib -L C:/dev/extlibs/lib/
// #include <mylib/mylib.h>
import "C"

which is allows me to avoid installing Dlls, libs, and header files directly into my C:\Windows directory, but doesn't allow for much flexibility when other developers are working with a different file system setup (they all need the libs to be in C:/dev/extlibs/...).

Is there a way I could referent an environment variable from within the code? Perhaps something along the lines of:

// #cgo windows CFLAGS: -I $EXTLIBS$/include/

Or is there another way that people solve this issue that I have missed? I've spent some time googling around on this subject and haven't seen much that has been useful, so any information and/or resources could be a real help!

like image 534
Chris Covert Avatar asked Jun 05 '13 04:06

Chris Covert


People also ask

How do you pass an environment variable?

Environment variables can be used to pass configuration to an application when it is run. This is done by adding the definition of the environment variable to the deployment configuration for the application. To add a new environment variable use the oc set env command.

What is CGO enabled?

The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling. You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it.

What is Cgo_ldflags?

CGO_LDFLAGS is meant for both internal linking and external linking mode, whereas -extldflags is meant only. for external linking. Ok , that seems like a logical distinction, though I haven't figured out how to pass in multiple options to -extldflags from the command line.


2 Answers

According to the docs for CGO:

When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS and CGO_LDFLAGS environment variables are added to the flags derived from these directives. Package-specific flags should be set using the directives, not the environment variables, so that builds work in unmodified environments.

Using this knowledge, I have had success building a third-party package that wraps a C library so long as it provides it as a system package. The example I linked to:

package sdl

// #cgo LDFLAGS: -lSDL2
// #include <SDL2/SDL.h>
import "C"

Even though it specifies a system package for SDL2, and I have SDL2 installed in some non-system directory, I am able to still build this package using some of the environment variables I mentioned, such as in the following:

export SDL_PATH=/home/mark/where/I/installed/sdl
CGO_CFLAGS="-I$SDL_PATH/include" CGO_LDFLAGS="-L$SDL_PATH/lib" go build hello.go
LD_LIBRARY_PATH="$SDL_PATH/lib" ./hello

Of course, this is Linux, but you can probably use the same ideas in Windows.

like image 102
Mark Hildreth Avatar answered Sep 19 '22 10:09

Mark Hildreth


You could try using environment variables, the Gentoo Linux Wiki page on Safe C Flags has an example in the following format

CXXFLAGS="${CFLAGS}"

So you may be able to do something like

// #cgo windows CFLAGS: -I "${EXTLIBS}"/include/

but my syntax may be off, and that may be Makefile specific.

You could also try setting a CPATH environment variable which:

specifies a list of directories to be searched as if specified with -I, but after any paths given with -I options on the command line. This environment variable is used regardless of which language is being preprocessed.

The equivalent for -L is, I think, LIBRARY_PATH (Described at the CPATH link).

According to http://golang.org/cmd/cgo/ one sort of recommended way to get around this in a platform independant way is to use pkg-config.

// #cgo pkg-config: mylib otherlib

It's available for windows (http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/) and there's some more information on installing it at this question (How to install pkg config in windows?)

Other than that, put all the dependencies into a sub-directory of the go-code, use relative paths in your CFLAGS and LDFLAGS, and share the entire bundle with other developers.

like image 21
Intermernet Avatar answered Sep 21 '22 10:09

Intermernet