Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetCDF 4.8.1 does not work on windows #3731

Closed
Alexander-Barth opened this issue Oct 12, 2021 · 18 comments
Closed

NetCDF 4.8.1 does not work on windows #3731

Alexander-Barth opened this issue Oct 12, 2021 · 18 comments
Labels
Windows 🙄 Doesn't build for Windows

Comments

@Alexander-Barth
Copy link
Contributor

Unfortunately, there is an issue with my PR #3620.
The windows binary does not seem to work. The size of the library is also suspiciously small. Symbols like nc_inq_libvers are no longer found.

@Alexander-Barth
Copy link
Contributor Author

It seems that the users gets libnetcdf.dll.a while the NetCDF functions are in libnetcdf-19.dll. I am not sure about the difference between these files.

sandbox:${WORKSPACE}/srcdir/netcdf-c-4.8.1 # nm /workspace/destdir/lib/libnetcdf.dll.a  | grep nc_inq_libver
sandbox:${WORKSPACE}/srcdir/netcdf-c-4.8.1 # nm /workspace/srcdir/netcdf-c-4.8.1/liblib/.libs/libnetcdf-19.dll | grep nc_inq_libver
0000000066f483e0 T nc_inq_libvers

@giordano
Copy link
Member

giordano commented Oct 12, 2021

Libraries for Windows are under bin/, not lib/:

sandbox:${WORKSPACE} # nm libnetcdf-19.dll | grep nc_inq_libvers
0000000066f483e0 T nc_inq_libvers

@Alexander-Barth
Copy link
Contributor Author

You are right. I should look at libnetcdf-19.dll in bin. Still for some reasons I get this error in my package:

https://github.com/Alexander-Barth/NCDatasets.jl/runs/3870249033?check_suite_focus=true#step:7:85

@Alexander-Barth
Copy link
Contributor Author

On a windows machine, I can see the function nc_inq_libvers using MSYS2's nm:

Alexander Barth@alex-laptop MSYS /c/Users/Alexander Barth/.julia/artifacts/ae78b073115f5cca9ab13a23994bdd930ecfe887/bin
$ /mingw64/bin/nm.exe libnetcdf-19.dll  | grep nc_inq_libvers
0000000066f483e0 T nc_inq_libvers

But in Julia 1.6.2, this function cannot be found:

julia> using NetCDF_jll

julia> ccall((:nc_inq_libvers,libnetcdf),Cstring,())
ERROR: could not load symbol "nc_inq_libvers":
The specified procedure could not be found.
Stacktrace:
 [1] top-level scope
   @ .\REPL[31]:1

(@v1.6) pkg> st NetCDF_jll
      Status `C:\Users\Alexander Barth\.julia\environments\v1.6\Project.toml`
  [7243133f] NetCDF_jll v400.802.100+0

julia> nclib = Libdl.dlopen(libnetcdf)
Ptr{Nothing} @0x0000000066f40000

julia> dlsym(nclib,:nc_inq_libvers)
ERROR: could not load symbol "nc_inq_libvers":
The specified procedure could not be found.
Stacktrace:
 [1] #dlsym#1
   @ .\libdl.jl:56 [inlined]
 [2] dlsym(hnd::Ptr{Nothing}, s::Symbol)
   @ Base.Libc.Libdl .\libdl.jl:54
 [3] top-level scope
   @ REPL[34]:1

@giordano
Copy link
Member

What if you dlopen the library with RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL? See for example https://discourse.julialang.org/t/problem-when-loading-intel-mkl-shared-library-to-use-with-c-written-shared-library/69323/9

@Alexander-Barth
Copy link
Contributor Author

Unfortunately, this is still the same (from a fresh julia session):

julia> using NetCDF_jll, Libdl

julia> nclib = Libdl.dlopen(libnetcdf,RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL)
Ptr{Nothing} @0x0000000066f40000

julia> dlsym(nclib,:nc_inq_libvers)
ERROR: could not load symbol "nc_inq_libvers":
The specified procedure could not be found.
Stacktrace:
 [1] #dlsym#1
   @ .\libdl.jl:56 [inlined]
 [2] dlsym(hnd::Ptr{Nothing}, s::Symbol)
   @ Base.Libc.Libdl .\libdl.jl:54
 [3] top-level scope
   @ REPL[5]:1

I am trying with the old NetCDF library to see what could be the difference.

@giordano
Copy link
Member

