g++ failing when trying to use GDAL library [duplicate] - c++

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 3 months ago.
I just want to compile this easy example of the GDAL library in my Ubuntu 22.04 system using the system-packed g++, version 11.3.0:
#include <iostream>
#include "gdal_priv.h"
#include "cpl_conv.h"
#include "gdal.h"
using namespace std;
int main(int argc, char* argv[])
{
GDALDataset *poDataset;
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen(argv[1], GA_ReadOnly);
if (poDataset == NULL)
{
cout << "No dataset loaded for file " << argv[1] << ". Exiting." << endl;
return 1;
}
cout << "Driver: "
<< poDataset->GetDriver()->GetDescription()
<< "/"
<< poDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME)
<< endl;
cout << "Size: "
<< poDataset->GetRasterXSize() << "x"
<< poDataset->GetRasterYSize() << "x"
<< poDataset->GetRasterCount()
<< endl;
if (poDataset->GetProjectionRef() != NULL)
{
cout << "Projection: " << poDataset->GetProjectionRef() << endl;
}
}
Of course I installed the GDAL libraries, as it can be seen here:
~$ dpkg -l | grep gdal
ii gdal-bin 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library - Utility programs
ii gdal-data 3.4.1+dfsg-1build4 all Geospatial Data Abstraction Library - Data files
ii libgdal-dev 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library - Development files
ii libgdal30 3.4.1+dfsg-1build4 amd64 Geospatial Data Abstraction Library
ii python3-gdal 3.4.1+dfsg-1build4 amd64 Python 3 bindings to the Geospatial Data Abstraction Library
Everything seems to be settled and ready to go, but then, when I trigger this g++ command to compile my little program
g++ -I/usr/include/gdal -L/usr/lib -lgdal open_file.cpp -o open_file -g
it fails with this output:
/usr/bin/ld: /tmp/ccU6PwuP.o: in function `main':
/home/jose/Code/concepts/gdal/open_file.cpp:13: undefined reference to `GDALAllRegister'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:14: undefined reference to `GDALOpen'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:29: undefined reference to `GDALDataset::GetRasterXSize()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:30: undefined reference to `GDALDataset::GetRasterYSize()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:31: undefined reference to `GDALDataset::GetRasterCount()'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:34: undefined reference to `GDALDataset::GetProjectionRef() const'
/usr/bin/ld: /home/jose/Code/concepts/gdal/open_file.cpp:36: undefined reference to `GDALDataset::GetProjectionRef() const'
collect2: error: ld returned 1 exit status
Which doesn't make any sense, because I am indeed passing the GDAL libraries in -I/usr/include/gdal and the definition of the "undefined" references do exist in the multiple .h files there.
Moreover, this works using clang++:
clang++ -I/usr/include/gdal -L/usr/lib -lgdal open_file.cpp -o open_file -g
Did anyone have a similar issue, or can give some hint on where the problem might be? Thank you.

Include paths have nothing to do with the symbols.
-I/usr/include/gdal -L/usr/lib both are not necessary as they are set by default. But you should use #include <gdal/gdal.h>, not just <gdal.h> and certainly not "gdal.h".
Move -lgdal after all other cpp/object files.
In general, it should be g++ <OPTIONS> <OBJECTS> <LIBRARIES> where library A which uses symbols from lib B should appear after B i.e. -lB -lA, the order matters for ld. Because it will use the library to resolve just the currently missing symbols and then will promptly forget the library ever existed. So any newly found unresolved symbols will not be resolved, hence shifting the library arguments "right". One can resolve circular dependencies by repeating libraries more than once.

Related

Nm shows symbol in shared library, but undefined symbol when linking

As a mental exercise, I'm trying to write a program that links directly against the GPU driver of my Macbook Pro rather than using Apple's Metal framework. Some exploration led me to this file (presumably specific to my particular hardware):
/System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver
Running file on it confirms this is a Mach-O 64-bit dynamically linked shared library.
Running nm on it tells me it's a superset of AMD's ROCr runtime. One symbol in particular that interests me is this one:
$ nm -gD AMDRadeonX6000MTLDriver | grep "hsa_init"
00000000001cca20 T __ZN3HSA8hsa_initEv
$ nm -gCD AMDRadeonX6000MTLDriver | grep "hsa_init"
00000000001cca20 T HSA::hsa_init()
So I wrote this simple program (rocr_test.cpp):
typedef int hsa_status_t;
namespace HSA {
hsa_status_t hsa_init();
}
int main() {
HSA::hsa_init();
return 0;
}
And compiled it like so:
$ clang++ rocr_test.cpp -c
$ clang++ rocr_test.o /System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver
Undefined symbols for architecture x86_64:
"HSA::hsa_init()", referenced from:
_main in rocr_main-95c854.o
ld: symbol(s) not found for architecture x86_64
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
However, nm on the object file shows the linker should look for a symbol with the same name:
$ nm rocr_test.o
U __ZN3HSA8hsa_initEv
0000000000000000 T _main
Why am I seeing this linker error, when nm shows that a symbol with this exact name clearly exists in the shared library?
Apple's compiler is a bit different, and in order to link with libraries it needs to use a ".tbd" file. This is a textual file containing the symbol list, a UUID and the basic details of a mach-O it is linked against. You can find plenty of examples of those in the SDK (go to the SDK root and find . -type f -name "*.tbd"). The TBD would look something like:
--- !tapi-tbd-v3
archs: [ x86_64 ]
uuids: ['x86_64: 8891E6F5-0B7C-3CC7-88C1-9F5303311EC7' ]
platform: ios
install-name: /System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver
objc-constraint: none
exports:
- archs: [ x86_64 ]
symbols: [ __Z34amdMtl_GFX10_GetFallbackFamilyNameP15GFX10_HwInfoRec, __Z35amdMtl_GFX10_GetFallbackProductNameP15GFX10_HwInfoRec, __Z25amdMtl_GFX10_AllocLsHsMgrP15GFX10_MtlDeviceP14AMDPPMemMgrRec, ...
You'd have to create a TBD for the Bundle, (the above was created using jtool2 --tbd), and direct the compiler to use it (or place it in the SDK directory) and that should (hopefully) work.
If has_init is not part of a class, then you can still call the function by it's mangled name. However, this will only work if it is a free function. If it is part of a class, then you can not really call it without class definition, as you don't know what it does to the class members and you would have to pass the object as the first argument.
#include <iostream>
#include <dlfcn.h>
using namespace std;
typedef int hsa_status_t;
typedef hsa_status_t (*hsa_init_t)();
hsa_init_t hsa_init;
const char *hsa_init_name = "__ZN3HSA8hsa_initEv";
const char *libPath = "/System/Library/Extensions/AMDRadeonX6000MTLDriver.bundle/Contents/MacOS/AMDRadeonX6000MTLDriver";
int main()
{
void *libraryHandle = dlopen(libPath, RTLD_NOW);
if (!libraryHandle)
{
cout << "Error opening library: " << libPath << " Error: " << dlerror() << endl;
return 0;
}
dlerror(); // clear any existing error
hsa_init = (hsa_init_t)dlsym(libraryHandle, hsa_init_name);
if (!hsa_init)
{
cout << "Error importing symbol: " << hsa_init_name << " Error: " << dlerror() << endl;
return 0;
}
hsa_init();
return 0;
}

Compiling boost on Mac OS X Mavericks [duplicate]

This question already has answers here:
C++ Boost: undefined reference to boost::system::generic_category()
(13 answers)
Closed 8 years ago.
There are many threads on this topic, but I've tried some of the solutions and nothing seems to work.
If I install boost with:
brew install booost --c++11
and try to compile the following program tut1.cpp:
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: tut1 path\n";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
return 0;
}
using
clang -I /usr/local/Cellar/boost/1.55.0_1/include/ -L /usr/local/Cellar/boost/1.55.0_1/lib/ tut1.cpp
and it fails horribly:
Undefined symbols for architecture x86_64:
"boost::filesystem::path::codecvt()", referenced from:
boost::filesystem::path::path<char*>(char* const&, boost::enable_if<boost::filesystem::path_traits::is_pathable<boost::decay<char*>::type>, void>::type*) in tut1-6a2087.o
...
...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The linking seems to be the problem because if I invoke the -c option the object file gets created.
Any ideas what the hell is going on?
You want to link against boost filesystem and boost system:
-lboost_filesystem -lboost_system
So the complete compile command would be:
clang++ -I /usr/local/opt/boost/include -L /usr/local/opt/boost/lib tut1.cpp -lboost_filesystem -lboost_system

c++11 threads, SFML and code::blocks

I'm trying to run this code using c++11 std::thread and the SFML library for networking, however I just cant get it to build. I'm pretty sure it has something to do with how I'm setting up the compiler, but I don't know... How can I get this to work? I've been messing about trying to get this to work, going through tutorials and such for hours now, so I have turned to Stack Overflow for answers. I'm using the code::blocks IDE and the x32-4.8.1-posix-dwarf-rev5 compiler on a windows7 64-bit machine.
#include <iostream>
#include <thread>
#include <string>
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
using namespace std;
void doNetwork() {
cout << "Starting..." << endl;
sf::TcpListener listener;
listener.listen(88);
// Wait for a connection
sf::TcpSocket socket;
listener.accept(socket);
cout << "New client connected: " << socket.getRemoteAddress() << endl;
// Receive a message from the client
char buffer[1024];
size_t received = 0;
socket.receive(buffer, sizeof(buffer), received);
cout << "The client said: " << buffer << endl;
// Send an answer
string message = "Welcome, client";
socket.send(message.c_str(), message.size() + 1);
}
int main()
{
thread task(doNetwork);
task.join();
return 0;
}
This is what the build debug log is saying:
-------------- Build: Debug in bang ---------------
Compiling: main.cpp
Linking console executable: bin\Debug\bang.exe
obj\Debug\main.o: In function `Z9doNetworkv':
C:/Users/user/CppProjects/bang/main.cpp:12: undefined reference to `sf::TcpListener::TcpListener()'
C:/Users/user/CppProjects/bang/main.cpp:13: undefined reference to `sf::TcpListener::listen(unsigned short)'
C:/Users/user/CppProjects/bang/main.cpp:16: undefined reference to `sf::TcpSocket::TcpSocket()'
C:/Users/user/CppProjects/bang/main.cpp:17: undefined reference to `sf::TcpListener::accept(sf::TcpSocket&)'
C:/Users/user/CppProjects/bang/main.cpp:18: undefined reference to `sf::TcpSocket::getRemoteAddress() const'
C:/Users/user/CppProjects/bang/main.cpp:18: undefined reference to `sf::operator<<(std::ostream&, sf::IpAddress const&)'
C:/Users/user/CppProjects/bang/main.cpp:23: undefined reference to `sf::TcpSocket::receive(void*, unsigned int, unsigned int&)'
C:/Users/user/CppProjects/bang/main.cpp:28: undefined reference to `sf::TcpSocket::send(void const*, unsigned int)'
obj\Debug\main.o: In function `ZN2sf11TcpListenerD1Ev':
C:/Users/user/CppProjects/SFML-2.1/include/SFML/Network/TcpListener.hpp:43: undefined reference to `sf::Socket::~Socket()'
obj\Debug\main.o: In function `ZN2sf9TcpSocketD1Ev':
C:/Users/user/CppProjects/SFML-2.1/include/SFML/Network/TcpSocket.hpp:46: undefined reference to `sf::Socket::~Socket()'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
10 errors, 0 warnings
The settings I am using with the compiler:
Compiler Flags:
-std=C++0x
Other options:
-std=gnu++0x -U__STRICT_ANSI__
defines:
SFML_STATIC
Linker Settings:
sfml-system-s-d
sfml-network-s-d
Search Directories - Compiler:
C:\Users\user\CppProjects\SFML-2.1\include
C:\Users\user\CppProjects\bang\include
Search Directories - Linker:
C:\Users\user\CppProjects\SFML-2.1\lib\
Toolchain Executables:
-Compilers instalation dir:
C:\Program Files (x86)\mingw-builds\x32-4.8.1-posix-dwarf-rev5\mingw32
-C compiler:
i686-w64-mingw32-gcc-4.8.1.exe
-C++ Compiler:
i686-w64-mingw32-c++.exe
-Linker for dynamic libs:
i686-w64-mingw32-c++.exe
-Linker for static libs:
ar.exe
-Debugger:
gdb.exe
-Resource Compiler:
windres.exe
-Make Program:
mingw32-make.exe
I had a simular problem and how i solved this on a Linux system was: Project / build options
Go to linker settings tab.
there i added: sfml-network
Done.
Hope it helps

