Search code examples
c++linuxg++gdal

g++ failing when trying to use GDAL library


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.


Solution

    • 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.