Closed seisman closed 4 years ago
tool -L gmt says what?
$ otool -L gmt
gmt:
/usr/local/opt/netcdf/lib/libnetcdf.15.dylib (compatibility version 15.0.0, current version 15.0.0)
/usr/lib/libcurl.4.dylib (compatibility version 7.0.0, current version 9.0.0)
/usr/local/opt/gdal/lib/libgdal.20.dylib (compatibility version 26.0.0, current version 26.2.0)
@rpath/libpcre.1.dylib (compatibility version 4.0.0, current version 4.11.0)
/usr/local/opt/fftw/lib/libfftw3f.3.dylib (compatibility version 9.0.0, current version 9.8.0)
/usr/local/opt/fftw/lib/libfftw3f_threads.3.dylib (compatibility version 9.0.0, current version 9.8.0)
/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate (compatibility version 1.0.0, current version 4.0.0)
/usr/local/opt/glib/lib/libglib-2.0.0.dylib (compatibility version 6201.0.0, current version 6201.4.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
The file size of the gmt executable is ~4.6 Mb.
So is there static libraries being built. All that stuff in libgmt should now be in gmt.exe, no? But that cannot be the case. Are there any libgmt* files being produced?
I think the static libraries are already included in the gmt executable. That's why the gmt.exe is as large as 4.6 Mb.
The static libraries are still being built in the lib directory. Below are what I have in my lib directory
.
├── gmt
│ └── plugins
│ └── supplements.so
├── libgmt.6.1.0.dylib
├── libgmt.6.dylib -> libgmt.6.1.0.dylib
├── libgmt.a
├── libgmt.dylib -> libgmt.6.dylib
├── libpostscriptlight.6.1.0.dylib
├── libpostscriptlight.6.dylib -> libpostscriptlight.6.1.0.dylib
├── libpostscriptlight.a
└── libpostscriptlight.dylib -> libpostscriptlight.6.dylib
Does nm -gU gmt
list all the expected symbols that normally would be listed by
nm -gU libgmt.dylib | grep GMT_grdimage
000000000045db90 T _GMT_grdimage
Sorry, I mixed the libraries from the static and shared builds. For static build, I have
.
├── gmt
│ └── plugins
│ └── supplements.so
├── libgmt.a
└── libpostscriptlight.a
Does
nm -gU gmt
list all the expected symbols that normally would be listed bynm -gU libgmt.dylib | grep GMT_grdimage 000000000045db90 T _GMT_grdimage
Yes.
gmt coast -Vd
gives:
gmt coast -Vd 78 ↵
gmt [DEBUG]: Obtained the ppid from parent: 56674
gmt [DEBUG]: Enter: gmtinit_new_GMT_ctrl
gmt [DEBUG]: GMT->session.SHAREDIR = /Users/seisman/local/GMT/share
gmt [DEBUG]: GMT->session.HOMEDIR = /Users/seisman
gmt [DEBUG]: GMT->session.USERDIR = /Users/seisman/.gmt [created]
gmt [DEBUG]: GMT->session.CACHEDIR = /Users/seisman/.gmt/cache [created]
gmt [DEBUG]: GMT: 0. Will try to find subdir=postscriptlight stem = PSL_custom_fonts suffix=.txt
gmt [DEBUG]: GMT: 1. gmt_getsharepath trying current dir
gmt [DEBUG]: GMT: 2. gmt_getsharepath trying USERDIR /Users/seisman/.gmt
gmt [DEBUG]: Map distance calculation will be Cartesian
gmt [DEBUG]: Exit: gmtinit_new_GMT_ctrl
gmt [DEBUG]: Enter: New_PSL_Ctrl
gmt [DEBUG]: Exit: New_PSL_Ctrl
gmt [DEBUG]: Enter: gmt_manage_workflow
gmt [DEBUG]: Exit : gmt_manage_workflow
gmt [DEBUG]: Enter: PSL_beginsession
gmt [DEBUG]: Exit : PSL_beginsession
gmt [DEBUG]: Enter: PSL_setdefaults
gmt [DEBUG]: Exit : PSL_setdefaults
gmt [DEBUG]: Enter: gmtlib_io_init
gmt [DEBUG]: Exit : gmtlib_io_init
gmt [DEBUG]: Enter: gmt_hash_init
gmt [DEBUG]: Exit: gmt_hash_init
gmt [DEBUG]: Enter: gmt_hash_init
gmt [DEBUG]: Exit: gmt_hash_init
gmt [DEBUG]: The PROJ_GEODESIC set to Vincenty
gmt [DEBUG]: Enter: gmt_getdefaults
gmt [DEBUG]: Look for file /Users/seisman/gmt.conf
gmt [DEBUG]: Look for file /Users/seisman/.gmt/gmt.conf
gmt [DEBUG]: Look for file /Users/seisman/.gmt/server/gmt.conf
gmt [DEBUG]: Look for file /Users/seisman/.gmt/cache/gmt.conf
gmt [DEBUG]: Could not find file gmt.conf
gmt [DEBUG]: Exit: gmt_getdefaults
gmt [DEBUG]: Enter: gmtlib_plot_C_format
gmt [DEBUG]: Exit: gmtlib_plot_C_format
gmt [DEBUG]: Enter: gmt_get_history
gmt [DEBUG]: Initialize FFTW with 8 threads.
gmt [DEBUG]: GMT_Create_Session initialized GMT structure
gmt [DEBUG]: Shared Library # 0 (core). Path = libgmt.a
gmt [DEBUG]: Loading GMT plugins from: /Users/seisman/local/GMT/bin/gmt/plugins
ERROR: No module named coast was found. This could mean one of four cases:
1. There actually is no such module; please check your spelling.
2. You used a modern mode module name while running in GMT classic mode.
3. Module exists in the GMT supplemental library, but the library could not be found.
4. Module exists in a GMT custom library, but none was specified via GMT_CUSTOM_LIBS.
Shared libraries must be in standard system paths or set via environmental parameter DYLD_LIBRARY_PATH.
gmt [DEBUG]: Entering GMT_Destroy_Session
Our code for getting the pointer to the selected module assumes shared library I think. Perhaps the stuff in gmt_api.c (_api_initsharedlibs) and loop over shared libs in _GMT_CallModule is just wrong for static. If static, don't we just call that function directly? I.e., instead of things like
for (lib = 0; lib < API->n_shared_libs; lib++) { /* Look for gmt_module in any of the shared libs */
*(void **) (&p_func) = api_get_module_func (API, gmt_module, lib);
if (p_func) break; /* Found it in this shared library */
}
we simply have
`*(void **) (&p_func) = gmt_core_module_lookup (API, gmt_module);`
and then
`status = (*p_func) (V_API, mode, args); /* Call the module in peace */`
i.e., no checking.
It sounds correct.
Shall I have a look at this or have you already started? I think I can get this working pretty quickly if I can find what #defines are used for the static vs shared.
I know little about shared libraries, so you may need to take a look at it.
OK, will have a look.
About done - the gmt_make_module_src.sh needed some updates. Running tests now.
Progress. Got all to run but accessing GMT parameters from supplemental functions yields trouble and failed tests:
265 - geodesy/test_earthtide.sh (Failed)
450 - img/imgmap.sh (Failed)
451 - img/imgtrack.sh (Failed)
805 - spotter/spotter_06.sh (Failed)
834 - x2sys/x2sys_05.sh (Failed)
The log has stuff like
earthtide [ERROR]: Syntax error: Unrecognized keyword FORMAT_FLOAT_OUT.
Don't know what that means so need to debug.
Returning to this with the plan to debug but now I am unable to build. Perhaps something changed with Xcode or with our CMake system? It is failing at this point now:
[219/248] Linking C static library src/libpostscriptlight.a
FAILED: src/libpostscriptlight.a
: && /opt/local/bin/cmake -E remove src/libpostscriptlight.a && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar qc src/libpostscriptlight.a src/CMakeFiles/pslib.dir/postscriptlight.c.o && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib src/libpostscriptlight.a && /opt/local/bin/cmake -E touch src/libpostscriptlight.a && cd /Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/gmt-dev/dbuild/src && /usr/bin/dsymutil /Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/gmt-dev/dbuild/src/libpostscriptlight.a
error: cannot parse the debug map for '/Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/gmt-dev/dbuild/src/libpostscriptlight.a': The file was not recognized as a valid object file
[225/248] Building C object src/CMakeFiles/testgmt.dir/testgmt.c.o
ninja: build stopped: subcommand failed.
Previously it built just fine and we were having some issued with external variables I think.
The same happens to me, but I don't think we made any changes to cmake recently, except #2667, which is unmerged.
I switched to Xcode 10.3 and got the same. Wonder if there is some setting in the ConfigUser that I am missing relative to when I did this 26 days ago...
I don't know what happened, but now I can do the static builds again. @PaulWessel Please try again.
Strange, I still get (this time at work - yesterday was at home):
error: cannot parse the debug map for '/Users/pwessel/GMTdev/gmt-dev/dbuild/src/libpostscriptlight.a': The file was not recognized as a valid object file
Googling indicates it has to do with debug information being stripped off before this command runs. Based on that information it was suggested to add these:
set_target_properties(${TARGETNAME} PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
but no change. I even hardwired
set (CMAKE_BUILD_TYPE Debug)
Breaking things down a bit more; this is the failing command that complains:
/usr/bin/dsymutil /Users/pwessel/GMTdev/gmt-dev/dbuild/src/libpostscriptlight.a
Some progress. Building with Release worked but not RelWithDebInfo. So anything with Debug seems to fail at dsymutil step. However, building purely for Xcode to debug in Xcode worked so I will see if I can solve the problem with the extern array. I suspect if you try to build with gcc then it will also work.
Debug in Xcode shows that the static array _keyshashnode declared and filled in gmt_init.c during gmt_begin is empty when earthtide (a module in the shared dynamic library supplements.so) calls a function in the static library that needs to look at _keyshashnode. The array is correctly filled during gmt_begin but all is lost by the round-trip from calling the shared library function that calls a static function.
I made changes such as removing the static and adding EXTERN_MSC when building statically but no luck. I suspect the static and shared libraries have separate data spaces and their own copies of this variable, and only the static one is updated. But not sure.
I have made a branch static-build-fix for experimenting with this issue.
Maybe gurus like @remkos or @ldldr might now how this should work when we mix libgmt.a with supplemental.so and we actually have some global (now extern) arrays created in libgmt.a but requested by a module in supplemental.so that then calls functions in libgmt.a that need those arrays [they are empty right now].
I suspect we need to add the _keyshashnode structure array to the GMT allocated struct for this to work for both static and shared builds.
Closing this as we wont support static for now.
Hi, we're encountering a similar issue after upgrading to 6.4.0. Now, when we call, for example, gmt select
, we get the same error about the module not being found. We rely on the static build in order to distribute our software with as few system lib dependencies as possible. Has there been any progress on this since this issue was closed? Thanks!
Edit: It appears that the gmt
executable is still attempting to load libgmt.dylib (which doesn't/shouldn't exist):
gmt [DEBUG]: Loading core GMT shared library: libgmt.dylib
gmt [DEBUG]: Shared Library # 0 (core). Path = libgmt.dylib
If I naively assume that creating a static build should really only involve setting certain linker flags or CMAKE settings. If anyone is interesting in pursuing that we would of course be happy to merge in a PR that would do this. But I suspect none of the volunteer developers have any particular interest in static builds. If TidBit is interesting in solving this and make a PR then that would be great since it sounds like you are motivated.
Actually is more complicated than that. The largest number of GMT dependencies comes through GDAL where there have been so questions on static libs and the conclusion is no way, we have a lot of dependencies and woul'd need to all be build statically.
For what it's worth, we do compile and link GDAL statically for our distributables.
I guess that means your GDAL lib has a reduced number of dependencies.
@PaulWessel I would be happy to work on this given time. Just to get the high level conversation started, I suspect you would want a new CMake config variable to control all of this, like, LINK_EXECUTABLES_TO_STATIC_LIBS
?
@joa-quim We are currently compiling version 3.5.3 from source, and also compile zlib, hdf5, and netcdf statically from source. It does work, but it sounds like it is not a common use case. I understand that the modern paradigm is to link against shared libraries and ship those with your distributable, but because we run our software in MATLAB (in particular) we were experiencing a lot of shared library conflicts and it was easier to reduce variables by compiling and linking static external package libraries.
I have to leave now but I'm curious about the netCDF build. I couldn't build it on Windows (have an open issue in the netCDF repo). Well I built it but with lots of trickery involving hacking-and-reusing the vcpkg ninja build file.
And yes, we are very well aware of the Matlab issues in other OS than Windows.
@joa-quim Yes, our Windows build is still under development and has a reduced set of external packages and capabilities. In particular, we have not yet incorporated netCDF into this build (as we only use it as a prerequisite for GDAL). But I feel your pain: we used MSYS2 MinGW to be able to reuse a lot of the existing configuration from our *nix builds and it was not always straightforward.
@PaulWessel So a big hint here is that when I revert to version 6.0.0 in our install script but change nothing else about our configuration, gmtselect
does work. The 6.0.0 docs indicated that the gmt module
syntax was already available at that time, though I believe it was not yet the default to only compile the gmt
executable. Are there changelogs available (I couldn't easily find them on the website)? Between that and parsing repo diffs it might be relatively trivial for myself or someone else to ensure that the gmt executable and others are linked statically to libgmt in more recent versions the way that they were in 6.0.0.
@PaulWessel I would be happy to work on this given time. Just to get the high level conversation started, I suspect you would want a new CMake config variable to control all of this, like,
LINK_EXECUTABLES_TO_STATIC_LIBS
?
Yes, something that would be FALSE by default.
We have GMT_INSTALL_MODULE_LINKS which controls whether we build links called gmtselect, grdimage etc but otherwise we expect people to do thegmt module option
path due to namespace solution issues.
We have GMT_INSTALL_MODULE_LINKS which controls whether we build links called gmtselect, grdimage etc but otherwise we expect people to do the gmt module option path due to namespace solution issues.
Yes, I tried rebuilding with this first, but those links seem to just be sort of aliases (i.e. gmtselect
calls gmt
with arg select
)? Because the base gmt
was still linked against libgmt.dylib (which doesn't exist), this still fails.
OK, expected that but thought I mention it.
But I feel your pain: we used MSYS2 MinGW to be able to reuse a lot of the existing configuration from our *nix builds and it was not always straightforward.
Actually, except now for netCDF (their fault), it's quite some work because I build all dependencies with custom names, and hence escape the Matlab shits that way, but all runs smoothly with VisualStudio. Out GDAL build has:
┌ Info: GDAL 3.7.0dev-2cefafcbad-dirty, released 2023/01/05
│ 210 GDAL drivers found
└ 77 OGR drivers found
I can't build GMT with MinGW due to a strange error at the linking stage when it tries to link with libcurl. Did you manage to build it with MinGW?
Did you manage to build it with MinGW?
No, that's on the back burner for me, but I'll be happy to share with you if/when I do accomplish it.
Tried to have a static build by setting BUILD_SHARED_LIBS to FALSE. The build is succesful, and
gmt
can print the splash screen, butgmt coast
saysNo module named coast was found.