Include libsodium using cgo in go project fails - go

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.

Related

Linking ports libraries under FreeBSD

I have built some libraries (gtk3, qt5, ...) through the ports collection under FreeBSD 11.2. In order to test them I just built minimal examples. Each time the linker complains about not finding these libraries.
Correct me if I am wrong, but under FreeBSD, regular packages (those which are setup with pkg) are installed under /usr/include and /usr/lib, however ports lie, by default, under /usr/local/include and /usr/local/lib.
Is there a simple way to tell the compiler to search under these directories rather than having huge compilation commands with the -I and -L options?
Thank you for your answers.
Edit
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(gtk-test)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
find_package(GTK3 REQUIRED)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_executable(gtk-test gtk-test.c)
target_link_libraries(gtk-test ${GTK3_LIBRARIES})
I have solved the dependencies issue by grabbing the following CMake script:
https://github.com/eiskaltdcpp/eiskaltdcpp/blob/master/cmake/FindGTK3.cmake
However, another problem has pop up:
[100%] Linking C executable gtk-test
/usr/lib/crt1.o: In function `_start':
crt1.c:(.text+0x91): undefined reference to `main'
collect2: error: ld returned 1 exit status
Edit
I am stupid, I even did not notice that there was no main function in the sample. It works fine except that, by default, CMake cannot locate GTK3 library and its dependencies.
Here is the content of my CMake config scripts:
Qt5
Qt53DQuick
Qt53DRender
Qt5DataVisualization
Qt5Location
Qt5OpenGLExtensions
Qt5QuickTest
Qt5SerialBus
Qt5UiPlugin
Qt5WebKit
Qt5XmlPatterns
Qt53DAnimation
Qt53DQuickAnimation
Qt5Bluetooth
Qt5Designer
Qt5Multimedia
Qt5Positioning
Qt5QuickWidgets
Qt5SerialPort
Qt5UiTools
Qt5WebKitWidgets
assimp-4.1
Qt53DCore
Qt53DQuickExtras
Qt5Charts
Qt5Gamepad
Qt5MultimediaWidgets
Qt5PrintSupport
Qt5Script
Qt5Sql
Qt5WebChannel
Qt5WebSockets
harfbuzz
Qt53DExtras
Qt53DQuickInput
Qt5Concurrent
Qt5Gui
Qt5Network
Qt5Qml
Qt5ScriptTools
Qt5Svg
Qt5WebEngine
Qt5Widgets
libxml2
Qt53DInput
Qt53DQuickRender
Qt5Core
Qt5Help
Qt5Nfc
Qt5Quick
Qt5Scxml
Qt5Test
Qt5WebEngineCore
Qt5X11Extras
Qt53DLogic
Qt53DQuickScene2D
Qt5DBus
Qt5LinguistTools
Qt5OpenGL
Qt5QuickControls2
Qt5Sensors
Qt5TextToSpeech
Qt5WebEngineWidgets
Qt5Xml

cannot use ceres solver,glog

I install ceres in ubuntu and use the all of the command line in http://ceres-solver.org/installation.html Linux part from
sudo apt-get install libgoogle-glog-dev
all the way to
make install
Seems I have installed ceres solver and it dependency without problem.
But when I try to run the test file
bin/simple_bundle_adjuster ../ceres-solver-1.12.0/data/problem-16-22106-pre.txt
It shows
unable to open file ../ceres-solver-1.9.0/data/problem-16-22106-pre.tx
Then I try to compile helloworld in tutorial use command
g++ -I/usr/include/eigen3 helloworld.cpp -o helloworld
It gives me a bunch of problems.
undefined reference to google::InitGoogleLogging(char const*)'
helloworld.cpp:(.text+0x104): undefined reference toceres::Problem::Problem()'
helloworld.cpp:(.text+0x155): undefined reference to `ceres::Problem::AddResidualBlock(ceres::CostFunction*, ceres::LossFunction*, double*)'
I didn't list them all. But seems it cannot find things about google at all.
Hope you can help me!!
it gives me a mountain of problems.
Sounds like you're not linking to the library; this would cause references to be undefined. If you are calling the linker (G++ can be the linker), then add -lglog add the end, it should then link it to glog.
Similarly, you should also link to ceres.
Here's a snippet from the things I need to link to use a library which uses Ceres. In CMake. I suggest you start at the bottom/end and add things to the top to fix, you may need to prefix with -l to indicate that you need to link them.
I recommend using cmake, so that you can simply paste this list in a target_link_libraries(myexecutable listhere) and remove unnecessary/unused libraries;
umfpack
cxsparse
stlplus
glog
gomp
ccolamd
btf
klu
cholmod
lapack
blas
camd
amd
pthread
ceres

Override an external package's cgo compiler and linker flags?

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.

Using gomake/gotest for a package with external dependencies

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?

configure.in: AM_DISABLE_SHARED doesn't change my Makefile

I'm extremely new to using Makefiles and autoconf. I'm using the Camellia image library and trying to statically link my code against their libraries. When I run "make" on the Camellia image library, I get libCamellia.a, .so, .la, and .so.0.0.0 files inside my /usr/local/lib directory. This is the command I use to compile my code with their libraries:
gcc -L/usr/local/lib -lCamellia -o myprogram myprogram.c
This works fine, but when I try to statically link, this is what I get:
gcc -static -L/usr/local/lib -lCamellia -o myprogram myprogram.c
/tmp/cck0pw70.o: In function `main':
myprogram.c:(.text+0x23): undefined reference to `camLoadPGM'
myprogram.c:(.text+0x55): undefined reference to `camAllocateImage'
myprogram.c:(.text+0x97): undefined reference to `camZoom2x'
myprogram.c:(.text+0x104): undefined reference to `camSavePGM'
collect2: ld returned 1 exit status
I want to statically link because I'm trying to modify the Camellia source code and I want to compare my version against theirs. So after some googling, I tried adding AM_DISABLE_SHARED into the configure.in file. But after running ./configure, I still get the exact same Makefile. After I "make install", I still get the same results above.
What is an easy way to get two versions of my code, one with the original Camellia source code compiled and one with my modified version? I think static libraries should work. There is an easy way to get static libraries working or are there other simple solutions to my problem? I just don't want to re-"make" and re-"make install" everytime I want to compare my version against the original.
Did you re-run autoconf after adding AM_DISABLE_SHARED and before configure, make, make install? You also can just use configure --disable-dynamic to stop it building the shared libraries. Make sure you delete any previously installed ones - make uninstall should do that. I can't see anything else obviously wrong. Try being explicit:
gcc -static -o myprogram myprogram.c /usr/local/lib/libCamellia.a
or break it down into two steps and check the symbols in myprogram.o are what you expect with nm myprogram.o.
I am not skillful with autoconf and I don't know why your attempt to link statically fails, but if linking dynamically works I think using shared libraries would actually solve your problem a little better.
Just make two shared libraries, one with the original Camellia code and one with your modified version. Put them in two different directories, and when you run myprogram you can choose between them either by switching LD_LIBRARY_PATH (or whatever you're using to find libraries) or by keeping a symbolic link in /usr/local/lib and switching it between libraries. The advantage of this over static libraries (apart from the fact that this works) is that you can tinker with your modified code, rebuild the shared library and run without having to rebuild myprogram (as long as you don't modify the signatures).
P.S. An experiment: try removing the shared libraries from /usr/local/lib and rebuilding without the -static flag, just as if you were using the shared libraries. In theory this should cause gcc to use the static libraries instead. The results may give a clue to why the static link is failing.

Resources