If you do that after using NetCDF_jll, the library had been already dlopened, I'm not sure it'd be dlopened a second time

@Alexander-Barth
Copy link
Contributor Author

Alexander-Barth commented Oct 12, 2021

Just after restarting julia:

julia> const oldlibnetcdf = "c:\\Users\\Alexander Barth\\.julia\\artifacts\\a81fe95ac632a7fa76c5e9cbe522c998aee9fa21\\bin\\libnetcdf-18.dll"
"c:\\Users\\Alexander Barth\\.julia\\artifacts\\a81fe95ac632a7fa76c5e9cbe522c998aee9fa21\\bin\\libnetcdf-18.dll"

julia> isfile(oldlibnetcdf)
true

julia> using Libdl

julia> ccall((:nc_inq_libvers,oldlibnetcdf),Cstring,())
ERROR: could not load library "c:\Users\Alexander Barth\.julia\artifacts\a81fe95ac632a7fa76c5e9cbe522c998aee9fa21\bin\libnetcdf-18.dll"
The specified module could not be found.
Stacktrace:
 [1] top-level scope
   @ .\REPL[4]:1

julia> using NetCDF_jll

julia> ccall((:nc_inq_libvers,oldlibnetcdf),Cstring,())
Cstring(0x0000000068391260)

julia> unsafe_string(ccall((:nc_inq_libvers,oldlibnetcdf),Cstring,()))
"4.7.4 of Jan 26 2021 22:47:01 \$"

Maybe using NetCDF_jll loads also the dependencies which makes the old library usuable?

@giordano
Copy link
Member

Maybe using NetCDF_jll loads also the dependencies which makes the old library usuable?

Correct and this is very likely the cause of the error here

@Alexander-Barth
Copy link
Contributor Author

I am not sure if this is relevant, but the new library is also linked against apphelp.dll (present on my windows machine)

Alexander Barth@alex-laptop MSYS /c/Users/Alexander Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/bin
$ ldd ../../ae78b073115f5cca9ab13a23994bdd930ecfe887/bin/libnetcdf-19.dll
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffb0e970000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ffb0dbd0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ffb0c220000)
        apphelp.dll => /c/WINDOWS/SYSTEM32/apphelp.dll (0x7ffb09540000)
        libnetcdf-19.dll => /c/Users/Alexander Barth/.julia/artifacts/ae78b073115f5cca9ab13a23994bdd930ecfe887/bin/libnetcdf-19.dll (0x66f40000)
        msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ffb0dc90000)

Alexander Barth@alex-laptop MSYS /c/Users/Alexander Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/bin
$ ldd libnetcdf-18.dll
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffb0e970000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ffb0dbd0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ffb0c220000)
        libnetcdf-18.dll => /c/Users/Alexander Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/bin/libnetcdf-18.dll (0x682c0000)
        msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ffb0dc90000)

@giordano
Copy link
Member

giordano commented Oct 12, 2021

Don't trust ldd, it dynamically dlopens a library and shows all libraries found on the current system, not the libraries the binary objects links to:

sandbox:${WORKSPACE} # ${target}-objdump -x libnetcdf-19.dll | grep "DLL Name"
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: libcurl-4.dll
        DLL Name: libhdf5_hl-0.dll
        DLL Name: libhdf5-0.dll

@Alexander-Barth
Copy link
Contributor Author

OK, good to know.
I am trying to compile a simple C program using NetCDF

First with NetCDF 4.7.4: this works

Alexander Barth@alex-laptop MINGW64 /c/Users/Alexander Barth/Downloads
$ cp /c/Users/Alexander\ Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/bin/libnetcdf-18.dll .

Alexander Barth@alex-laptop MINGW64 /c/Users/Alexander Barth/Downloads
$ gcc -I/c/Users/Alexander\ Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/include/ simple_xy_wr.c -L/c/Users/Alexander\ Barth/.julia/artifacts/a81fe95ac632a7fa76c5e9cbe522c998aee9fa21/lib -lnetcdf^C

Alexander Barth@alex-laptop MINGW64 /c/Users/Alexander Barth/Downloads
$ ./a.exe
*** SUCCESS writing example file simple_xy.nc!

Then with NetCDF 4.8.1 whichs fails. The compiler is unable to find any functions. Maybe they are not exported?

Alexander Barth@alex-laptop MINGW64 /c/Users/Alexander Barth/Downloads
$ cp /c/Users/Alexander\ Barth/.julia/artifacts/ae78b073115f5cca9ab13a23994bdd930ecfe887/bin/libnetcdf-19.dll .

