4

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)'|

2 Answers 2

5

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)
Sign up to request clarification or add additional context in comments.

3 Comments

Well ill be damned, it actually compiled. 2 things - I dont know why it gives me the error with that signature, but the code im showing in the main is exactly what i have to call NetCDF. Second - How can i specify my file location with your example if i am using target named All. Also, how can i add additional source files to the app?(Put multiple files in WILXAPP?)
I don't know what you mean by how can i specify my file location if i am using target named All ? If you mean, you want to be able to run make All and have it build the target, you just add a rule All : bin/Debug/WilxAstakTest. And yes, to add more source files you just add them to the WILXAPP variable. Note that this is not how things are normally done. You're passing source files directly to the linker, which means every time ANY file changes, ALL the files will be recompiled. That will get slow when you have a lot of source. Normally you build .o from .cpp first.
Thanks for you help and time. I think this will do nicely for start. I will read more on make and .o files when things get slow
3

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.