I am trying to get a very simple program to compile while using functions from libpano13, but I am running into linking errors. I am on Ubuntu 10.04, and have done the following:
sudo apt-get install libpano13-dev
My sample program is as follows:
#include <cstring>
#include <pano13/PTcommon.h>
int main(int argc, char **argv) {
fullPath *outFile = new fullPath();
StringtoFullPath(outFile, (char *)"/tmp/randomImage.jpg");
return 0;
}
I am attempting to compile this with the following command (the above code is located in a file called panoTest.cpp):
$ g++ panoTest.cpp -o testApp -L/usr/lib -lpano13
When I run this command I get the following error:
$ g++ panoTest.cpp -o testApp -L/usr/lib -lpano13
/tmp/ccyIioEi.o: In function `main':
panoTest.cpp:(.text+0x87): undefined reference to `StringtoFullPath(fullPath*, char*)'
collect2: ld returned 1 exit status
make: *** [all] Error 1
Now, I've checked /usr/lib for libpano* and found the following files:
$ ls /usr/lib/libpano*
/usr/lib/libpano13.a /usr/lib/libpano13.so /usr/lib/libpano13.so.1
/usr/lib/libpano13.so.1.0.0
I've checked libpano13.so using nm and got the following output:
$ nm --demangle /usr/lib/libpano13.a | grep StringtoFullPath
U StringtoFullPath
U StringtoFullPath
00000000 T StringtoFullPath
$ nm --demangle /usr/lib/libpano13.so | grep StringtoFullPath
nm: /usr/lib/libpano13.so: no symbols
I also checked it using objdump:
$ objdump -T /usr/lib/libpano13.so | grep StringtoFullPath
00057fd0 g DF .text 0000004c Base StringtoFullPath
So, the following seems to be true:
libpano13 exists in /usr/lib,
libpano13 contains the symbols for StringtoFullPath,
I am using the correct library directory of /usr/lib,
I am using the correct library name of pano13, and
g++ is able to locate the library
But, for some reason, g++ is unable to find the symbol for StringtoFullPath.
Does anyone have any suggestions/ideas about why this is happening?
Any help would be greatly appreciated!
The
undefined reference to `StringtoFullPath(fullPath*, char*)'
worries me a bit: it contains the types of the parameters. Most Linux libraries are not C++, so there should be no types...
Try surrounding the #include for the header with an extern "C" { ... } block.
Related
I am trying to compile a program so that it starts on a different entry point. I am running WSL1 with Ubuntu 20.04.5, and GCC and G++ 9.4.0
I found that adding the flag -Wl,--entry=foo to the compiler will link foo() as the entry function. Testing, this has worked with gcc, but not with g++.
Using the example file src/main.c:
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
return 0;
}
int not_main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
exit(0); // Necessary, otherwise it throws a segfault
}
When compiled with gcc -Wl,--entry=not_main -o entry.o src/main.c the output is what I want: Entering src/main.c:not_main.
However, when compiled with g++ -Wl,--entry=not_main -o entry.o src/main.c, the following warning appears: /usr/bin/ld: warning: cannot find entry symbol not_main; defaulting to 0000000000001080.
This defaults to the main() function, outputting Entering src/main.c:main. The function not_main() is not found by the linker, but it is present in the source code.
The documentation for g++ says:
g++ is a program that calls GCC and automatically specifies linking against the C++ library.
I don't see how g++ can differ from gcc, if internally one calls the other. I understand that it is not the compiler but the linker which changes the entry point, and that g++ (unlike gcc) is linking against the C++ library, but I fail to understand how that is problematic.
What am I missing?
Because of name mangling, the function is not not_main but _Z8not_mainv.
how g++ can differ from gcc,
What is the difference between g++ and gcc? why use g++ instead of gcc to compile *.cc files?
C++, unlike C, uses name mangling to distinguish different overloads of the same function name.
When compiled with gcc:
$ objdump -t entry.o | grep not_main
000000000000117c g F .text 0000000000000036 not_main
When compiled with g++:
$ objdump -t entry.o | grep not_main
0000000000000000 *UND* 0000000000000000 not_main
000000000000117c g F .text 0000000000000036 _Z8not_mainv
The *UND*efined reference to not_main was probably placed there by the linker since you requested this as the entry point. The actual not_main function has its name mangled to _Z8not_mainv.
To export not_main under its original name, use extern "C":
extern "C" int not_main()
{
printf("Entering %s:%s\n", __FILE__, __func__);
exit(0); // Necessary, otherwise it throws a segfault
}
I'd like to build a dynamic library from a Rust program and link it to an existing C++ project.
For the C++ project, we are stuck on using gcc for compilation (a relatively old gcc 4.8.2, but I'm also trying with gcc 7.3.0 with the same issue).
This is a minimal example of the issue:
src/lib.rs
#[no_mangle]
pub unsafe extern "C" fn hello() {
println!("Hello World, Rust here!");
}
Cargo.toml
[package]
name = "gcc-linking"
version = "0.1.0"
authors = ..
edition = "2018"
[lib]
crate-type = ["dylib"]
[dependencies]
hello.cpp:
extern "C" void hello();
int main() {
hello();
return 0;
}
Now, when I link with clang, everything is fine:
cargo build --lib
clang -L target/debug -l gcc_linking hello.cpp -o hello
LD_LIBRARY_PATH=target/debug:$LD_LIBRARY_PATH ./hello
As expected, this results in:
Hello World, Rust here!
But if I try to link this with gcc, I get the following linking error:
gcc -L target/debug -l gcc_linking hello.cpp -o hello
Output:
/tmp/ccRdGJOK.o: In function `main':
hello.cpp:(.text+0x5): undefined reference to `hello'
collect2: error: ld returned 1 exit status
Looking at the dynamical library:
# objdump -T output
0000000000043f60 g DF .text 0000000000000043 Base hello
# nm -gC output
0000000000043f60 T hello
I suspect the problem has something to do with mangling of function names, but I cannot figure out how to solve it.
Any ideas?
As #Jmb suggested, the solution was to change the order of arguments to gcc and list the shared library after the C++ file:
gcc -L target/debug hello.cpp -l gcc_linking -o hello
I found a number of similar questions (e.g. this, that or this), but none of them helped me solve my problem. I have a *.so file (from the core of gnss-sdr) that, as indicated by:
$nm libgnss_system_parameters_dyn.so | c++filt |grep Gps_Eph
contains the symbol Gps_Ephemeris::Gps_Ephemeris(), which is supposed to be a constructor.
I've written some minimal code:
#include <iostream>
#include <core/system_parameters/gps_ephemeris.h>
int main(int argc,const char* argv[])
{
Gps_Ephemeris ge;
return 0;
}
which I compile with:
g++ main.cpp -std=c++0x -I some_include_path -L some_lib_path -l gnss_system_parameters_dyn`
The linker then complains:
/tmp/ccHCvldG.o: In function `main':
main.cpp:(.text+0x33): undefined reference to `Gps_Ephemeris::Gps_Ephemeris()'
collect2: error: ld returned 1 exit status
I also tried cmake, but the line it generated was similar to that (it just added -rdynamic before linking), and it still generated the exact same linker error.
Note that both the library and my minimal code are being compiled with the same compiler (g++-5), with the exact same flags and the same c++0x standard.
Addressing the answer by Maxim Egorushkin, the line:
nm --demangle --defined-only --extern-only libgnss_system_parameters.so |grep Gps_Eph
doesn't output anything. However, the symbol is defined in the static library (i.e. the *.a library):
00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()
00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()
Knowing that both are generated by cmake, in the following way:
add_library(lib_name SHARED ${sources_etc}) #for the *.so
add_library(lib_name_2 ${sources_etc}) #for the *.a
there should be no difference in symbols contained/defined in those libraries, right? I didn't notice anything in cmake's documentation on add_library. Am I missing something obvious?
The pedantically correct way to check that a .so exports a symbol is nm --demangle --dynamic --defined-only --extern-only <lib.so> | grep <symbol>.
Without --defined-only your command also shows undefined symbols.
Without --extern-only it also shows symbols with internal linkage which are unavailable for linking.
It looks like you need to link another library because Gps_Ephemeris::Gps_Ephermeris() is not resolved by linking libgnss_system_parameters_dyn.so. A good way to start is that library's documentation and examples.
I have found in the past that this type of error is caused by the lack of proper extern "C" { ... } bracketing in an include file.
I am trying to call cplus_demangle() function from libiberty.a, but I am getting "undefined reference to 'cplus_demangle' error.
This is my simple main:
extern "C" char *cplus_demangle(const char *, int);
int main() {
cplus_demangle("a", 0);
}
and my build command (libiberty is in ../../install/lib64):
g++ -L../../install/lib64 -liberty main.cpp -o main
If I rename libiberty.a to something else I'd get "cannot find -liberty" error. So, I assume the linker sees the library. And I can see cplus_demangle in libiberty.a:
$> nm -C --defined-only libiberty.a | grep "cplus_demangle"
0000000000002230 T cplus_demangle
...
But I am getting this error when I compile:
main.cpp:(.text+0xf): undefined reference to `cplus_demangle'
collect2: ld returned 1 exit status
make: *** [main] Error 1
I'd appreciate your help. Thanks!
Move the -liberty to the end of the command line. The library should be searched after main.o is created. Order matters.
I'm trying to write an application using the UDP module included
in the inetmanet framework in omnetpp. The problem is that the files that I have to include don't get included in the linking phase.
The errors are:
opp_makemake
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$ opp_makemake --deep -f -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base
Creating Makefile in /home/bedo/omnetpp/samples/Basic-Broadcast-Simulation...
Makefile created, running "make depend" to add dependencies...
opp_makedep -Y --objdirtree -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base -I. -Igcc-debug -Igcc-debug/src -Igcc-debug/src/flooding -Isimulations -Isimulations/bitmaps -Isimulations/results -Isrc -Isrc/flooding -f Makefile -P\$O/ -- ./*.cc gcc-debug/*.cc gcc-debug/src/*.cc gcc-debug/src/flooding/*.cc simulations/*.cc simulations/bitmaps/*.cc simulations/results/*.cc src/*.cc src/flooding/*.cc
make
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$ make
g++ -c -g -Wall -fno-stack-protector -DHAVE_PCAP -DXMLPARSER=libxml -DWITH_PARSIM -DWITH_NETBUILDER -I../inet-sommer/src/transport/contract -I../inet-sommer/src/networklayer/contract -I../inet-sommer/src/base -I. -Igcc-debug -Igcc-debug/src -Igcc-debug/src/flooding -Isimulations -Isimulations/bitmaps -Isimulations/results -Isrc -Isrc/flooding -I/home/bedo/omnetpp/include -o out/gcc-debug//src/flooding/Flooding.o src/flooding/Flooding.cc
src/flooding/Flooding.cc: In member function ‘virtual void Flooding::handleLowerMsg(cMessage*)’:
src/flooding/Flooding.cc:82: warning: unused variable ‘m’
g++ -Wl,--export-dynamic -Wl,-rpath,/home/bedo/omnetpp/lib -Wl,-rpath,. -o out/gcc-debug//Basic-Broadcast-Simulation out/gcc-debug//src/flooding/Flooding.o -Wl,--whole-archive -Wl,--no-whole-archive -L"/home/bedo/omnetpp/lib/gcc" -L"/home/bedo/omnetpp/lib" -u _tkenv_lib -lopptkenvd -loppenvird -lopplayoutd -u _cmdenv_lib -loppcmdenvd -loppenvird -loppsimd -ldl -lstdc++
out/gcc-debug//src/flooding/Flooding.o: In function `Flooding::setupLowerLayer()':
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:50: undefined reference to `UDPControlInfo::UDPControlInfo()'
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:52: undefined reference to `UDPSocket::generateSocketId()'
out/gcc-debug//src/flooding/Flooding.o: In function `Flooding::sendMessage()':
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:101: undefined reference to `UDPControlInfo::UDPControlInfo()'
/home/bedo/omnetpp/samples/Basic-Broadcast-Simulation/src/flooding/Flooding.cc:103: undefined reference to `IPAddress::ALL_HOSTS_MCAST'
collect2: ld returned 1 exit status
make: *** [out/gcc-debug//Basic-Broadcast-Simulation] Error 1
bedo#ethereal:~/omnetpp/samples/Basic-Broadcast-Simulation$
I really don't know why they get included, and my module compile fine, but in the linking phase I get "undefined reference".
Any idea?
You can run nm on on all libraries you link with to see which library undefined symbols like this:
nm liboppcmdenvd.(so/a) | c++filt | grep UDPControlInfo
(c++filt demangles C++ symbols).
Library that requires the symbol will get output something like (U for Undefined):
00000000007f90a0 U UDPControlInfo
Library that defines/has the symbol will get output something like:
00000000007f90a0 T UDPControlInfo
This can be T or t
Of course, libraries you link with are indicated by arguments with starting by -l:
-lopptkenvd -loppenvird -lopplayoutd -u _cmdenv_lib -loppcmdenvd -loppenvird
liboppcmdenvd liboppenvird liboppsimd libUDPControlInfo
Solved. I modified the makefile in the root directory to a simpler one, leaving all the compile and linking duties to the src's makefile.
Thanks everyone