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.

Answer from Mark Hildreth on Stack Overflow
🌐
GitHub
github.com › golang › go › issues › 44125
Add an include path for `go tool cgo` for vendored c libs · Issue #44125 · golang/go
February 5, 2021 - $ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/jpoole/.cache/go-build" GOENV="/home/jpoole/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/jpoole/core3:/home/jpoole/core3/plz-out/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/opt/tm/tools/go/1.14/usr/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/opt/tm/tools/go/1.14/usr/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="cc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build291593539=/tmp/go-build -gno-record-gcc-switches"
Author   Tatskaari
🌐
Go Packages
pkg.go.dev › cmd › cgo
cgo command - cmd/cgo - Go Packages
April 7, 2026 - This means that if a header file foo/bar.h exists both in the source directory and also in the system include directory (or some other place specified by a -I flag), then "#include <foo/bar.h>" will always find the local version in preference to any other version. 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 as well as when the CC environment variable is unset and the default C compiler (typically gcc or clang) cannot be found on the system PATH.
Discussions

cmd/cgo: #include relative to current directory broken since Go 1.8
What version of Go are you using (go version)? go version devel +4b2f7b4 Sat May 6 01:28:38 2017 +0000 windows/amd64 What did you do? main.go package main //#cgo CFLAGS: -Iinc //#include "foo.... More on github.com
🌐 github.com
10
May 6, 2017
cgo compile c files housed in different directory than go files
Go will only compile C files that are in a Go package directory. But the Go package doesn't need to actually do anything. Here's an example project that keeps the C library in a separate directory from the Go api that exposes it. The key is lib/lib.go, and the import of the lib package inapi/api.go. go.mod module go-c-example go 1.20 main.go package main import ( "fmt" "go-c-example/api" ) func main() { fmt.Println(api.Add(4, 7)) } api/api.go package api import _ "go-c-example/lib" // #include "../lib/include/lib.h" import "C" func Add(i1 int, i2 int) int { return int(C.add(C.int(i1), C.int(i2))) } lib/lib.go package lib import "C" lib/include/lib.h int add(int i1, int i2); lib/lib.c #include "include/lib.h" int add(int i1, int i2) { return i1 + i2; } More on reddit.com
🌐 r/golang
3
3
April 14, 2023
include - How to point to C header files in GO? - Stack Overflow
New to GoLang so go easy on me. I installed this package for which are GO bindings for the HDF5s filesystem: go get github.com/sbinet/go-hdf5 and I get fatal error: hdf5.h: No such file or direc... More on stackoverflow.com
🌐 stackoverflow.com
New to cgo - unable to include header
OS:- windows. Go version :- 1.11 I have written a program which uses some functions in c header file. I am getting the below error. Error: #go build command-line-arguments: invalid flag in #cgo CFLAGS: Files/IBM/SQLLIB Code:(sql.go) package main // #cgo CFLAGS: -I C:/Program Files/IBM/SQLLIB ... More on forum.golangbridge.org
🌐 forum.golangbridge.org
0
0
January 3, 2019
Top answer
1 of 2
22

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.

2 of 2
9

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.

🌐
Matrix
matrix-org.github.io › go-neb › pkg › C › index.html
cgo - The Go Programming Language
C code can #include this to see the declarations. -gccgo Generate output for the gccgo compiler rather than the gc compiler. -gccgoprefix prefix The -fgo-prefix option to be used with gccgo. -gccgopkgpath path The -fgo-pkgpath option to be used with gccgo. -import_runtime_cgo If set (which it is by default) import runtime/cgo in generated output.
🌐
GitHub
github.com › golang › go › issues › 20266
cmd/cgo: #include relative to current directory broken since Go 1.8 · Issue #20266 · golang/go
May 6, 2017 - What version of Go are you using (go version)? go version devel +4b2f7b4 Sat May 6 01:28:38 2017 +0000 windows/amd64 What did you do? main.go package main //#cgo CFLAGS: -Iinc //#include "foo.h" import "C" func main() { println(C.FOO) } ...
Author   gooid
🌐
Reddit
reddit.com › r/golang › cgo compile c files housed in different directory than go files
r/golang on Reddit: cgo compile c files housed in different directory than go files
April 14, 2023 -

Hello folks.

I am working on writing an Interpreter which is written in C and I want build a go api for my interpreter.

My current directory structure is something like this

