Unidata / netcdf-fortran

Official GitHub repository for netCDF-Fortran libraries, which depend on the netCDF C library. Install the netCDF C library first.
Other
244 stars 98 forks source link

Official Windows support via CMake #48

Open WardF opened 8 years ago

WardF commented 8 years ago

The cmake files for netcdf-fortran need to be overhauled, to leverage some of the knowledge gained whilst enhancing cmake support in netcdf-c. Part of this effort will also be to include official support for netCDF-Fortran using Windows compilers.

We are a bit hobbled by the fact that there aren't any free compilers (I can find) that are commonly used in conjunction with Microsoft Visual Studio. PGI and Intel Fortran Compilers seem to be the main two our community are using. The Intel compiler pricing is prohibitive at this point, but we should be able to get most of the way there using the PGI compilers.

arjenmarkusdeltaresnl commented 8 years ago

Recently I succeeded in building NetCDF4 on Windows using the MSVC++ and Intel Fortran compilers. The procedure is more or less straightforward, but there is one file that needed patching, netcdf-config.cmake.in. The computation of the prefix path is wrong. Here is the code I use for this:

Compute installation prefix relative to this file.

get_filename_component (_dir "@CMAKE_CURRENT_LIST_FILE@" PATH) get_filename_component (_prefix "@CMAKE_BINARY_DIR@" ABSOLUTE)

Note that I use CMake's "NMake Makefiles" generator and nmake rather than building via Visual Studio. The latter should not be a problem, but I seldom use that method in conjunction with CMake-based projects.

WardF commented 8 years ago

That is encouraging to hear, although I didn't realize you could use "NMake Makefiles" with Visual Studio projects. Thanks for the information re: the prefix path, that will be very helpful!

xiazemin commented 8 years ago

I tried my best to compile it with Visual studio2010 and Intel Fortran 2013 with CMake,but always failed.Can you give me some instructions or share a x86 lib for win7 with me(for research reason)? My email is 465474307@qq.com,Thank you very much.

arjenmarkusdeltaresnl commented 8 years ago

I have used VS 2013 and Intel Fortran 2015 myself. I did create a small batch file to automate things as much as possible, but I also see that it wants either VS 2012 or VS 2013. The reason for that is that the build procedure for HDF5 requires either of these (or else only batch and configuration files for these two environments are provided).

What are the symptoms? What messages do you get?

jbuonagurio commented 7 years ago

I eventually succeeded in building netCDF-Fortran with Intel Fortran 17.0 on Windows. Some notes on the process are below. Any advice is appreciated, maybe I could turn this into a pull request.

netCDF-C 4.4.1.1 Static Library

The Windows distribution for netCDF-C does not include static libraries so you need to build them yourself. I ran CMake with the following arguments, which may vary depending on your HDF5 configuration. If you want to build with a static CRT (/MT) you can also set NC_USE_STATIC_CRT=TRUE, but CMakeLists.txt needs to be rearranged so the macro definition is before the call to specify_static_crt_flag.

-G"NMake Makefiles"
-DCMAKE_BUILD_TYPE:STRING=RELEASE
-DBUILD_SHARED_LIBS=FALSE
-DHDF5_DIR:STRING="E:\HDF5-1.8.18-win32\cmake"
-DZLIB_LIBRARY:STRING="E:\HDF5-1.8.18-win32\lib\libzlib.lib"
-DZLIB_INCLUDE_DIR="E:\HDF5-1.8.18-win32\include"
-DNC_ENABLE_HDF_16_API=TRUE
-DENABLE_DAP=FALSE
-DENABLE_TESTS=FALSE
-DBUILD_TESTING=FALSE
-DNC_FIND_SHARED_LIBS=FALSE

netCDF-Fortran 4.4.4 Static Library

This is easier than a shared build. I ran CMake with the following arguments. This will build the library only; examples and tests will not build because additional libraries need to be passed to the linker and the current CMake script does not support this. These arguments should disable tests, but since there is no ENABLE_EXAMPLES option in CMakeLists.txt you will need to remove ADD_SUBDIRECTORY(examples) manually for a 'clean' build.

-G"NMake Makefiles"
-DCMAKE_BUILD_TYPE:STRING=RELEASE
-DCMAKE_Fortran_COMPILER:STRING="C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_2017.1.143/windows/bin/ia32/ifort.exe"
-DBUILD_SHARED_LIBS=FALSE
-DBUILD_V2=FALSE
-DENABLE_TESTS=FALSE
-DnetCDF_INCLUDE_DIR:STRING="E:\netcdf-4.4.1.1\include"
-DNETCDF_C_LIBRARY:STRING="E:/netcdf-4.4.1.1-build/liblib/netcdf.lib"

I could then build examples with the following 'one-liner', adjust as necessary for your HDF5 configuration:

ifort simple_xy_rd.f -I"E:\netcdf-fortran-4.4.4\fortran" /link
 /LIBPATH:"E:\netcdf-4.4.1.1-build\liblib"
 /LIBPATH:"E:\HDF5-1.8.18-win32\lib"
 /LIBPATH:"E:\netcdf-fortran-4.4.4-build\fortran"
 libzlib.lib libszip.lib libhdf5.lib libhdf5_hl.lib netcdf.lib netcdff.lib msvcrt.lib /NODEFAULTLIB:LIBCMT

netCDF-Fortran 4.4.4 Shared Library

You can use the same CMake arguments for the static library but set BUILD_SHARED_LIBS=TRUE and NETCDF_C_LIBRARY to the shared version of the C library, the one provided in the official Windows distribution will work. This will get you almost all the way there, but I had the exact same issues mentioned by @arjenmarkusdeltaresnl in the Intel Forums:

nf_nc4.f90.obj : error LNK2019: unresolved external symbol _nc_create_par_fortran referenced in function _NF_CREATE_PAR
nf_nc4.f90.obj : error LNK2019: unresolved external symbol _nc_open_par_fortran referenced in function _NF_OPEN_PAR
nf_nc4.f90.obj : error LNK2019: unresolved external symbol _nc_var_par_access referenced in function _NF_VAR_PAR_ACCESS
nf_v2compat.c.obj : error LNK2001: unresolved external symbol _ncerr
nf_v2compat.c.obj : error LNK2001: unresolved external symbol _ncopts

There are two problems here:

  1. The par functions are for parallel netCDF and are not available on Windows. I am guessing this issue would occur on other platforms as well if USE_PARALLEL was not defined in the C library.
  2. For some reason, the linker is not 'seeing' the ncerr and ncopts global variables defined in the declaration modifiers section of netcdf.h. This same problem is also described in a support thread: netCDF #KIS-873279. Not sure why this is happening just yet.

My temporary solution was just to remove all of those function calls from netCDF-Fortran because I didn't need them. I think a proper solution would involve either of a couple options:

  1. On the netCDF-C side: add stubs for par functions even if the parallel build is disabled. Maybe they could just call the non-parallel versions.
  2. On the netCDF-Fortran side: use preprocessor macros to conditionally remove definitions of the par functions, or make them call the non-parallel versions.

I'm not sure yet how to resolve the issue with ncerr and ncopts.

luzpaz commented 5 years ago

121

MuellerSeb commented 4 years ago

268