1

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.

José L. Patiño
  • 3,683
  • 2
  • 29
  • 28
  • @RichardCritten I think the answer "Failure to link against appropriate libraries/object files or compile implementation files" in that post does indeed answer my question, yes. Quimby's comment was however more concise and clear to my specific answer this time. – José L. Patiño Nov 29 '22 at 10:45

1 Answers1

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

Quimby
  • 17,735
  • 4
  • 35
  • 55
  • 1
    That was a fast and clear response, thank you very much. Moving the `-lgdal` argument to the end made it as you just said. So: `g++ -I/usr/include/gdal -L/usr/lib open_file.cpp -o open_file -g -lgdal` – José L. Patiño Nov 29 '22 at 10:35
  • 1
    In addition, thank you for pointing that my `-I` and `-L` arguments are also not necessary if you specify it in your includes, e.g. `#include "gdal/gdal_priv.h"`. I just assumed they were always needed for the compiler to see the library inside the `/usr/include` directory. – José L. Patiño Nov 29 '22 at 10:42
  • 1
    @JoséL.Patiño No problem :) [There are some default include paths](https://stackoverflow.com/a/11946295/7691729) for system-wide packages installed by `apt` (or other package managers). Custom ones are, well, if the default do not work ;) – Quimby Nov 29 '22 at 11:34