Linker fails with NBIS library - c++

I am trying to use the NBIS library on OS X, but I am getting a problem:
Undefined symbols for architecture x86_64:
"distance(int, int, int, int)", referenced from:
_main in test-2db11c.o
ld: symbol(s) not found for architecture x86_64
I tried using the .a archive, as well as the .o files in there - no luck - same problem.
The source code I am trying to compile (test.cpp):
#include <iostream>
#include <lfs.h>
using namespace std;
int main() {
cout << distance(1, 2, 3, 4) << endl;
}
Here are the execution lines that I tried (unsuccessfully):
$> g++ -std=c++11 -ggdb -g -Wall test.cpp -o test.bin -lm -lc++
$> g++ -std=c++11 -ggdb -g -Wall test.cpp -o test.bin -lm -lc++ -L/NBIS/Main/lib -lmindtct
$> g++ -std=c++11 -ggdb -g -Wall test.cpp -o test.bin -lm -lc++ -L/NBIS/Main/lib -l:libmindtct.a
$> g++ -std=c++11 -ggdb -g -Wall test.cpp /NBIS/Main/lib/libmindtct.a -o test.bin -lm -lc++
$> g++ -std=c++11 -ggdb -g -Wall test.cpp /NBIS/Main/lib/util.o -o test.bin -lm -lc++
Just to confirm that the libraries actually have the method declared, I checked what is inside the libmindtct.a archive:
$> ar t libmindtct.a
__.SYMDEF SORTED
<MANY FILES .o>
util.o
<SOME MORE .o FILES>
$> ar -x libmindtct.a util.o
$> nm util.o
U ___stderrp
00000000000008d0 T _angle2line
U _atan2
0000000000000a10 T _closest_dir_dist
0000000000000600 T _distance
00000000000008a0 T _find_incr_position_dbl
U _fmod
U _free
U _fwrite
0000000000000650 T _in_int_list
0000000000000920 T _line2direction
U _malloc
0000000000000000 T _maxv
0000000000000360 T _minmaxs
00000000000001b0 T _minv
0000000000000690 T _remove_from_int_list
0000000000000630 T _squared_distance
To compile the library I use the following:
$> cd ~/Downloads/NBIS/
$> ./setup.sh /NBIS/Main --64
$> make config && make it && make install LIBNBIS=no && make catalog

lfs.h from NBIS is C only. You need to enable C linkage for lfs.h:
extern "C" {
#include <lfs.h>
}
Additionally, you should not need to manually link libc++ or libm using g++.

Related

How to build zlib library on a m1 chip macbookpro?

