I am trying to use a shared library in go-lang, I am following this blog post: http://blog.ralch.com/tutorial/golang-sharing-libraries/
But when I hit build I get back an error:
simo#simo:~/gopath$ go build -linkshared -o app effe/prova
src/effe/prova/prova.go:3:8: cannot find package "libmath" in any of:
/usr/local/go/src/libmath (from $GOROOT)
/home/simo/gopath/src/libmath (from $GOPATH)
I am pretty new to go, so I will show also my environment...
simo#simo:~/gopath$ pwd
/home/simo/gopath
simo#simo:~/gopath$ echo $GOPATH
/home/simo/gopath
simo#simo:~/gopath$ tree
.
├── pkg
│ └── linux_amd64_dynlink
│ ├── effe
│ │ ├── libmath.a
│ │ └── libmath.shlibname
│ └── libeffe-libmath.so
└── src
└── effe
├── libmath
│ └── libmath.go
└── prova
└── prova.go
7 directories, 5 files
simo#simo:~/gopath$ cat src/effe/libmath/libmath.go
// filename: libmath.go
package libmath
func Sum(x, y int) int {
return x + y
}
simo#simo:~/gopath$ cat src/effe/prova/prova.go
package main
import "libmath"
import "fmt"
func main() {
fmt.Printf("5 op 10 => %d", libmath.Sum(5, 10))
}
simo#simo:~/gopath$ go install -buildmode=shared -linkshared effe/libmath
simo#simo:~/gopath$ go build -linkshared -o app effe/prova
src/effe/prova/prova.go:3:8: cannot find package "libmath" in any of:
/usr/local/go/src/libmath (from $GOROOT)
/home/simo/gopath/src/libmath (from $GOPATH)
What am I doing wrong ?
The import path for "libmath" is "effe/libmath".
Try to get your build working in the standard build mode before experimenting with more complicated build and execution modes.
Related
Using Arch Linux and I have Ctag 5.8 installed.
My Go project has this structure:
.
├── apply
│ └── apply.go
├── calculate
│ └── calculate.go
├── coupon.sqlite3
├── Godeps
│ ├── Godeps.json
│ └── Readme
├── main.go
├── Makefile
├── models
│ ├── cupom.go
│ ├── errorMessage.go
│ └── product.go
├── ping
│ └── ping.go
├── README.md
├── routes
│ └── routes.go
├── tags
├── tests
│ ├── apply_test.go
│ ├── calculate_test.go
│ ├── config.go
│ ├── coupon.sqlite3
│ └── fixtures
│ └── calculate.go
Running the command ctags -R or ctags -R . I have a tags file generated but with this content only.
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert#users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
Running the same command on other project generate the tags file correctly.
You have Exuberant Ctags installed, which does not support Go out of the box (http://ctags.sourceforge.net/languages.html).
There are a bunch of different alternative programs or ways to add it to your existing ctags:
https://go-wise.blogspot.ca/2011/09/using-ctags-with-go.html
https://github.com/eapache/starscope
https://github.com/jstemmer/gotags
http://ctags.sourceforge.net/EXTENDING.html
Running a go run main.go I get a strange error message:
danilo#lm ~/godev/src/quick $ go run main.go
command-line-arguments
/usr/lib/go-1.6/pkg/tool/linux_amd64/link: cannot open file /usr/lib/go-1.6/pkg/linux_amd64/github.com/valyala/quicktemplate.a: open /usr/lib/go-1.6/pkg/linux_amd64/github.com/valyala/quicktemplate.a: no such file or directory`
Here is my environment:
Linux Mint 18
GOLANG ENV:
danilo#lm ~/godev/src/quick $ go env
GOARCH="amd64"
GOBIN="/home/danilo/godev/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/danilo/godev"
GORACE=""
GOROOT="/usr/lib/go-1.6"
GOTOOLDIR="/usr/lib/go-1.6/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
My $GOPATH tree:
.(godev)
├── bin
│ └── qtc
├── pkg
│ └── linux_amd64
│ └── github.com
│ └── valyala
│ ├── bytebufferpool.a
│ └── quicktemplate.a
└── src
├── github.com
│ └── valyala
│ ├── bytebufferpool
│ │ ├── ...
│ └── quicktemplate
│ ├── ...
└── quick
├── main.go
└── templates
├── hello.qtpl
└── hello.qtpl.go
It seems like to miss the pkg folder in my workspace where the static libraries are stored!
Am I right?
Sorry, I solved. The main.go code was:
package main
import (
"fmt"
"./templates"
)
func main() {
fmt.Printf("%s\n", templates.Hello("Foo"))
fmt.Printf("%s\n", templates.Hello("Bar"))
}
so I missed to use absolute path in the import section:
package main
import (
"fmt"
"quick/templates"
)
func main() {
fmt.Printf("%s\n", templates.Hello("Foo"))
fmt.Printf("%s\n", templates.Hello("Bar"))
}
I'm trying to add a shared library to my project using CMake. The library is MsgPack for C++11. I must be doing something wrong because none of the examples here compile. I get this error:
error: no match for ‘operator<<’ (operand types are
‘MsgPack::Serializer’ and ‘std::unique_ptr’)
serializer << MsgPack__Factory(Array(std::move(arrayWith3Elements)));
My guess is that it has to do with my CMake syntax. The file system tree where I keep the compiled library looks like this:
/home/I/direcytory/MsgPack/
├── include
│ ├── Container.h
│ ├── ContainerHeader.h
│ ├── Core.h
│ ├── Data.h
│ ├── Element.h
│ ├── Header.h
│ ├── MsgPack.h
│ ├── MsgPackSocket.h
│ ├── netLink.h
│ ├── Number.h
│ ├── Primitive.h
│ ├── Socket.h
│ ├── StreamManager.h
│ └── Utf8.h
├── libnetLink.a
└── libnetLink.so
In CMake I'm doing this:
cmake_minimum_required(VERSION 3.0.2)
project(MyProject)
add_library(libnetLink SHARED IMPORTED)
SET_PROPERTY(TARGET libnetLink PROPERTY IMPORTED_LOCATION /home/I/Direcytory/MsgPack/libnetLink.so)
set(SOURCE_FILES main.cpp)
include_directories("/home/I/Direcytory/MsgPack/include")
target_link_libraries(MyProject libnetLink)
CMake doesn't report any errors, but my program won't compile.
It's worth noting, the above method has worked fine for me with other libraries. That's what has me confused.
In SCons when a folder is installed the dependency tree is not aware of the contents of the folder. This means that implicit relationships cannot be created.
env.Install("out/bin","path/to/folder")
env.Install("out/archive", Glob("out/bin/folder/library.lib"))
In this sample code the Glob returns [] because SCons is unaware the folder contains a file called library.lib.
The only workaround I've found for this is to walk the directory and install each individual file.
Does the SCons Install not have an option to do this for you?
I have run into this as well. I have not found any other solution than to walk the directories as you describe. Though the contents of the folder are copied, to SCons there is just one target, and just one source, unless you specify each one individually.
import os
def recursive_install(target, source, env):
source_dirname = os.path.dirname(source)
for root, dirnames, filenames in os.walk(source):
for filename in filenames:
env.Install(os.path.join(
target, os.path.relpath(root, os.path.dirname(source))),
os.path.join(root, filename))
env = Environment()
recursive_install("out/bin", "path/to/folder", env)
env.Install("out/archive", "out/bin/folder/library.lib")
Which when run produces...
>> scons --version
SCons by Steven Knight et al.:
script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation
>> tree
.
├── path
│ └── to
│ └── folder
│ └── library.lib
└── SConstruct
3 directories, 2 files
>> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Install file: "path/to/folder/library.lib" as "out/bin/folder/library.lib"
Install file: "out/bin/folder/library.lib" as "out/archive/library.lib"
scons: done building targets.
>> tree
.
├── out
│ ├── archive
│ │ └── library.lib
│ └── bin
│ └── folder
│ └── library.lib
├── path
│ └── to
│ └── folder
│ └── library.lib
└── SConstruct
7 directories, 4 files
SCons doesn't have an option for recursively installing all files under a top-folder, because that's considered to be a rare case (note, how SCons prefers in-source-tree builds, such that you'd have to exclude a lot of files from the Install call otherwise). If you are creating the "files to install" within the same build, the preferred method would be to use the emitted list of targets from your Builder, and put it as second argument to the Install method:
mylibs = env.AnyBuilder('library', sources)
env.Install("out/bin", mylibs)
Then you don't have to manually list all the target files again with a recursive os.walk as in Kenneth's answer.
Problem
I haven't been able to find a solution to this by looking at related questions. I can't tell what makes my Go environment different from the canonical setup.
go env returns
GOROOT="/usr/lib/go"
GOBIN=""
GOARCH="386"
GOCHAR="8"
GOOS="linux"
GOEXE=""
GOHOSTARCH="386"
GOHOSTOS="linux"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_386"
GOGCCFLAGS="-g -O2 -fPIC -m32 -pthread"
CGO_ENABLED="1"
tree $GOPATH returns
/home/USER/go
├── bin
├── pkg
│ └── linux_386
│ └── bitbucket.org
│ └── USER-NAME
│ └── PROJECT
│ └── my_package.a
└── src
└── bitbucket.org
└── USER-NAME
└── PROJECT
├── main
│ ├── main.go
└── my_package
└── my_package.go
(ALL-CAPS are substitutions)
main.go contains
package main
import (
"bitbucket.org/USER-NAME/PROJECT/my_package"
)
func main() {
my_package.Foo()
}
Calling go build in the main directory returns import "my_package": cannot find package
Volker pointed out that go env should have returned a GOPATH entry as well. The source of the env command corroborates that. However, running echo $GOPATH in bash or os.Getenv("GOPATH") in Go both return \home\USER\go. I'm not sure why the same isn't returned by go env.
Solution
I was running Go 1.0 when I was having this issue. The problem disappeared when I upgraded to Go 1.2.1.
You have a directory called main. This won't work. Change it.
Structure it like $GOPATH/src/bitbucket.com/youruser name/yourpackagename/{main.go, otherthing.go, otherpackagedirectory}.
"package main" doesn't have to be in it's own sub folder: it inherits the name of your Bitbucket project (username/myprojectname).
You did not set (or export) GOPATH. GOPATH Is much more important than GOROOT (at least in newe Go versions).