...
cpank/*.c
cpank/stdlib/*.c
cpank/ext/*.c
cpank/ext/*.h
cpank/include/*.h
goapi/api.go
...

cpank/*.c contains the core files, stdlib contains source for standard library, ext curently contains 2 files xxhash.c and xxhash.h but can and will contain more files later.

I have tried putting the go file in main cpank directory but it fails. If I directly include the c files, cgo throws duplicate errors. Only thing that works is copying all c files from cpank, stdlib, ext and the include directory into the goapi directory.

Is there any way to tell cgo to compile this this and that files like we use with normal c projects.

How do I make this work?

Any help or suggestions will be appreciated.

🌐
Gridengine
gridengine.eu › index.php › other-stories › 232-avoiding-the-ldlibrarypath-with-shared-libs-in-go-cgo-applications-2015-12-21
Avoiding the LD_LIBRARY_PATH for Shared Libs in Go (cgo) Applications - Grid Engine Unleashed
December 21, 2015 - export CGO_LDFLAGS="-L/path/to/the/lib -Wl,-rpath -Wl,\$ORIGIN/../lib" export CGO_CFLAGS="-I/path/to/include/file/of/the/lib/include" go build
Find elsewhere
🌐
Go Forum
forum.golangbridge.org › getting help
New to cgo - unable to include header - Getting Help - Go Forum
January 3, 2019 - Error: #go build command-line-... func main() { fmt.Println(C.SQL_BLOB) } The sqlcli1.h file is LOCATED in C:\Program Files\IBM\SQLLIB\include....
🌐
The Go Programming Language
tip.golang.org › src › cmd › cgo › doc.go
Using cgo with the go command
Used to generate files in the 561 syscall package when bootstrapping a new target. 562 -importpath string 563 The import path for the Go package. Optional; used for 564 nicer comments in the generated files. 565 -import_runtime_cgo 566 If set (which it is by default) import runtime/cgo in 567 generated output.
🌐
GitHub
github.com › golang › go › issues › 20606
proposal: cmd/cgo: expand $GOPATH in -I and -L directives · Issue #20606 · golang/go
June 8, 2017 - package main // #cgo CFLAGS: -g -O3 -std=c99 // #cgo CFLAGS: -I${GOPATH}/github.com/chewxy/path/to/internal/sharedheaders // #include "fromshared.h" // #include "fromlocaldir.h" import "C" func main() { var a C.int C.sharedfuckall(a) C.localfuckall(a) }
Author   chewxy
🌐
Ardan Labs
ardanlabs.com › blog › 2013 › 08 › using-cgo-with-pkg-config-and-custom.html
Using CGO with Pkg-Config And Custom Dynamic Library Locations
In this version I specified the compiler and linker flags directly. The location of the header and dynamic library are referenced with a relative path. package main /* #cgo CFLAGS: -I../DyLib #cgo LDFLAGS: -L. -lkeyboard #include <keyboard.h> */ import "C" This is the new code.
🌐
GitHub
github.com › lxwagn › using-go-with-c-libraries
GitHub - lxwagn/using-go-with-c-libraries: A tutorial project showing how to use C static and dynamic libraries (.a and .so) with Golang · GitHub
/* #cgo CFLAGS: -I./src #cgo LDFLAGS: -L./lib -lmylib -Wl,-rpath=./lib #include "mylib.h" #include <stdlib.h> #include <stdio.h> void myPrintFunction2() { printf("Hello from inline C\n"); } */ import "C"
Starred by 202 users
Forked by 20 users
Languages   Go 60.9% | Makefile 26.7% | C 12.4%
🌐
Reddit
reddit.com › r/golang › cgo - bundle and include c files?
r/golang on Reddit: cgo - bundle and include C files?
January 28, 2017 -

I would like to include C source files together with my bindings for raylib https://github.com/gen2brain/raylib-go. It is not a library that you can just apt-get/dnf/brew so I think it would be nice if I bundle C source together with Go files.

I know for some examples, like gousb or glwf3 that bundle C source files, and include .c files together with .h but I am not sure where to start. So in raylib C version, there are 5-6 .c files, they are built to .o and then linked to one static library. How will that work in cgo, if I just include .c files how are they linked?

🌐
Google Groups
groups.google.com › g › golang-nuts › c › yNDhuLwlIBE › m › A037Q-N-BQAJ
Dynamic include path in cgo?
August 9, 2020 - to golang-nuts · On Sunday, August 9, 2020 at 9:56:43 AM UTC-7, Miki Tebeka wrote: Is there a way to pass include path dynamically to cgo? The easiest way is to generate the include file and just reference it from cgo. It looks like your code needs to have a Makefile anyway.
🌐
Google Groups
groups.google.com › g › golang-nuts › c › fFIyDVilcrU
where is my lib? cgo and c libraries
1. I set LD_LIBRARY_PATH to point to the directory with the C library before I run the program. 2. When I use `go build`, I add an option that says to include the path to the C library in the code: -ldflags="-r /path/to/lib" I think that when a package gets installed, the path to C libaries ...
🌐
Go
go.googlesource.com › go › + › master › src › cmd › cgo › doc.go
src/cmd/cgo/doc.go - go - Git at Google
Sign in · go/go/master/./src/cmd/cgo/doc.go · blob: 47d243d1a16190b5205dde6aad8ea521cbabe8ad [file] [log] [blame] · Powered by Gitiles| Privacy| Termstxt json
🌐
Go
go.dev › src › cmd › cgo › doc.go
- The Go Programming Language
Used to generate files in the 561 syscall package when bootstrapping a new target. 562 -importpath string 563 The import path for the Go package. Optional; used for 564 nicer comments in the generated files. 565 -import_runtime_cgo 566 If set (which it is by default) import runtime/cgo in 567 generated output.
🌐
Google Groups
groups.google.com › g › golang-nuts › c › gVNucGdZBxY
CGO CFlags for different platforms
CGO_CFLAGS=-I/my/inc/path CGO_LDFLAGS=-L/my/lib/path go get some/cgo/project These two work with `go build`, as well. ... Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message ... #cgo CFLAGS: -I/usr/include #cgo ...