在cgo的CFLAGS注释中使用环境变量是否可行?

huangapple go评论159阅读模式
英文:

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

问题

我正在尝试为Go语言编写一些C绑定,并在设置Windows的Cgo编译时遇到了一些棘手的问题。我有以下代码:

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

这样可以避免直接将DLL、库和头文件安装到C:\Windows目录中,但在其他开发人员使用不同的文件系统设置时(他们都需要将库放在C:/dev/extlibs/...中),这样做就没有太多的灵活性。

我能否在代码中引用环境变量?也许可以这样做:

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

或者还有其他解决这个问题的方法吗?我在这个问题上花了一些时间搜索,但没有找到太多有用的信息和资源,所以任何信息和/或资源都将是真正的帮助!

英文:

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 &lt;mylib/mylib.h&gt;
import &quot;C&quot;

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!

答案1

得分: 19

根据CGO的文档

> 在构建时,CGO_CFLAGS、CGO_CPPFLAGS、CGO_CXXFLAGS和CGO_LDFLAGS环境变量会添加到从这些指令派生的标志中。应该使用指令设置特定于包的标志,而不是环境变量,以便在未修改的环境中进行构建。

利用这个知识,只要将第三方包提供为系统包,我就成功地构建了一个包装C库的第三方包。我提供的示例代码如下:

package sdl

// #cgo LDFLAGS: -lSDL2
// #include &lt;SDL2/SDL.h&gt;
import &quot;C&quot;

即使它为SDL2指定了一个系统包,而我在某个非系统目录中安装了SDL2,我仍然可以使用我提到的一些环境变量来构建这个包,例如:

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

当然,这是在Linux上,但你可能可以在Windows上使用相同的思路。

英文:

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 &lt;SDL2/SDL.h&gt;
import &quot;C&quot;

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=&quot;-I$SDL_PATH/include&quot; CGO_LDFLAGS=&quot;-L$SDL_PATH/lib&quot; go build hello.go
LD_LIBRARY_PATH=&quot;$SDL_PATH/lib&quot; ./hello

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

答案2

得分: 9

你可以尝试使用环境变量,Gentoo Linux Wiki页面上的Safe C Flags有一个以下格式的示例:

CXXFLAGS=&quot;${CFLAGS}&quot;

所以你可以尝试做一些类似的事情

// #cgo windows CFLAGS: -I &quot;${EXTLIBS}&quot;/include/

但是我的语法可能有问题,而且可能是特定于Makefile的。

你也可以尝试设置CPATH环境变量,它:

>指定要搜索的目录列表,就像在命令行上使用-I指定的一样,但是在命令行上使用-I选项指定的路径之后。无论预处理哪种语言,都会使用此环境变量。

相当于-L的等效方式是LIBRARY_PATH(在CPATH链接中描述)。

根据http://golang.org/cmd/cgo/,在一个平台无关的方式中,一种有点推荐的方法是使用pkg-config

// #cgo pkg-config: mylib otherlib

它在Windows上可用(http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/),并且在这个问题(如何在Windows上安装pkg config?)中有一些更多关于安装它的信息。

除此之外,将所有依赖项放入go代码的子目录中,在CFLAGSLDFLAGS中使用相对路径,并与其他开发人员共享整个包。

英文:

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

CXXFLAGS=&quot;${CFLAGS}&quot;

So you may be able to do something like

// #cgo windows CFLAGS: -I &quot;${EXTLIBS}&quot;/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.

huangapple
  • 本文由 发表于 2013年6月5日 12:41:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/16931700.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定