Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking and using netCDF with gcc

Im trying to use netCDF library in my C++ project, but i cannot, for some reason, use it.

Here is my make file

NETCDF = -L/usr/lib -lnetcdf_c++
WILXAPP = -Lsrc src/wilxtest.cpp -o bin/Debug/WilxAstakTest

Debug:
    g++ -Wall -ggdb $(NETCDF) $(WILXAPP)

In my cpp file i basically have (removed bloat)

#include <iostream>
#include <netcdfcpp.h>

int main(int argc, char* argv[])
{
   NcFile dataFile("simple_xy.nc", NcFile::Replace);
}

And I get this:

 undefined reference to `NcFile::NcFile(char const*, NcFile::FileMode, unsigned long*, unsigned long, NcFile::FileFormat)'|
like image 654
user1047833 Avatar asked Feb 15 '23 20:02

user1047833


2 Answers

I'm not sure that the errors you're providing match the source you're showing, since the undefined reference for the constructor signature has no relationship to the way you've invoked the constructor in your example.

Anyway, I suspect your problem is that order matters on the link line. The linker only walks through its libraries etc. one time, so if something that comes LATER on the link line needs something that comes EARLIER on the link line, you fail. You must order your link line such that things that require other things come first, and things that are required come later.

A few other tips: the -L option only gives search paths for libraries, so you don't need -Lsrc here as there's no library you're linking from the src directory. Also you don't need to add -L/usr/lib (in fact, it's a very bad idea) as the compiler already searches the system directories in the proper order, and on many systems (that support multiple architectures for example) /usr/lib won't be the right place.

Finally, when writing makefiles always remember that the recipe should create the exact filename of the target: for GNU make you can use $@ for that in all cases. And you need to use the source file as a prerequisite, otherwise you might as well not bother using make and just write a shell script. Try this:

NETCDF = -lnetcdf_c++
WILXAPP = src/wilxtest.cpp
CXX = g++
CXXFLAGS = -Wall -ggdb

bin/Debug/WilxAstakTest: $(WILXAPP)
        $(CXX) $(CXXFLAGS) -o $@ $^ $(NETCDF)
like image 169
MadScientist Avatar answered Feb 18 '23 11:02

MadScientist


Solved the very same problem by combining MadScientist's answer (almost complete) with a solution by "Russ" I found in an archived email in the UniData support pages (http://www.unidata.ucar.edu/support/help/MailArchives/netcdf/msg04846.html):

You need to add "-lnetcdf" to the end of your g++ invocation. If you run "make test" in the src/cxx directory, you will see this is how the test program is linked. So use something like:

g++ -o example -I<PATH>netcdf-3.5.1-beta13/include example.cpp -L<PATH>netcdf-3.5.1-beta13/lib -lnetcdf_c++ -lnetcdf

if you want to do the compile and link all in one step.

The default installation stores the C++ library in a different library file than the C library, but I think you could use ld to combine them into a single library for convenience. There were portability problems with trying to do this on all platforms, so the interfaces are distributed to use separate libraries.

--Russ

The point is: you need to link BOTH -lnetcdf_c++ AND -lnetcdf ... in this order. My 'makefile' looks like this:

NETCDF = -lnetcdf_c++ -lnetcdf
APP = main.cpp
CXX = g++
CXXFLAGS = -Wall -ggdb

Example: $(APP)
    $(CXX) $(CXXFLAGS) -o $@ $^ $(NETCDF)

m. (MyselfAnotherMadScientist)

like image 37
Mathis Avatar answered Feb 18 '23 09:02

Mathis