C++ code compiled with g++ works, but XCode fails - c++

I'm trying to compile a small C++ example in XCode 12.5.1 using the linear algebra library armadillo, which I've installed without problems:
//example.cpp
#include <armadillo>
#include <iostream>
using namespace std;
using namespace arma;
int
main(int argc, char** argv)
{
cout << "Armadillo version: " << arma_version::as_string() << endl;
cx_vec eigval;
cx_mat eigvec;
mat A(3,3,fill::zeros);
eig_gen(eigval, eigvec, A);
cout << A << "\n";
cout << eigval << "\n";
cout << eigvec << "\n";
return 0;
}
Specifically, I'm trying to figure out why the inclusion function eig_gen() gives me linking errors in XCode (removing the function call allows for proper compilation):
Undefined symbols for architecture x86_64:
"_dgeev_", referenced from:
void arma::lapack::geev<double>(char*, char*, int*, double*, int*, double*, double*, double*, int*, double*, int*, double*, int*, int*) in main.o
"_dgeevx_", referenced from:
void arma::lapack::geevx<double>(char*, char*, char*, char*, int*, double*, int*, double*, double*, double*, int*, double*, int*, int*, int*, double*, double*, double*, double*, double*, int*, int*, int*) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Since if I compile the program using g++ on the command line,g++ example.cpp -o example -std=c++11 -O2 -larmadillo, the compilation is successful and the program outputs:
Armadillo version: 10.6.2 (Keep Calm)
0 0 0
0 0 0
0 0 0
(0,0)
(0,0)
(0,0)
(+1.000e+00,+0.000e+00) (+1.000e+00,-0.000e+00) (0,0)
(+0.000e+00,+1.000e+00) (+0.000e+00,-1.000e+00) (0,0)
(0,0) (0,0) (+1.000e+00,+0.000e+00)
The only change I made to XCode's default linking setup (the project is a Command Line Tool project) is to include /usr/local/include in System Header Search Paths, so that I can use the code's first line #include <armadillo>.
Any suggestions as to why XCode specifically might be giving me this error?
############################### Update
I've noticed that if I place the definition #define ARMA_DONT_USE_WRAPPER in the fist line of the program above #include <armadillo>, then the command-line compilation using g++ also outputs the same linking errors. This suggests to me that the error is related to armadillo.

Related

Undefined reference ZGETRI/ZGETREF [duplicate]

