Russ,
I'll try to give a better example:
I don't have hdf-libraries installed (at least not in default pathes).
First, from a pure ABI point of view:
---------------------------------------------------------------
With netcdf-4.1.2:
./configure --prefix=/disk1/netcdf-4.1.2_install
make
make install
In /disk1/netcdf-4.1.2_install/include:
$ grep nc_def_var_deflate netcdf.h
* function nc_def_var_deflate. These defines are used there. */
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
In /disk1/netcdf-4.1.2_install/lib:
$ nm libnetcdf.so | grep nc_def_var_deflate
Nothing found, symbol not defined.
--------------------------------------------------------------
New try, all directories removed and new untar:
./configure --prefix=/disk1/netcdf-4.1.2_install --disable-netcdf4
make
make install
In /disk1/netcdf-4.1.2_install/lib:
$ nm libnetcdf.so | grep nc_def_var_deflate
Nothing found, symbol not defined. Still the same.
---------------------------------------------------------------
New try, now 4.2:
$ ./configure --prefix=/disk1/netcdf-4.2_install --disable-netcdf-4
make
make install
In /disk1/netcdf-4.2_install/lib
$ nm libnetcdf.so | grep nc_def_var_deflate
Nothing found, symbol not defined.
---------------------------------------------------------------
A previous build, with hdf5 enabled:
$ nm /disk1/heiko/local/netcdf4.2-rc1/lib/libnetcdf.so | grep
nc_def_var_deflate
000299b0 T nc_def_var_deflate
----------------------------------------------------------------
Now, from a API point of view:
a slightly modified simple_xy_wr.c (from
http://www.unidata.ucar.edu/software/netcdf/examples/programs/), just
enabling compression if netcdf4 is supported by the library:
#ifdef NC_NETCDF4
/* compress all variables in netcdf4 */
if ((retval = nc_def_var_deflate(ncid, varid, 0, 1, 3)))
ERR(retval);
#endif
The program works nicely with netcdf-4.1.1, independently of netcdf4 is
enabled or disabled.
$ gcc -c -I/opt/netcdf4.1.1/include/ simple_xy_wr.c
$ gcc -o simple_xy_wr simple_xy_wr.o -L/opt/netcdf4.1.1/lib/ -lnetcdf
No problems
With above 4.2:
$ gcc -c -I/disk1/netcdf-4.2_install/include/ simple_xy_wr.c
No problems.
$ gcc -o simple_xy_wr simple_xy_wr.o -L/disk1/netcdf-4.2_install/lib
-lnetcdf
simple_xy_wr.o: In function `main':
simple_xy_wr.c:(.text+0x27d): undefined reference to `nc_def_var_deflate'
collect2: ld returned 1 exit status
With 4.2, but with enabled hdf/netcdf4 support (ok, that's 4.2rc1, but
that not the point here):
$ gcc -c -I/disk1/heiko/local/netcdf4.2-rc1/include simple_xy_wr.c
No problems
$ gcc -o simple_xy_wr simple_xy_wr.o
-L/disk1/heiko/local/netcdf4.2-rc1/lib -lnetcdf
No problems, generating netcdf4 files.
I see the code of nc_def_var_deflate defined in libdispatch/dvar.c, but
it doesn't seem to make it to the library.
Best regards,
Heiko
On 2012-04-26 18:51, Russ Rew wrote:
Heiko,
since netcdf-4.1.2, the netcdf.h file declares all netcdf4 functions,
like nc_def_var_deflate and NC_NETCDF4, even if the library was compiled
without hdf5 support, and does not have these functions.
I have code like
#ifdef NC_NETCDF4
nc_def_var_deflate(...)
#endif
which worked perfectly with netcdf3 and netcdf4 until 4.1.1. Since
netcdf 4.1.2, this code compiles still, but when the netcdf-library was
not compiled with hdf5 support, the code won't link with the library.
This means, that netcdf since 4.1.2 has a single API, but has different
ABIs depending on netcdf-configure flags. I would suggest adding the
'Extra netcdf4 stuff.' function calls to the netcdf3 code, even if they
are empty, e.g.
int
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
int deflate_level)
{
return NC_NOERR;
}
This means, that netcdf since 4.1.2 has a single API, but has different
ABIs depending on netcdf-configure flags. I would suggest adding the
'Extra netcdf4 stuff.' function calls to the netcdf3 code, even if they
are empty, e.g.
int
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
int deflate_level)
{
return NC_NOERR;
}
Sorry, but I can't duplicate the problem. This is supposed to be
handled by the "dispatch layer" in netCDF-4.x. For example, when you
run "make check" on a netCDF-4.2 distribution that has been configured
with "--disable-netcdf-4", it will link and run netCDF-3 tests against
the library, so this would indicate all the public functions declared in
netcdf.h must be implemented.
The following function appears in libdispatch/dvar.c, even when
configured with "--disable-netcdf-4":
int
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int
deflate_level)
{
NC* ncp;
int stat = NC_check_id(ncid,&ncp);
if(stat != NC_NOERR) return stat;
return
ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level);
}
I've also just tried building the 4.2 library with --disable-netcdf-4
and --disable-shared, and verified that a netCDF-3 program compiles and
links with the resulting static library. However, I had to remove
previously built shared libraries from the directory in which I
installed the static library, because the dynamic linker/loader will use
an older installed shared library in preference to a new static library.
I also built a new shared library with --disable-netcdf-4 but without
--disable-shared and verified that a netCDF-3 program could be
successfully linked and run against the resulting shared library. For
this, I set LD_LIBRARY_PATH to run the resulting program, but other
alternatives would also work, assuming the library is installed in
LIBDIR:
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have system administrator add LIBDIR to `/etc/ld.so.conf'
This was all on a Linux system, but our cross-platform tests should
catch such problems on some other systems, such as Solaris, MacOS, and
AIX.
It's possible I've misunderstood the problem. If so, I'll need more
information to reproduce it. For now, I think the dispatch layer
implementation already provides the stub functions for 'extra netCDF-4
stuff' that you're requesting ...
--Russ
Note: as Dennis Heimbigner pointed out last week on this list, for now
it's necessary to build netCDF-4.2 with "--disable-dap-remote-tests", at
least until we resolve a problem with the test server, which was moved
from port 8080 to 8081.
--
Dr. Heiko Klein Tel. + 47 22 96 32 58
Development Section / IT Department Fax. + 47 22 69 63 55
Norwegian Meteorological Institute http://www.met.no
P.O. Box 43 Blindern 0313 Oslo NORWAY
/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is a very simple example which writes a 2D array of
sample data. To handle this in netCDF we create two shared
dimensions, "x" and "y", and a netCDF variable, called "data".
This example demonstrates the netCDF C API. This is part of the
netCDF tutorial, which can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
Full documentation of the netCDF C API can be found at:
http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c
$Id: simple_xy_wr.c,v 1.11 2006/09/27 13:44:36 ed Exp $
*/
#include <stdlib.h>
#include <stdio.h>
#include <netcdf.h>
/* This is the name of the data file we will create. */
#define FILE_NAME "simple_xy.nc"
/* We are writing 2D data, a 6 x 12 grid. */
#define NDIMS 2
#define NX 6
#define NY 12
/* Handle errors by printing an error message and exiting with a
* non-zero status. */
#define ERRCODE 2
#define ERR(e) {printf("Error: %s\n", nc_strerror(e)); exit(ERRCODE);}
int
main()
{
/* When we create netCDF variables and dimensions, we get back an
* ID for each one. */
int ncid, x_dimid, y_dimid, varid, filetype;
int dimids[NDIMS];
/* This is the data array we will write. It will just be filled
* with a progression of numbers for this example. */
int data_out[NX][NY];
/* Loop indexes, and error handling. */
int x, y, retval;
/* Create some pretend data. If this wasn't an example program, we
* would have some real data to write, for example, model
* output. */
for (x = 0; x < NX; x++)
for (y = 0; y < NY; y++)
data_out[x][y] = x * NY + y;
/* Always check the return code of every netCDF function call. In
* this example program, any retval which is not equal to NC_NOERR
* (0) will cause the program to print an error message and exit
* with a non-zero return code. */
/* Create the file. The NC_CLOBBER parameter tells netCDF to
* overwrite this file, if it already exists.*/
#ifdef NC_NETCDF4
filetype = NC_CLOBBER | NC_NETCDF4;
#endif
if ((retval = nc_create(FILE_NAME, filetype, &ncid)))
ERR(retval);
/* Define the dimensions. NetCDF will hand back an ID for each. */
if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid)))
ERR(retval);
if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid)))
ERR(retval);
/* The dimids array is used to pass the IDs of the dimensions of
* the variable. */
dimids[0] = x_dimid;
dimids[1] = y_dimid;
/* Define the variable. The type of the variable in this case is
* NC_INT (4-byte integer). */
if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS,
dimids, &varid)))
ERR(retval);
#ifdef NC_NETCDF4
/* compress all variables in netcdf4 */
if ((retval = nc_def_var_deflate(ncid, varid, 0, 1, 3)))
ERR(retval);
#endif
/* End define mode. This tells netCDF we are done defining
* metadata. */
if ((retval = nc_enddef(ncid)))
ERR(retval);
/* Write the pretend data to the file. Although netCDF supports
* reading and writing subsets of data, in this case we write all
* the data in one operation. */
if ((retval = nc_put_var_int(ncid, varid, &data_out[0][0])))
ERR(retval);
/* Close the file. This frees up any internal netCDF resources
* associated with the file, and flushes any buffers. */
if ((retval = nc_close(ncid)))
ERR(retval);
printf("*** SUCCESS writing example file simple_xy.nc!\n");
return 0;
}