Linking/compiling a program that uses boost/filesystem.hpp

I'm trying to use the boost/filesystem library in some code that I am writing. I seem to be having a hard time getting it to compile. I'm running Debian Wheezy, and have boost version 1.49(which is what comes if you install using apt-get). I'm trying to compile an example that is available with the documentation
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: tut1 path\n";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
return 0;
}
I use the following command:
g++ temp.cc -o temp /usr/lib/libboost_filesystem.a
I get a number of errors such as:
/usr/lib/libboost_filesystem.a(operations.o): In function `boost::filesystem3::detail::dir_itr_close(void*&, void*&)':
(.text+0x4d): undefined reference to `boost::system::system_category()'
/usr/lib/libboost_filesystem.a(operations.o): In function `boost::filesystem3::detail::directory_iterator_increment(boost::filesystem3::directory_iterator&, boost::system::error_code*)':
(.text+0xe3): undefined reference to `boost::system::system_category()'
This is probably some linking error right? Any ideas on how I could solve it?
UPDATE #1:
I tried running it with the -lboost_filesyste and -L /usr/lib. It gives me the following error:
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
You are not linking the library properly. Also, as others mentioned, boost_filesystem needs also boost_system library. Use:
g++ temp.cc -o temp -lboost_system -lboost_filesystem
Command line param -l foo links libfoo.a library. If the static library is not in default library location, use command -L /custom/library/dir. But I believe /usr/lib is automatically taken into consideration by GCC.
Edit
According to your comment below it looks like you are not compiling the file with main() function, or you have a typo in main() name. Make sure that temp.cc contains one and only one of these functions:
int main();
int main(int argc, char** argv);
Of course you do remember that upper/lower case matters. :)
Boost.Filesystem uses things in Boost.System. You have to link against that, too.
The error messages that you are seeing:
/usr/lib/libboost_filesystem.a(operations.o): In function
`boost::filesystem3::detail::dir_itr_close(void*&, void*&)':
(.text+0x4d): undefined reference to `boost::system::system_category()'
that's a reference to Boost.System
Add -lboost_system and you should be good to go (or, at least better off).
Compile with -lboost_filesystem