Alexander Barth@alex-laptop MINGW64 /c/Users/Alexander Barth/Downloads
$ gcc -o simple_xy_wr_nc481 -I/c/Users/Alexander\ Barth/.julia/artifacts/ae78b073115f5cca9ab13a23994bdd930ecfe887/include/ simple_xy_wr.c -L/c/Users/Alexander\ Barth/.julia/artifacts/ae78b073115f5cca9ab13a23994bdd930ecfe887/lib -lnetcdf
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0xa4): undefined reference to `nc_create'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0xc0): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0xfd): undefined reference to `nc_def_dim'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x119): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x156): undefined reference to `nc_def_dim'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x172): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x1db): undefined reference to `nc_def_var'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x1f7): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x21d): undefined reference to `nc_enddef'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x239): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x26c): undefined reference to `nc_put_var_int'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x288): undefined reference to `nc_strerror'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x2ae): undefined reference to `nc_close'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccI2WaKl.o:simple_xy_wr.c:(.text+0x2ca): undefined reference to `nc_strerror'
collect2.exe: error: ld returned 1 exit status

@Alexander-Barth
Copy link
Contributor Author

Using Dependency Walker on Windows or with objdump -p libnetcdf-19.dll on Linux, it seems that the Export Address Table is much longer in the old version 4.7.4 than in the new version 4.8.1 (13 symbols versus 1771 symbols).

@Alexander-Barth
Copy link
Contributor Author

I found a way to force the export of all symbols. But I am facing now a different issue on Windows:

Unidata/netcdf-c#2124

Would it be possible to rollback the upgrade to its previous version? Sorry for all this confusion!

@giordano
Copy link
Member

I found a way to force the export of all symbols

Did you also try to do a native build with the same build options? Or is there any native build for Windows already available? I don't think we do anything special with regard to symbols being exported or not, so I'm curious to see what happens outside of BinaryBuilder.

Would it be possible to rollback the upgrade to its previous version? Sorry for all this confusion!

You can yank the offending versions in the registry.

@Alexander-Barth
Copy link
Contributor Author

So far, I did not try to make a native build and I am not aware of any native build available. Unfortunately, mingw64 is not officially supported by NetCDF (only the Microsoft C compiler on Windows) and the library contains a lot of platform specific code.

For your information, I needed the use the -Wl,--export-all-symbols flag:

diff --git a/N/NetCDF/common.jl b/N/NetCDF/common.jl
index 3c04a6c1..8176f14f 100644
--- a/N/NetCDF/common.jl
+++ b/N/NetCDF/common.jl
@@ -34,7 +34,7 @@ if [[ ${target} == *-mingw* ]]; then
     export LIBS="-lhdf5-0 -lhdf5_hl-0 -lcurl-4 -lz"
     # linking fails with: "libtool:   error: can't build x86_64-w64-mingw32 shared library unless -no-undefined is specified"
     # unless -no-undefined is added to LDFLAGS
-    LDFLAGS_MAKE="${LDFLAGS} ${LIBS} -no-undefined"
+    LDFLAGS_MAKE="${LDFLAGS} ${LIBS} -no-undefined -Wl,--export-all-symbols"
 
     # testset fails on mingw (NetCDF 4.8.1)
     # libtool: link: cc -fno-strict-aliasing -o .libs/pathcvt.exe pathcvt.o  -L/workspace/destdir/bin ../liblib/.libs/libnetcdf.dll.a -lhdf5-0 -lhdf5_hl-0 -lcurl-4 -lz -L/workspace/destdir/lib

I found this concerning the --export-all-symbols flag: https://sourceware.org/binutils/docs-2.37/ld.html#WIN32
I hope to find some more time to debug this issue and make a native build on Windows.

Thank you for the suggestion to yank the version in the registry. This is done now.

@giordano
Copy link
Member

I believe I'm crashing into this issue in #4344. Honestly, I have zero clue about what's wrong with the Windows build, but I confirm it looks "broken"

@Alexander-Barth
Copy link
Contributor Author

Here is a fresh attempt:
https://github.com/Alexander-Barth/Yggdrasil/tree/NetCDF-v4.8.1/N/NetCDF

I tried to find some volunteers to test the library before I make a PR:
Alexander-Barth/NCDatasets.jl#165

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Windows 🙄 Doesn't build for Windows
Projects
None yet
Development

No branches or pull requests

3 participants