I'm currently writing a header-only wrapper library which is supposed to provide C++ access to some FORTRAN code. But I'm stuck at the 'undefined reference (...)'
I must say I'm a little bit surprised because I compiled my own functions in C++ using this FORTRAN routine, with no problems at all.
Maybe a few words about the structure. The library follows the singleton pattern, but without the possibility of instantiating the Library by the user. So the only entry point for the user is a static method MultiNestWrapper::Wrapper<T>::run(). MultiNestWrapper is a namespace, Wrapper<T> is a templated class (so that in future you can benchmark how choosing on which type to perform calculations affects results and performance). The FORTRAN routine is declared outside of this namespace, as
extern "C" {
extern void __nested_MOD_nestrun(int *, int *, int *, double *, double *, int *, int *, int *, int *, int *, double *, const char *, int *, int *, int *, int *, void (*Loglike)(double *, int *, int *, double *), void (*dumper)(int *, int *, int *, double **, double **, double *, double *, double *), int *context);
}
and I call it like
__nested_MOD_nestrun(&_mmodal, &_ceff, &_nlive, &_tol, &_efr, &_ndims, &_nPar, &_nClsPar, &_maxModes, &_updInt, &_Ztol, _root, &_seed, _pWrap, &_fb, &_resume, internalLogLike, internalDumper, &_context);
And the types for arguments match.
When I try to compile it, I get the following error:
[dare2be#schroedinger multinest-interfejs]$ make all
g++ -c ExampleLibMnCpp.cpp -o ExampleLibMnCpp.o
gfortran -lstdc++ -llapack -lblas -lnest3 -L/usr/local/lib ExampleLibMnCpp.o -o ExampleLibMnCpp
ExampleLibMnCpp.o: In function `MultiNestWrapper::Wrapper<double>::run(MultiNestWrapper::MNParams<double>*, double (*)(double const*, int), bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, double, int, double, void (*)(int*, int*, int*, double**, double**, double*, double*, double*), int, double, bool)':
ExampleLibMnCpp.cpp:(.text._ZN16MultiNestWrapper7WrapperIdE3runEPNS_8MNParamsIdEEPFdPKdiEbSsididPFvPiS9_S9_PPdSB_SA_SA_SA_Eidb[MultiNestWrapper::Wrapper<double>::run(MultiNestWrapper::MNParams<double>*, double (*)(double const*, int), bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, double, int, double, void (*)(int*, int*, int*, double**, double**, double*, double*, double*), int, double, bool)]+0x585): undefined reference to `__nested_MOD_nestrun'
collect2: ld returned 1 exit status
make: *** [ExampleLibMnCpp] Error 1
But, note that
[dare2be#schroedinger multinest-interfejs]$ nm /usr/local/lib/libnest3.a | grep __nested_MOD_nestrun
000000000001e0f0 T __nested_MOD_nestrun
I've always dealt with those undefined references myself. But now I can't wrap my head around this. I specify -lnest3 -L/usr/local/lib explicite and /usr/local/lib/libnest3.a contains the routine the linker whines about... Please, help a brother out! :)
EDIT: fixed typos
The order in which you specify libraries in GCC's command-line matters. Read GCC man pages for details - in short you have to specify libraries (-lnest3 etc) after modules that use them. (I always specify libraries in the end of the command-line.)
In your case you have to write
gfortran ExampleLibMnCpp.o -o ExampleLibMnCpp -L/usr/local/lib -lstdc++ -llapack -lblas -lnest3
Maybe you need to specify the source files before the libraries when linking everything together. Like this:
gfortran *.o -lblas -l... ...
Linkers are sometimes picky about the order of their arguments.

retrieving values from array of future objects, std::vector

I'm receiving an error message I have no idea how to respond to. I'm trying to retrieve the values from a vector of future objects and then output them, but I'm having trouble confirming if I'm retrieving the values.
Code:
std::vector<std::future<double>> threadResults;
int numThreads = 4;
double output;
for (int j=0; j<numThreads; j++) {
threadResults.push_back(std::async(launch::async, someCalculation, array1, array2, dimension));
}
for (auto& fut : threadResults) {
auto output = fut.get();
}
I'm new to using std::vector, so I'm unsure of how to use get() with it. Some researching brought me to the bottom for-loop, which I'm unsure if it's working. If anyone sees any obvious mistakes, please let me know, but my main concern is how to correctly use std::vector with the future class.
Here is my error message:
/tmp/ccQ19btT.o: In function `std::thread::thread<std::__future_base::_Async_state_impl<std::_Bind_simple<double (*(double*, double*, double*, int))(double*, double*, double*, int)>, double>::_Async_state_impl(std::_Bind_simple<double (*(double*, double*, double*, int))(double*, double*, double*, int)>&&)::{lambda()#1}>(std::__future_base::_Async_state_impl<std::_Bind_simple<double (*(double*, double*, double*, int))(double*, double*, double*, int)>, double>::_Async_state_impl(std::_Bind_simple<double (*(double*, double*, double*, int))(double*, double*, double*, int)>&&)::{lambda()#1}&&)':
nonOptimizedNonThreaded.cpp:(.text._ZNSt6threadC2IZNSt13__future_base17_Async_state_implISt12_Bind_simpleIFPFdPdS4_S4_iES4_S4_S4_iEEdEC4EOS8_EUlvE_IEEEOT_DpOT0_[_ZNSt6threadC5IZNSt13__future_base17_Async_state_implISt12_Bind_simpleIFPFdPdS4_S4_iES4_S4_S4_iEEdEC4EOS8_EUlvE_IEEEOT_DpOT0_]+0x2d): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
Sorry for the long horizontal scroll, let me know if there's a better to format it.
Here is how I'm compiling:
g++ threadingVector.cpp -o threadingVector -std=c++0x
Let me know if this isn't the right answer, and I shall delete it to avoid confusing other people, but I had the exact same issue yesterday and adding -pthread to the compiler args worked. Try:
g++ -pthread threadingVector.cpp -o threadingVector -std=c++0x
On different architectures the std::thread & company leave some of the low-level implementation of multi-threading down to the environment, and one popular library that would complete the threading implementation on linux would be pthread.

link error when accessing std::string members on Mac Yosemite with libc++

I'm trying to compile this kind of code and I get link errors when trying to build using latest Xcode (6.0) on MacOSX Yosemite:
#include <iostream>
#include <string>
int main()
{
auto x = &std::string::size;
std::string hello("hello");
std::cout << (hello.*x)() << std::endl;
return 0;
}
$ g++ --std=c++11 -stdlib=libc++ hello.cpp -o hello
KO:
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::size() const", referenced from:
_main in hello-a9a7cd.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Note that the code compiles file using libstdc++:
$ g++ --std=c++11 -stdlib=libstdc++ hello.cpp -o hello
OK
I was having the same problem. See Taking pointer to member std::string::size fails to link with libc++ but works with libstdc++
Basically the solution I came up with is to force the instantiation of the std::string template class.
Here is the proposed solution:
#include <iostream>
#include <string>
template class std::basic_string<char>;
int main()
{
auto x = &std::string::size;
std::string hello("hello");
std::cout << (hello.*x)() << std::endl;
return 0;
}

Having trouble linking C++ to Fortran using ICL/IFORT

So I'm following the example from
http://difdop.polytechnique.fr/wiki/index.php/How_to_Bessel_Functions_in_C
Except I'm trying to use the intel compilers ICL and IFORT instead of gcc and g77.
The code I have in C++ is:
extern "C" void zbesj_(double*, double*, double*, int*, int*, double*, double*, int*, int*);
typedef std::complex<double> CplxDbl;
CplxDbl besselj(double nu, CplxDbl z)
{
int kode=1;
int n=1;
double zr=z.real();
double zi=z.imag();
int nz,ierr;
double cyr[1],cyi[1];
CplxDbl res;
zbesj_(&zr,&zi,&nu,&kode,&n,cyr,cyi,&nz,&ierr);
if(ierr!=0){
printf("error!\n");
}
return CplxDbl(cyr[0],cyi[0]);
}
int _tmain(int argc, _TCHAR* argv[])
{
CplxDbl J0=besselj(0.0,CplxDbl(0.1,0.2));
printf("\nJ0(0.1+0.2i)= %.17f %+.17f I\n",J0.real(),J0.imag());
return 0;
}
Additionally, I have zbesj.f and all its dependencies. I've tried calling ICL first, then IFORT and vice versa. Doesn't compile :(
icl -c CallFortranFromC.cpp
ifort -o test CallFortranFromC.obj *.f
Always end up with the same linker error:
CallFortranFromC.obj : error LNK2019: unresolved external symbol zbesj_ referenced in function main
test.exe : fatal error LNK1120: 1 unresolved externals
Any help is appreciated!
You have a mismatch on symbol names in the link stage. If you do:
dumpbin /SYMBOLS zbesj.obj
you'll see symbol name in object file is UPPER CASE and has no trailing UNDERSCORE.
Easiest fix is this (assuming you don't want to change your C code):
icl -c CallFortranFromC.cpp
ifort /names:lowercase /assume:underscore -o test CallFortranFromC.obj *.f

Can't get past "undefined reference to `XXXX'"

I'm currently writing a header-only wrapper library which is supposed to provide C++ access to some FORTRAN code. But I'm stuck at the 'undefined reference (...)'
I must say I'm a little bit surprised because I compiled my own functions in C++ using this FORTRAN routine, with no problems at all.
Maybe a few words about the structure. The library follows the singleton pattern, but without the possibility of instantiating the Library by the user. So the only entry point for the user is a static method MultiNestWrapper::Wrapper<T>::run(). MultiNestWrapper is a namespace, Wrapper<T> is a templated class (so that in future you can benchmark how choosing on which type to perform calculations affects results and performance). The FORTRAN routine is declared outside of this namespace, as
extern "C" {
extern void __nested_MOD_nestrun(int *, int *, int *, double *, double *, int *, int *, int *, int *, int *, double *, const char *, int *, int *, int *, int *, void (*Loglike)(double *, int *, int *, double *), void (*dumper)(int *, int *, int *, double **, double **, double *, double *, double *), int *context);
}
and I call it like
__nested_MOD_nestrun(&_mmodal, &_ceff, &_nlive, &_tol, &_efr, &_ndims, &_nPar, &_nClsPar, &_maxModes, &_updInt, &_Ztol, _root, &_seed, _pWrap, &_fb, &_resume, internalLogLike, internalDumper, &_context);
And the types for arguments match.
When I try to compile it, I get the following error:
[dare2be#schroedinger multinest-interfejs]$ make all
g++ -c ExampleLibMnCpp.cpp -o ExampleLibMnCpp.o
gfortran -lstdc++ -llapack -lblas -lnest3 -L/usr/local/lib ExampleLibMnCpp.o -o ExampleLibMnCpp
ExampleLibMnCpp.o: In function `MultiNestWrapper::Wrapper<double>::run(MultiNestWrapper::MNParams<double>*, double (*)(double const*, int), bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, double, int, double, void (*)(int*, int*, int*, double**, double**, double*, double*, double*), int, double, bool)':
ExampleLibMnCpp.cpp:(.text._ZN16MultiNestWrapper7WrapperIdE3runEPNS_8MNParamsIdEEPFdPKdiEbSsididPFvPiS9_S9_PPdSB_SA_SA_SA_Eidb[MultiNestWrapper::Wrapper<double>::run(MultiNestWrapper::MNParams<double>*, double (*)(double const*, int), bool, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, double, int, double, void (*)(int*, int*, int*, double**, double**, double*, double*, double*), int, double, bool)]+0x585): undefined reference to `__nested_MOD_nestrun'
collect2: ld returned 1 exit status
make: *** [ExampleLibMnCpp] Error 1
But, note that
[dare2be#schroedinger multinest-interfejs]$ nm /usr/local/lib/libnest3.a | grep __nested_MOD_nestrun
000000000001e0f0 T __nested_MOD_nestrun
I've always dealt with those undefined references myself. But now I can't wrap my head around this. I specify -lnest3 -L/usr/local/lib explicite and /usr/local/lib/libnest3.a contains the routine the linker whines about... Please, help a brother out! :)
EDIT: fixed typos
The order in which you specify libraries in GCC's command-line matters. Read GCC man pages for details - in short you have to specify libraries (-lnest3 etc) after modules that use them. (I always specify libraries in the end of the command-line.)
In your case you have to write
gfortran ExampleLibMnCpp.o -o ExampleLibMnCpp -L/usr/local/lib -lstdc++ -llapack -lblas -lnest3
Maybe you need to specify the source files before the libraries when linking everything together. Like this:
gfortran *.o -lblas -l... ...
Linkers are sometimes picky about the order of their arguments.