I downloaded zlib from https://zlib.net/ and execute ./configure and make cmd. However, it shows that there are some undefined symbols for architecture arm64. How to build zlib in this case?
I'm using a macbookpro 2021 with apple m1pro chip.
The full info is:
~/GitClone/zlib-1.2.11 > ./configure at 15:42:53
Checking for gcc...
Checking for shared library support...
Building shared library libz.1.2.11.dylib with gcc.
Checking for size_t... Yes.
Checking for off64_t... No.
Checking for fseeko... Yes.
Checking for strerror... Yes.
Checking for unistd.h... Yes.
Checking for stdarg.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.
Checking for attribute(visibility) support... Yes.
~/GitClone/zlib-1.2.11 > make at 15:43:13
gcc -O3 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
gcc -O3 -DHAVE_HIDDEN -c -o adler32.o adler32.c
gcc -O3 -DHAVE_HIDDEN -c -o crc32.o crc32.c
gcc -O3 -DHAVE_HIDDEN -c -o deflate.o deflate.c
gcc -O3 -DHAVE_HIDDEN -c -o infback.o infback.c
gcc -O3 -DHAVE_HIDDEN -c -o inffast.o inffast.c
gcc -O3 -DHAVE_HIDDEN -c -o inflate.o inflate.c
gcc -O3 -DHAVE_HIDDEN -c -o inftrees.o inftrees.c
gcc -O3 -DHAVE_HIDDEN -c -o trees.o trees.c
gcc -O3 -DHAVE_HIDDEN -c -o zutil.o zutil.c
gcc -O3 -DHAVE_HIDDEN -c -o compress.o compress.c
gcc -O3 -DHAVE_HIDDEN -c -o uncompr.o uncompr.c
gcc -O3 -DHAVE_HIDDEN -c -o gzclose.o gzclose.c
gcc -O3 -DHAVE_HIDDEN -c -o gzlib.o gzlib.c
gcc -O3 -DHAVE_HIDDEN -c -o gzread.o gzread.c
gcc -O3 -DHAVE_HIDDEN -c -o gzwrite.o gzwrite.c
libtool -o libz.a adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
gcc -O3 -DHAVE_HIDDEN -o example example.o -L. libz.a
ld: warning: ignoring file libz.a, building for macOS-arm64 but attempting to link with file built for macOS-arm64
Undefined symbols for architecture arm64:
"_compress", referenced from:
_test_compress in example.o
(maybe you meant: _test_compress)
"_deflate", referenced from:
_test_deflate in example.o
_test_large_deflate in example.o
_test_flush in example.o
_test_dict_deflate in example.o
(maybe you meant: _test_large_deflate, _test_deflate , _test_dict_deflate )
"_deflateEnd", referenced from:
_test_deflate in example.o
_test_large_deflate in example.o
_test_flush in example.o
_test_dict_deflate in example.o
"_deflateInit_", referenced from:
_test_deflate in example.o
_test_large_deflate in example.o
_test_flush in example.o
_test_dict_deflate in example.o
"_deflateParams", referenced from:
_test_large_deflate in example.o
"_deflateSetDictionary", referenced from:
_test_dict_deflate in example.o
"_gzclose", referenced from:
_test_gzio in example.o
"_gzerror", referenced from:
_test_gzio in example.o
"_gzgetc", referenced from:
_test_gzio in example.o
"_gzgets", referenced from:
_test_gzio in example.o
"_gzopen", referenced from:
_test_gzio in example.o
"_gzprintf", referenced from:
_test_gzio in example.o
"_gzputc", referenced from:
_test_gzio in example.o
"_gzputs", referenced from:
_test_gzio in example.o
"_gzread", referenced from:
_test_gzio in example.o
"_gzseek", referenced from:
_test_gzio in example.o
"_gztell", referenced from:
_test_gzio in example.o
"_gzungetc", referenced from:
_test_gzio in example.o
"_inflate", referenced from:
_test_inflate in example.o
_test_large_inflate in example.o
_test_sync in example.o
_test_dict_inflate in example.o
(maybe you meant: _test_large_inflate, _test_inflate , _test_dict_inflate )
"_inflateEnd", referenced from:
_test_inflate in example.o
_test_large_inflate in example.o
_test_sync in example.o
_test_dict_inflate in example.o
"_inflateInit_", referenced from:
_test_inflate in example.o
_test_large_inflate in example.o
_test_sync in example.o
_test_dict_inflate in example.o
"_inflateSetDictionary", referenced from:
_test_dict_inflate in example.o
"_inflateSync", referenced from:
_test_sync in example.o
"_uncompress", referenced from:
_test_compress in example.o
"_zlibCompileFlags", referenced from:
_main in example.o
"_zlibVersion", referenced from:
_main in example.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [example] Error 1
The clang version and environment variable is like:
~ > clang --version at 16:22:31
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
~ > clang++ --version at 16:22:34
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
~ > echo $PATH at 16:22:37
/usr/local/include:/opt/homebrew/Cellar/binutils/2.38_1/bin:/Users/hanxiaohao/.npm-global/bin:/Library/Java/JavaVirtualMachines/jdk-18.0.2.jdk/Contents/Home/bin:/opt/homebrew/Cellar/binutils/2.38_1/bin:/Users/hanxiaohao/.npm-global/bin:/Library/Java/JavaVirtualMachines/jdk-18.0.2.jdk/Contents/Home/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/hanxiaohao/Library/Application Support/JetBrains/Toolbox/scripts:/opt/homebrew/Cellar/maven/3.6.3/bin:/opt/homebrew/Cellar/maven/3.6.3/bin
Not reproducible.
Tested on M1 Max macOS 12.5.1 with XCode 13.4.1 and Homebrew in the /opt/homebrew directory.
I noticed you have /usr/local/include and /usr/local/bin in your path. Those should be non-existent on M1 macOS. They were for Homebrew Intel.
% ls -l /usr/local/include /usr/local/bin
ls: /usr/local/bin: No such file or directory
ls: /usr/local/include: No such file or directory
Here is the run log of my test:
% ./configure
Checking for gcc...
Checking for shared library support...
Building shared library libz.1.2.12.dylib with gcc.
Checking for size_t... Yes.
Checking for off64_t... No.
Checking for fseeko... Yes.
Checking for strerror... Yes.
Checking for unistd.h... Yes.
Checking for stdarg.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.
Checking for attribute(visibility) support... Yes.
% make
gcc -O3 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
gcc -O3 -DHAVE_HIDDEN -c -o adler32.o adler32.c
gcc -O3 -DHAVE_HIDDEN -c -o crc32.o crc32.c
gcc -O3 -DHAVE_HIDDEN -c -o deflate.o deflate.c
gcc -O3 -DHAVE_HIDDEN -c -o infback.o infback.c
gcc -O3 -DHAVE_HIDDEN -c -o inffast.o inffast.c
gcc -O3 -DHAVE_HIDDEN -c -o inflate.o inflate.c
gcc -O3 -DHAVE_HIDDEN -c -o inftrees.o inftrees.c
gcc -O3 -DHAVE_HIDDEN -c -o trees.o trees.c
gcc -O3 -DHAVE_HIDDEN -c -o zutil.o zutil.c
gcc -O3 -DHAVE_HIDDEN -c -o compress.o compress.c
gcc -O3 -DHAVE_HIDDEN -c -o uncompr.o uncompr.c
gcc -O3 -DHAVE_HIDDEN -c -o gzclose.o gzclose.c
gcc -O3 -DHAVE_HIDDEN -c -o gzlib.o gzlib.c
gcc -O3 -DHAVE_HIDDEN -c -o gzread.o gzread.c
gcc -O3 -DHAVE_HIDDEN -c -o gzwrite.o gzwrite.c
libtool -o libz.a adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
gcc -O3 -DHAVE_HIDDEN -o example example.o -L. libz.a
gcc -O3 -DHAVE_HIDDEN -I. -c -o minigzip.o test/minigzip.c
gcc -O3 -DHAVE_HIDDEN -o minigzip minigzip.o -L. libz.a
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/adler32.o adler32.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/crc32.o crc32.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/deflate.o deflate.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/infback.o infback.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/inffast.o inffast.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/inflate.o inflate.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/inftrees.o inftrees.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/trees.o trees.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/zutil.o zutil.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/compress.o compress.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/uncompr.o uncompr.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/gzclose.o gzclose.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/gzlib.o gzlib.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/gzread.o gzread.c
gcc -O3 -fPIC -DHAVE_HIDDEN -DPIC -c -o objs/gzwrite.o gzwrite.c
gcc -dynamiclib -install_name /usr/local/lib/libz.1.dylib -compatibility_version 1 -current_version 1.2.12 -O3 -fPIC -DHAVE_HIDDEN -o libz.1.2.12.dylib adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo -lc
rm -f libz.dylib libz.1.dylib
ln -s libz.1.2.12.dylib libz.dylib
ln -s libz.1.2.12.dylib libz.1.dylib
gcc -O3 -DHAVE_HIDDEN -o examplesh example.o -L. libz.1.2.12.dylib
gcc -O3 -DHAVE_HIDDEN -o minigzipsh minigzip.o -L. libz.1.2.12.dylib
% gcc --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
% clang --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
% clang++ --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
% uname -a
Darwin Superbook.local 21.6.0 Darwin Kernel Version 21.6.0: Wed Aug 10 14:28:23 PDT 2022; root:xnu-8020.141.5~2/RELEASE_ARM64_T6000 arm64

