I am currently trying to develop a C++ application which will envolve solving some algebraic tasks (such as differentiation or integration) using GiNaC; I've installed it first from the Ubuntu Software Center (Ubuntu 13.04) and afterwards directly from the ftp ftp://ftpthep.physik.uni-mainz.de/pub/GiNaC/ ; however, everytime i try to compile the following example program:
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
int main()
{
symbol x("x"), y("y");
ex poly;
for (int i=0; i<3; ++i)
poly += factorial(i+16)*pow(x,i)*pow(y,2-i);
cout << poly << endl;
return 0;
}
i get a list of errors, all starting with "undefined reference to GiNaC::". I have verified that cln is also installed and the header files are on the default locations. Also, when compiling I've used the command g++ -o simple pkg-config --cflags --libs ginac simple.cpp
and g++ -o simple -lginac -lcln simple.cpp, both have failed to compile.
The problem is the order of the parameters on the compile line. Try one of the following two variants:
g++ -o simple simple.cpp `pkg-config --cflags --libs ginac`
g++ -o simple -Wl,--no-as-needed `pkg-config --cflags --libs ginac` simple.cpp
The idea is that the order of the object files and libraries is important to the linker. Very simply put, by default it only links a library if it needs it to resolve some previously unresolved symbols.
The first variant above moves the libraries at the end of the build parameters (so after the object file for your code), while the second variant disables this behavior in the linker.
I ran into the same exact issue, and I found 2 things that does bring you to where you want to be:
I placed -lcln after -lginac on the command line
This enabled me to compile it, but the program would not run. I found the solution to this. The error was "GLIB_CXX_3.4.21 not defined in libstdc++.so.6 with link time reference"
Link statically to libstdc++ with -static-libstdc++
As in:
g++ -g testgin.cpp -o simple -lcln -lginac -static-libstdc++
Peace
Related
(Note: This question had been closed, citing that this had an answer. However, my question is not generic, I am asking why this works in ubuntu/redhat, but not in macos/cygwin. So I have edited this question, by modifying the title, mentioning the words macos and ubuntu.)
I have the following c++ code:
// main.cpp
#include<iostream>
#include<cstdio>
#include "defs.h" // has the function headers only
int func0(int a0) {
printf("func0-%d\n", a0);
return a0+1;
}
int func1(int a1) {
int x;
x=func0(a1);
printf("func1-%d\n", x);
return a1+1;
}
int func2(int a2) {
int x;
x=func1(a2);
printf("func2-%d\n", x);
return x+5;
}
int main() {
func1(5);
func2(8);
}
I can compile and run this code as:
g++ main.cpp; ./a.out
Now I would like to move the functions to different files (func1 to f1.cpp,
fun0 and func2 to f2.cpp, and main to main.cpp), and create shared libraries
like this:
g++ -c -pipe -std=c++11 -fPIC main.cpp
g++ -c -pipe -std=c++11 -fPIC f1.cpp
g++ -c -pipe -std=c++11 -fPIC f2.cpp
g++ -shared -o libx1.so f1.o
g++ -shared -o libx2.so f2.o
g++ main.o -L. -lx1 -lx2 -o exe
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./exe
The above instructions work in redhat linux and ubuntu. But when I run the same commands in other variants of linux (eg macos or cygwin) I get errors during creation of the shared library like this:
g++ -shared -o libx1.so f1.o
undefined reference to func0(int)
g++ -shared -o libx2.so f2.o
undefined reference to func1(int)
Why is this error happening only in some OS versions, and not happening in redhat/ubuntu? Is it due to the gcc versions, or something to do with the OS?
(The above instructions work with g++ in redhat(gcc version 8.3.1) and ubuntu (9.4.0). It does not work with g++ in cygwin(11.3.0) and in macos(11.2.0).)
The problem is caused by cyclic dependencies between the two libraries. Before doing anything else, you should ask yourself whether it is acceptable to have cyclic dependencies for your project. It is never a good idea, but if the alternative involves massive refactoring, it could be the lesser of two evils. Still, refactoring should probably be the default answer in most cases. If you cannot refactor, the rest of this answer is for you.
How are cyclic dependencies handled on different OSes?
On both Linux and Mac OS X (and on FreeBSD and on most commercial Unixes of old), references are resolved at load time. The loader uses the first suitable symbol definition it encounters, be it it in the main executable, in the shared object itself, or in a different shared object. It is not known until load time where that definition will be found.
So when the executable from the question is loaded, the dynamic loader finds the definition of func1 in libx1 and the definitions of func0 and func2 in libx2, and all is well.
The difference between Linux and Mac OS X lies in the linker (ld) behaviour. Both GNU ld and LLVM ld by default allow unresolved references when building a shared library. Mac OS X ld appears to be of a different breed and unresolved references are not allowed by default. One can either list the dependencies on the link line, or explicitly allow unresolved references using the Mac-specific ld option -undefined dynamic_lookup. But of course when the dependencies are cyclic, the first option is problematic. For code in question:
g++ -shared -o libx1.so f1.o -Wl,-undefined,dynamic_lookup
g++ -shared -o libx2.so f2.o -Wl,-undefined,dynamic_lookup
Windows DLLs work very differently. Each symbol must be resolved at link time. Unlike the Unix-y loaders, the loader must know exactly which DLL to search for each imported symbol. There is no option to allow unresolved references in DLLs because there is no mechanism to resolve them at load time from an unknown source.
Windows still allows cyclic dependencies between DLLs, but the mechanism is a bit different. The linker must use separate import libraries in this case (they are usually optional when using GNU or LLVM toolchains). The linking is done in two phases. First, the .lib files are generated for each future .dll, and then .dll themselves are produced using the .lib files from the first stage. For code in question:
# first stage
g++ -shared -Wl,--out-implib=x1.lib -o x1.dll f1.o
g++ -shared -Wl,--out-implib=x2.lib -o x2.dll f2.o
# second stage
g++ -shared -o x1.dll f1.o x2.lib
g++ -shared -o x2.dll f2.o x1.lib
The first stage will report undefined symbols but will still produce the .lib file needed for the second stage.
I want to run sample code from PCL site to simple read cloud from file.
I installed libraries, and prepared build script:
g++ -std=c++11 main.cpp -lboost_system `pkg-config --libs --cflags opencv4` -g -o main
but compiller throws many errors like:
/usr/include/pcl/io/pcd_io.h:56: undefined reference to `vtable for pcl::PCDReader'
I know that I need to linking libpcl_io.so like I linked boost library by adding -lboost_system , but my question is - how?
I tried add to script something like -lpcl, -libpcl, -lpcl_io, but it doesn't works
So, what is keyword to linking PCL Libraries?
I've installed the libglfw3-dev:amd64 package on Ubuntu using the standard sudo apt get etc. My following compiling line is:
g++ -o output -IL/usr/lib/x86_64-linux-gnu -lglfw driver.o
My current c++ file is:
#include <GLFW/glfw3.h>
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
return -1;
}
I've tried using local libraries of glfw and setting the -I and -L locations but nothing has seemed to work. I've made sure the .so and .h files are in their respective locations but I always get this error while running make:
g++ -o output -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu -lglfw
driver.o
driver.o: In function `main':
driver.cpp:(.text+0x5): undefined reference to `glfwInit'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'output' failed
make: *** [output] Error 1
I've tried looking at all the other SO posts and they recommend compiling with tons of extra flags, but the only thing I've been able to draw from them is that something is wrong with my library since VScode detects the .h files. How can I compile this without any errors?
Have you tried swapping the linker arguments around? That is, compile with
g++ -o output driver.o -lglfw
The linker goes through the files from left to right, and it has to know which symbols from libraries you need, before the libraries are processed.
All is perfectly explained in the manual https://www.glfw.org/docs/latest/build_guide.html#build_link_pkgconfig
The key problem is in your -I/usr/include/GLFW and #include <GLFW/glfw3.h> that gives in sum the path /usr/include/GLFW/GLFW/glfw3.h. I suppose this is a wrong path to glfw3.h. compilation was successful because of the system default include path -I/usr/include.
Do not tune compiler flags manually, let pkg-config do
it for you.
A typical compile and link command-line when using the static version of the GLFW library may look like this:
g++ -o output `pkg-config --cflags glfw3` yourprog.c `pkg-config --static --libs glfw3`
If you are using the shared version of the GLFW library, simply omit the --static flag.
g++ -o output `pkg-config --cflags glfw3` yourprog.c `pkg-config --libs glfw3`
For reference: i am currently on Manjaro (Arch Linux) and am using the GNU g++ compiler. I want to create a program for JACK (Jack Audio Connection Kit) and am now trying to use their API provided here. I have Jack2 installed, but also tried it with Jack2-dbus. I found something in the AUR called jackcpp, but that didn't help neither.
To get to my problem: I fail to compile their example clients listed, and obviously I fail to build my own using that API. I suspect it is broken, but I can't imagine noone reporting it so I don't really know what to do now.
In my jacktest.cpp the following is written:
#include <iostream>
#include "jack/control.h"
int main(){
jackctl_server_t *server;
jackctl_driver_t *driver;
if (jackctl_server_start(server, driver)) {
std::cout << "Started!";
return 0;
}else{
std::cout <<"Failed!";
return 1;
};
}
based on the function documented here. Try to start a jack server and return a bool if operation successful or not.
If I try to compile this (with 'pkg-config' as I am supposed to):
$ g++ -o jacktest `pkg-config --cflags --libs jack` jacktest.cpp
it throws:
jacktest.cpp:8:44: error: too many arguments to function 'bool jackctl_server_start(jackctl_server_t*)'
if (jackctl_server_start(server, driver))
So I checked and indeed, in my /usr/include/jack/control.h, it defines jackctl_server_start with only one argument. I don't know if their documentation is outdated or if I am missing files/have the wrong ones...
Then I tried to do it with only one argument
...
if (jackctl_server_start(server)) {
...
which then throws:
/usr/bin/ld: /tmp/ccxm3fWC.o: undefined reference to symbol '_ZNSt8ios_base4InitD1Ev##GLIBCXX_3.4'
/usr/lib/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
I tried to rearrange the arguments:
$ g++ -o jacktest `pkg-config --cflags --libs jack` jacktest.cpp
$ g++ -o jacktest jacktest.cpp `pkg-config --cflags --libs jack`
$ g++ jacktest.cpp `pkg-config --cflags --libs jack` -o jacktest
$ g++ jacktest.cpp -o jacktest `pkg-config --cflags --libs jack`
which always throws the same error...
now the thing that really makes me think something is broken: another jacktest_2.cpp now including jack.h and excluding control.h
#include <iostream>
#include "jack/jack.h"
int main(){
jack_client_t *client;
if (client = jack_client_new("test_client")) {
std::cout << "Running!";
return 0;
}else{
std::cout <<"Not Running!";
return 1;
};
}
which I CAN compile:
$ g++ -o jacktest_2 jacktest_2.cpp `pkg-config --cflags --libs jack`
altough it gives me complains that this function is depricated, the program does what it should too! So at least some of it is working?!
Also:
$ g++ -print-file-name=jack
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib/jack
is that normal? There is no lib/jack in usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1
To conclude: I really NEED control.h, I even went as far as changing control.h and include their 'driver' part from the API Docs back into the function, but that didn't get me anywhere neither... (undefined reference...) I feel like I am missing something really simple, or something really is broken with that API. I have been on this for almost a week, and I just can't figure it out.
If anyone stumbles upon this and wondered what happend: I posted this in the JackAudio forum here. Anyone can read it if he/she wants to, but I will mark this question as answered now, since it really is not a C++ or compiling problem but rather a Jack problem. Thank you!
I recently compiled Allegro-5.0 from source (following the instructions from the wiki). I didn't get any errors during the process, so I assume it went well. However, I am getting linker errors with even the most minimal test programs:
//test.cpp
#include <allegro5/allegro.h>
int main()
{
al_init();
return 0;
}
I am compiling with
g++ `pkg-config --libs allegro-5.0` test.cpp -o test
But I always get
/tmp/ccVmmERa.o: In function `main':
test.cpp:(.text+0xf): undefined reference to `al_install_system'
collect2: error: ld returned 1 exit status
(pkg-config returns -L/usr/local/lib -lallegro, there doesn't seem to be anything wrong with that)
Also, I can compile the examples with the the given makefile just fine, so there doesn't seem to be anything wrong with the library. I would just try to do the same thing the makefile does to make it work, but I don't understand it at all (I can barely write my own simple ones).
Oh, and I'm using Ubuntu 11.10 and gcc 4.7, though I don't think that has anything to do with it.
So - why does this happen, and how can I fix it?
Put the libs last on the command line:
g++ test.cpp -o test `pkg-config --libs allegro-5.0`
When linking, the order of the files and libraries matter.