I have the following package Makefile:
include ${GOROOT}/src/Make.inc
TARG=gorilla.googlecode.com/hg/gorilla/mux
GOFILES=\
doc.go\
mux.go\
DEPS=\
gorilla.googlecode.com/hg/gorilla/context
include ${GOROOT}/src/Make.pkg
I changed TARG and DEPS today to point to the Google code repository as shown above, following this advice.
The problem is: I can goinstall the package and it will install the dependency, but I cannot use gotest or gomake anymore; I get the following error (using Go r59):
moraes#yukon:~/dev/repos/gorilla/gorilla/mux$ gotest
rm -f _test/gorilla.googlecode.com/hg/gorilla/mux.a
make -C gorilla.googlecode.com/hg/gorilla/context install
make: *** gorilla.googlecode.com/hg/gorilla/context: No such file or directory. Stop.
make: *** [gorilla.googlecode.com/hg/gorilla/context.make] Error 2
gotest: "/home/moraes/dev/repos/go/go.r59/bin/gomake testpackage GOTESTFILES=mux_test.go" failed: exit status 2
I tried goinstalling the dependency first (goinstall gorilla.googlecode.com/hg/gorilla/context), and it installs correctly in $GOROOT/pkg but the same error occurs with gotest/gomake.
I think I'm missing something pretty basic. How should I proceed to use gomake/gotest with the Makefile above? Is this supposed to work at all, or should I use a different one for development?
goinstall doesn't use the Makefile at all. Instead, it will parse dependencies directly from your .go files.
To specify dependencies, annotate your import lines with a "normalised" reference to the dependency. eg.
import (
gorilla_context "gorilla.googlecode.com/hg/gorilla/context"
...
gomake doesn't automatically resolve dependencies though, so you'll have to manually install them.
Similarly, for installing cgo source with goinstall, you can specify CFLAGS and LDFLAGS in comment directives. eg.
/*
#cgo CFLAGS: -I/usr/local/include
#cgo LDFLAGS: -L/usr/local/lib -lzmq
#include <zmq.h>
*/
import "C"
I think the Makefile is trying to find the file gorilla.googlecode.com/hg/gorilla/context in the current directory. Also, why would you want to specify it in a make file as opposed to importing it from within the Source?
Related
I am working on a smallish Go application that uses Cgo. I'm working on it on a Linux VM, and Linux is the main target environment. However, I have a need to also create a Windows executable. Normally, cross-compiling Go is trivial, but Cgo adds some complications. I've noticed at least two issues, but I'll only ask about the first problem here.
My application only has a single source file that requires Cgo, and the only difference between the Windows and Linux build is the lib path.
This is what I have so far for the beginning of the Cgo header. After this are some include file references:
/*
#cgo CFLAGS: -g -Wall -I${SRCDIR}/../include/v6.21.0
#cgo linux LDFLAGS: -L${SRCDIR}/../lib/linux/v6.21.0 -lvibesimple -lcurl -lssl -lvibecrypto -lvibeictk -lvibeserver
#cgo windows LDFLAGS: -L${SRCDIR}/../lib/windows/v6.21.0 -lvibesimple -lcurl -lssl -lvibecrypto -lvibeictk -lvibeserver
When I build this on Linux, or with GOOS=linux, it works fine.
When I build this for Windows, I get this:
$ GOOS=windows go build -o target/dist/windows-amd64
package voltagems
imports voltagems/app
imports voltagems/handlers
imports voltagems/voltagefuncs: build constraints exclude all Go files in /home/<uid>/git/voltagego/voltagefuncs
I know that I can create files ending in "_linux.go" or "_windows.go", but that would be painful. That would mean duplicating the entire source file, and having to maintain both copies.
I am trying to include the libsodium into my Go project. For that, I've copied the repo inside my project
// #cgo CFLAGS: -I/mypath/libsodium/src/libsodium/include/sodium
// #include <stdlib.h>
// #include "crypto_sign_ed25519.h"
import "C"
When trying to build the project I get the following error:
/tmp/go-build/cgo-gcc-prolog:53: undefined reference to `crypto_sign_ed25519_pk_to_curve25519'
collect2: error: ld returned 1 exit status
The file can be found but the error is there.
I've also tried to reference the '.c' file as well as to copy the crypto_sign_ed25519.h into the src folder but it does not work.
My question is do I have to add LDFLAGS and therefore generate a .so file from the library or that is not needed and there is another possible way of doing it?
UPDATE: I've achieved to make it running by installing the library on my local ubuntu:
$ ./configure
$ make && make check
$ sudo make install
and adding
// #cgo LDFLAGS: -L/usr/local/lib -lsodium
But how can I do it without adding the local path?
You indeed need to link the library, the headers themselves are only the interface to the library and don't link the actual libsodium code to your binary.
Assuming libsodium ships a pkg-config file (it seems to be the case), you can use something like
// #cgo pkg-config: libsodium
// #include "crypto_sign_ed25519.h"
See https://golang.org/cmd/cgo/ for more information about pkg-config support.
To see what cflags/libs you'd be getting (so what cgo will use), run:
pkg-config --cflags --libs libsodium
After manually installing a library on Linux, you have to type ldconfig so that the linker becomes aware of it.
Also, in order to get libsodium prototypes, you should simply include <sodium.h> not <sodium/crypto_sign_ed25519.h> (not meant to be included directly), and call sodium_init() before any other function so that internal data structures are properly initialized.
See how this is done in existing bindings for Go: https://github.com/jamesruan/sodium/blob/master/core.go
You may want to use these bindings instead of reinventing your own. If they are missing some of the functions you need, their maintainers will probably be happy to accept your pull requests.
The two main Go bindings for libsodium that I am aware of are sodium and libsodium-go.
Let's say I want to use some awesome go package. I can include it by:
import "github.com/really-awesome/project/foobar"
And inside that project's foobar.go file, it defines some cgo instructions like:
#cgo windows CFLAGS: -I C:/some-path/Include
#cgo windows LDFLAGS: -L C:/some-path/Lib -lfoobar
But if I have that foobar C dependency installed somewhere else, I would really need those lines to say:
#cgo windows CFLAGS: -I C:/different-path/Include
#cgo windows LDFLAGS: -L C:/different-path/Lib -lfoobar
Is there a way to override or trump where cgo is looking for these dependencies? Right now my fix is to manually edit those two lines after running go get ./... which will fetch the github.comreally-awesome/project/foobar code.
NOTE: I'm using the MinGw compiler, though I doubt that matters.
update:
I have tried adding flags to go build to no avail:
go build -x -gcflags="-I C:/different/include -L C:/different-path/lib -lfoobar"
go build -x -ccflags="-I C:/different/include" -ldflags="-L C:/different-path/lib -lfoobar"
With the -x argument I see the printout of flags and they don't include the ones I am setting on the command line. Perhaps the #cgo CFLAGS/LDFLAGS statements at the top of the external go package squash what I am telling it to use...
You can do this by setting the CGO_CPPFLAGS and CGO_LDFLAGS environment variables.
For example, on my MacBook, Homebrew is installed in ~/.homebrew (instead of /usr/local), so when I try to go get packages with native bindings they can't find the headers and libs.
To fix that I added these two lines to my ~/.zshenv file:
export CGO_CPPFLAGS="-I $BREW_HOME/include"
export CGO_LDFLAGS="-L $BREW_HOME/lib"
This is kind of the role filled by #cgo pkgconfig: foobar. If the library had been written that way, it would pick up the correct paths from foobar's pkgconfig definition.
I realise its not a direct answer to the question, and that pkgconfig isn't exactly a native windows tool... I'd be interested to hear if any other solutions exist.
I have a situation where I've refactored some code, and moved an include file.
Attempting to build the source tree yields an error:
make: *** No rule to make target `cmd/dispatcher.h', \
needed by `/tmp/test/dispatcher/main.o'. Stop.
If I do a make clean (which removes the outdated main.o file), and then rebuild I get a different error:
...src/test/dispatcher/main.cpp:3:28: fatal error: cmd/dispatcher.h: \
No such file or directory
Question:
Is there any way to invalidate main.o when one of its dependencies is missing?
There's no magic in make. If main.o depends on dispatcher.h, then it is written somewhere.
I suspect your Makefile runs gcc with the -MD or -MDD option that creates a dependency file. Usually they are named with a .d suffix. These dependencies files are automatically created by gcc as Makefile content: target: dependencies.
These files are then included into the main Makefile to provide the full automagic dependencies.
You should look for these .d files and remove them.
I am trying to build a certain library under cygwin (OpenEXR), and I get the following error:
b44ExpLogTable.cpp:52:18: error: half.h: No such file or directory
half.h is referenced using #include <half.h>, and is actually a part of another library I successfully run make/make install on previously.
The question is -- when using #include with <>, where the preprocessor expects to find the specified file?
(I have just found it in /usr/local/include/OpenEXR, but I have no idea why preprocessor cannot).
Update: I have also found:
Makefile
ILMBASE_CXXFLAGS = -I/usr/local/include/OpenEXR
Makefile.am
INCLUDES = #ILMBASE_CXXFLAGS# \
-I$(top_builddir) \
-I$(top_srcdir)/config
This actually decreased my understanding of what the problem may be.
Update 2: So, by redefining some variables in makefile I found out that instead of $(CXXCOMPILE) make seems to run $(CXX) $(CXXFLAGS), with CXXFLAGS being just -g -O2. Ok, I have no idea how it manages to run $(CXX) $(CXXFLAGS) if this combination in not used anywhere in the makefile except in $(CXXCOMPILE) which is not run. I can add my -I to CXXFLAGS but I have a feeling that a lot more additions will be required, so I would prefer to find a root cause of the problem.
(I am not sure whether it is a Super User or Stack Overflow question, because my developer skills in C++/Linux are almost non-existent.)
Additional include directories are usually specified in CPPFLAGS. Try running ./configure CPPFLAGS=-I/usr/local/include/OpenEXR and re-running make.
You need to somehow get -I/usr/local/include/OpenEXR added to the compiler command line. That might be a simple matter of doing:
CFLAGS=-I/usr/local/include/OpenEXR make