How to compile with cutil?

I am using a code from someone else. When compiling it I got the following error: " référence indéfinie vers « CUtil::CUtil() ".
I guess I am missing a package or library? Or is it a problem with my compiler? (gcc version 5.4.0).
I am on ubuntu.
Any idea how I should procees to be able to compile?
Edit: it is a linkage issue. I have all the files I need in mu directory and here is the script to compile:
g++ -c -Wall -fPIC GeoConvert.cpp
g++ -c -Wall -fPIC GlobalFunctions.cpp
g++ -c -Wall -fPIC Util.cpp
g++ -c -Wall -fPIC TbwInput.cpp
g++ -shared -o libTbwInput.so GeoConvert.o GlobalFunctions.o Util.o TbwInput.o
g++ -c -Wall -fPIC Atmosphere.cpp
g++ -c -Wall -fPIC GlobalFunctions.cpp
g++ -c -Wall -fPIC Interface.cpp
g++ -c -Wall -fPIC WriteInputFile.cpp
g++ -shared -o libInterface.so Atmosphere.o GlobalFunctions.o Interface.o WriteInputFile.o
g++ -c -Wall -fPIC CalllTBWinterface.cpp
#g++ -c -Wall -fPIC stdafx.cpp
g++ -shared -o libTBWinterfaceWrapper.so CalllTBWinterface.o #stdafx.o
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:'/home/bomble/TIARE/HasanKhan/MDO_GITHUB/All Libraries/1.TBWinterfaceWrapper/'
g++ -o TBWinterfaceWrapper TBWinterfaceWrapper.cpp -L'/home/bomble/TIARE/HasanKhan/MDO_GITHUB/All Libraries/1.TBWinterfaceWrapper' -lTbwInput -lInterface -lTBWinterfaceWrapper
All but the last step go fine. And then I have error about things not find even if they are in the cpp compiled at the beginning....