xerces-c++ compile/linking question

After installing Xerces-C++ (XML library):
./configure --disable-shared
./make
./make-install
ldconfig
And writing the simple program (xmlval.cpp):
#include <stdio>
#include <xercesc/dom/DOM.hpp>
int main()
{
std::cout << "HI" << std::endl;
}
And compiling:
/usr/bin/g++ -L/usr/local/lib -I/usr/local/include -o xmlval xmlval.cpp /usr/local/lib/libxerces-c.a
The compile result is a bunch of lines like:
/usr/local/lib/libxerces-c.a(CurlNetAccessor.o): In function `xercesc_3_0::CurlNetAccessor::cleanupCurl()':
/home/stullbd/xerces-c-3.0.1/src/xercesc/util/NetAccessors/Curl/CurlNetAccessor.cpp:78: undefined reference to `curl_global_cleanup'
/usr/local/lib/libxerces-c.a(CurlNetAccessor.o): In function `xercesc_3_0::CurlNetAccessor::initCurl()':
/home/stullbd/xerces-c-3.0.1/src/xercesc/util/NetAccessors/Curl/CurlNetAccessor.cpp:70: undefined reference to `curl_global_init'
/usr/local/lib/libxerces-c.a(CurlURLInputStream.o): In function `~CurlURLInputStream':
/home/stullbd/xerces-c-3.0.1/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp:168: undefined reference to `curl_multi_remove_handle'
Any thoughts on this?
You seem to miss linking with curl, try adding -lcurl.