Build issue with go using SWIG and an external C library

I am trying to create a golang program which will use an external C library.
Before doing complex stuff, I wanted to test the use of SWIG in a small foo example.
I also want to be able to use the "go get" syntax without having to manually run swig. And to take into account that the external C library shall have been built before and can be located anywhere on the machine.
I am using golang 1.12.5 and swig 3.0.12
I have created the following structure:
.
|-- libfoo
| |-- foo.c
| |-- foo.h
| `-- libfoo.so
`-- src
|-- example_test.go
|-- lib.go
`-- libfoo.swig
In the libfoo folder I have a simple shared library. The files contain:
foo.c:
#include "foo.h"
int foo(int c){
return c+1;
};
foo.h
int foo(int c);
That I've compiled it with:
gcc -o ./libfoo.so -fPIC -shared ./foo.c
Then the golang files:
libfoo.swig
%module libfoo
%{
extern int foo(int a);
%}
extern int foo(int a);
lib.go
package libfoo
/*
#cgo LDFLAGS: -L../libfoo -lfoo
*/
import "C"
And finally example_test.go
package libfoo
import (
"testing"
"fmt"
)
func TestFoo(*testing.T) {
i := Foo(1)
fmt.Printf("%v\n",i)
}
When I try to build with "go build -x" It seems that the cgo directives located in the "lib.go" file are not taken into account as I do not see the flag appears in the output. Here is the output
06aa7e308d6:/mnt/data/src# go build -x
WORK=/tmp/go-build551116655
mkdir -p $WORK/b001/
swig -version
cd $WORK
/opt/go/pkg/tool/linux_amd64/compile -o ./b001/_go_.o -trimpath ./b001 -p main -complete -goversion go1.12.5 -D _$WORK -c=4 ./swig_intsize.go
cd /mnt/data/src
swig -go -cgo -intgosize 64 -module libfoo -o $WORK/b001/libfoo_wrap.c -outdir $WORK/b001/ libfoo.swig
CGO_LDFLAGS='"-g" "-O2"' /opt/go/pkg/tool/linux_amd64/cgo -objdir $WORK/b001/ -importpath _/mnt/data/src -- -I $WORK/b001/ -g -O2 ./lib.go $WORK/b001/_libfoo_swig.go
cd $WORK
gcc -fno-caret-diagnostics -c -x c - || true
gcc -Qunused-arguments -c -x c - || true
gcc -fdebug-prefix-map=a=b -c -x c - || true
gcc -gno-record-gcc-switches -c -x c - || true
cd $WORK/b001
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x001.o -c _cgo_export.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x002.o -c lib.cgo2.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x003.o -c _libfoo_swig.cgo2.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x004.o -c libfoo_wrap.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_cgo_main.o -c _cgo_main.c
cd /mnt/data/src
TERM='dumb' gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_cgo_.o $WORK/b001/_cgo_main.o $WORK/b001/_x001.o $WORK/b001/_x002.o $WORK/b001/_x003.o $WORK/b001/_x004.o -g -O2
# _/mnt/data/src
/tmp/go-build551116655/b001/_x004.o: In function `_wrap_foo_libfoo_0f106433f15c8754':
/tmp/go-build/libfoo_wrap.c:255: undefined reference to `foo'
collect2: error: ld returned 1 exit status
If I set the CGO_LDFLAGS using an environment variable, it works. However I want to be able to just use "go get" without having those variables before.
I don't understand why go does not take my #cgo directive into account.
Did I miss something ?
Someone on the golang github repository has solved my issue.
The solution was to remove the newline between the import "C" directive and the comments containing the #cgo directives.

Compiling with -static causes undefined references to functions in other libraries

I'm trying to statically link glibc in order to run my application on an older OS, but when I use the -static flag I get "undefined reference" errors for other libraries I'm using that I don't get without using -static. How do I fix this issue?
My Makefile produces the following commands:
g++ -static -Wall -O3 -w -std=c++11 -I/storage/home/PA/libs -I/storage/home/PA/libs/xerces -fopenmp -c Utilities.cpp
gcc -static -Wall -O3 -w -std=c++11 -I/storage/home/PA/libs -I/storage/home/PA/libs/xerces -fopenmp -c ccvt.c
gcc -static -Wall -O3 -w -std=c++11 -I/storage/home/PA/libs -I/storage/home/PA/libs/xerces -fopenmp -c client.c
g++ -static -Wall -O3 -w -std=c++11 -I/storage/home/PA/libs -I/storage/home/PA/libs/xerces -fopenmp -c XML_Params.cpp
g++ -static -Wall -O3 -w -std=c++11 -I/storage/home/PA/libs -I/storage/home/PA/libs/xerces -fopenmp -c main.cpp
g++ -static -Wall -O3 -std=c++11 -L/storage/home/PA/libs/gsl -fopenmp -lgsl -lgslcblas -lm -L/storage/home/PA/libs/xerces -lxerces-c -o App main.o Utilities.o XML_Params.o ccvt.o client.o
After the last line I get a huge wall of errors complaining about undefined references to Xerces and gsl functions. However, if I remove the -static from the makefile, everything builds fine. What is the proper way to link these libraries when I'm using -static?
according to gcc manual:
-llibrary
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, foo.o -lz bar.o searches library z after
file foo.o but before bar.o. If bar.o refers to functions in z,
those functions may not be loaded.
Move -lxerces after *.o might solve your problem.
I think you don't need to add -static except for the last line, correct me if i'm wrong.

R dyn.load "Symbol not found" error, even though C++ code builds fine

I have a simple C++ program that I can build successfully using clang++ on my Mac (Mavericks) but that fails when built with R CMD SHLIB and loaded with dyn.load in R.
This is the C++ code (stored in simple.cpp), which uses the Gurobi optimizer:
#include "gurobi_c++.h"
#include <iostream>
void fxn() {
GRBEnv env = GRBEnv(); // Create a Gurobi environment
GRBModel colgen = GRBModel(env); // Create empty model object
colgen.addVar(0, 1, 0.0, GRB_BINARY); // Add binary variable to model
std::cout << "Hello world" << std::endl;
}
int main(int argc, char **argv) {
fxn();
return 0;
}
I can successfully compile and run this code using clang++, linking to the Gurobi libraries:
$ clang++ simple.cpp -I/Library/gurobi562/mac64/include \
-L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 -stdlib=libstdc++ \
-lpthread -lm
$ ./a.out
Hello world
I am able to compile successfully with R CMD SHLIB:
$ MAKEFLAGS="PKG_CXXFLAGS=-I/Library/gurobi562/mac64/include" R CMD SHLIB \
simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG \
-I/usr/local/include -I/Library/gurobi562/mac64/include -fPIC -mtune=core2 \
-g -O2 -c simple.cpp -o simple.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup \
-single_module -multiply_defined suppress -L/usr/local/lib -L/usr/local/lib \
-o simple.so simple.o -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm -F/Library/Frameworks/R.framework/.. \
-framework R -Wl,-framework -Wl,CoreFoundation
However, dyn.load("simple.so") fails in R:
Error in dyn.load("simple.so") :
unable to load shared object '[path]/simple.so':
dlopen([path]/simple.so, 6): Symbol not found: __ZN8GRBModel6addVarEdddcNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
Referenced from: [path]/simple.so
Expected in: flat namespace
in [path]/simple.so
From c++filt, I can see that the missing symbol is GRBModel::addVar(double, double, double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >), which should be provided by one of the Gurobi libraries I'm linking.
From previous posts, I've gathered that these "Symbol not found" errors often occur from simply not linking the correct libraries, but I've been able to successfully compile and run simple.cpp and I'm passing the same linking options to R CMD SHLIB.
The following are the contents of my ~/.R/Makevars file:
CC=clang
CXX=clang++
Edit I think the issue might have to do with the option -stdlib=libstdc++ that I'm using when I compile the code. When I remove this option from the first build (the working invocation of clang++), the first linker error I get is:
Undefined symbols for architecture x86_64:
"GRBModel::addVar(double, double, double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_fxn in simple-pRHAEs.o
This is the same undefined symbol that's causing dyn.load to fail.
I solved this issue, which turned out to be related to how I was providing the argument -stdlib=libstdc++ to R CMD SHLIB. R CMD SHLIB invokes clang++ twice, first as a compilation phase to build an object file (simple.o in my case) and then to link that file into a shared object (simple.so in my case). R CMD SHLIB was only passing the -stdlib=libstdc++ argument to the second invocation, but we need it to also provide the argument to the first invocation of clang++. We can do this by adding -stdlib=libstdc++ to PKG_CXXFLAGS:
$ PKG_CXXFLAGS="-I/Library/gurobi562/mac64/include -stdlib=libstdc++" R CMD SHLIB \
simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG \
-I/usr/local/include -I/Library/gurobi562/mac64/include -stdlib=libstdc++ \
-fPIC -mtune=core2 -g -O2 -c simple.cpp -o simple.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup \
-single_module -multiply_defined suppress -L/usr/local/lib -L/usr/local/lib \
-o simple.so simple.o -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm -F/Library/Frameworks/R.framework/.. \
-framework R -Wl,-framework -Wl,CoreFoundation
Now, dyn.load("simple.so") works without error from R (though as mentioned by #MartinMorgan and #JanvanderLaan, I'll need to expose my functions using extern "C" or an alternative to actually be able to call them from R).
R is expecting C linkage, but you've provided C++ linkage. One solution is
#include <iostream>
extern "C" void fxn() {
std::cout << "Hello world" << std::endl;
}
with
$ R --vanilla CMD SHLIB tmp.cpp && R --vanilla -e "dyn.load('tmp.so'); .C('fxn')"
clang++ -I/home/mtmorgan/bin/R-devel/include -DNDEBUG -I/usr/local/include -fpic -ggdb -O0 -c tmp.cpp -o tmp.o
clang++ -shared -L/usr/local/lib -o tmp.so tmp.o -L/home/mtmorgan/bin/R-devel/lib -lR
> dyn.load('tmp.so'); .C('fxn')
Hello world
list()