Building GMT on FreeBSD 12.1-RELEASE

Hi all.

I’m trying to compile GMT on FreeBSD 12.1-RELEASE amd64 but running into an issue.

I have installed the requirements given in https://github.com/GenericMappingTools/gmt/wiki/Install-dependencies-on-FreeBSD. (By the way, I changed the ghostscript package from print/ghostscript9 to print/ghostscript9-base as the former got no hits in the package repo.)

During cmake --build . I get an error:

[... everything OK up until this point ...]
Scanning dependencies of target gmt
[100%] Building C object src/CMakeFiles/gmt.dir/gmt.c.o
[100%] Linking C executable gmt
ld: error: libgmt.so.6.2.0: undefined reference to backtrace
ld: error: libgmt.so.6.2.0: undefined reference to backtrace_symbols_fd
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1

Stop.
make[2]: stopped in /usr/home/anbj/gmt/build
*** Error code 1

Stop.
make[1]: stopped in /usr/home/anbj/gmt/build
*** Error code 1

Stop.
make: stopped in /usr/home/anbj/gmt/build

Any good ideas on what might be wrong?

See src/gmt_common_sighandler.c and the long list of #ifdefs for various operating systems. While FreeBSD is listed I suspect things have changed. This stuff is extremely OS-specific, so if you can figure out what is needed we can update the source. Alternatively, add -DNO_SIGHANDLER to your flags and it will bypass the signal handling.

Thanks Paul.

I added -DNO_SIGHANDLER to my cmake command, but got:

$ cmake ~/gmt -DNO_SIGHANDLER -DCOPY_GSHHG=TRUE -DCOPY_DCW=TRUE -DGSHHG_ROOT=~/Downloads/gshhg -DDCW_ROOT=~/Downloads/dcw -DGMT_OPENMP=ON
CMake Error: Parse error in command line argument: -DNO_SIGHANDLER
Should be: VAR:type=value

CMake Error: Problem processing arguments. Aborting.

So I tried -DNO_SIGHANDLER=TRUE, but then I get:

CMake Warning:
  Manually-specified variables were not used by the project:

    NO_SIGHANDLER

So I never got passed the error.

I’ll try to look more into the problem.

OH, it has to go on the compiler, so I guess in your cmake/COnfigUser.cmake you add

add_definitions(-DNO_SIGHANDLER)

But cant I just define this on the command line? I dont like to fool around with the *.cmake-file. I do:

cmake ~/gmt/gmt -DCOPY_GSHHG=TRUE -DCOPY_DCW=TRUE \
-DGSHHG_ROOT=~/gmt/share/coast \
-DDCW_ROOT=~/gmt/share/dcw -DGMT_OPENMP=ON

Is it not possible to just add the -DNO_SIGHANDLER to this command?

(Apparently not, but I need guidance fed to me with a spoon)

Added add_definitions(-DNO_SIGHANDLER) to ConfigUser.cmake. Bleeding edge GMT up and running!

$ uname -a
FreeBSD  12.1-RELEASE FreeBSD 12.1-RELEASE r354233 GENERIC  amd64

When it comes to the sighandler stuff in https://github.com/GenericMappingTools/gmt/blob/master/src/gmt_common_sighandler.c, I have to admit I’m on deep water. I did a bit of googling and testing, but no bright lights yet.

Made a bug report about this (https://github.com/GenericMappingTools/gmt/issues/4396) so it’s in the system.

On a Raspberry Pi with FreeBSD 12.2-RELEASE (“RPI3”, SD Card Image), I got the following error:

[  3%] Building C object src/CMakeFiles/gmtlib.dir/gmt_common_sighandler.c.o
/home/anbj/gmt/gmt/src/gmt_common_sighandler.c:178:14: error: no member named 'mc_eip' in 'struct __mcontext'
        array [0] = UC_IP (uc); /* caller's address */
                    ^~~~~~~~~~
/home/anbj/gmt/gmt/src/gmt_common_sighandler.c:75:49: note: expanded from macro 'UC_IP'
#  define UC_IP(uc) ((void *) (uc)->uc_mcontext.mc_eip)
                              ~~~~~~~~~~~~~~~~~ ^
1 error generated.
*** Error code 1

Stop.
make[2]: stopped in /home/anbj/gmt/b
*** Error code 1

Stop.
make[1]: stopped in /home/anbj/gmt/b
*** Error code 1

Stop.
make: stopped in /home/anbj/gmt/b

Adding add_definitions(-DNO_SIGHANDLER) to cmake/ConfigUser.cmake as Paul suggested, fixes the problem.

I dont know why this error occurs on the FreeBSD Raspi SD Image, and not on a “normally” installed system. I dont know how the Raspi system differs.

Not necessarily something that should be looked at, but nice to know.

Attached are the cmake logs. NB! Had to rename to .zip or else I was not allowed to upload. They are plain text files.

cmake_build.zip (1.2 KB) cmake_config.zip (13.1 KB)

I came across the same problem and found out that the error is caused by a missing library in the linker flags. I was never able to add the flag to the CMake configuration but ended up compiling the library manually by running “make VERBOSE=1;” to see the full commandline where the error occurs and then running it manually, adding -lexecinfo to the commandline to pull in the library. Once that’s done, compilation continues without problems when you run make again.

A suggestion to the developers who are versed in the black magic of CMake would be to add -lexecinfo to the linker command line on FreeBSD. See this message on the gcc.gnu.org mailing list.

Anders

Anders,

Thank you for sharing this. Great to know.

Best,
Andreas

FYI, the missing library was already added in https://github.com/GenericMappingTools/gmt/pull/4405

Yes, I found that post and added it to the 6.1.1 sources I downloaded as a tar file earlier. It worked very well. Adding this just after line 300 in src/CMakeLists.txt works on 6.1.1 too.

FreeBSD uses a separate library for backtracking

if (${CMAKE_SYSTEM_NAME} STREQUAL “FreeBSD”)
find_library (EXECINFO_LIBRARY NAMES execinfo)
list (APPEND GMT_OPTIONAL_LIBRARIES ${EXECINFO_LIBRARY})
endif (${CMAKE_SYSTEM_NAME} STREQUAL “FreeBSD”)

Cheers,
Anders

@ahogrelius Is this related to the issue I initially described? Or the issue with compiling on the Raspberry Pi?

This is related to the first issue. The second issue on Raspberry Pi is not as easy to solve. If you look up the manpage for ucontext where the struct is described on FreeBSD it will tell you that “The uc_mcontext field is machine-dependent and should be treated as opaque by portable applications.”
If it even is possible, this means that you would have to add FreeBSD ARM specific code to gmt_common_sighandler.c to make it work as the mc_eip member doesn’t exist at all on FreeBSD ARM. Depending on the implementation on GMT it is also possible that you would have to write your own sighandler.

Update:
After studying the problem a bit more I have to report that the only thing you can do is to add the definition NO_SIGHANDLER. The ARM architecture doesn’t allow you to find the address of the calling function unless you have special unwind libraries added to your application and it will add a lot of unnecessary overhead.

Thats interesting. Great research @ahogrelius, thank you for informing.

Andreas

Hi @Andreas @ahogrelius,

I know both of you are FreeBSD users. Do you also use Python, or even PyGMT?

The PyGMT project is planning to provide some basic support for FreeBSD (see the linked issue below), but none of the developers are using FreeBSD. We would appreciate it if you can help us confirm some information about FreeBSD. It would be even better if you can run PyGMT once and let us know it works as expected.

Please see the linked issue below for more details.

@seisman I’m almost exclusive a command line user (bash, that is). But I’m more than happy to help.

Let me know if I should test differently.

 $ python3
Python 3.7.9 (default, Oct  3 2020, 01:29:35)
[Clang 8.0.1 (tags/RELEASE_801/final 366581)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.platform)
freebsd12
>>>

Can’t say for certain, but doing a listing of /usr/lib and usr/local/lib sure indicates that the suffix for shared libraries is .so.

Installed PyGMT via $ pip install pygmt and tried:

 $ python3
Python 3.7.9 (default, Oct  3 2020, 01:29:35)
[Clang 8.0.1 (tags/RELEASE_801/final 366581)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygmt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/__init__.py", line 3                                                                                                         2, in <module>
    _begin()
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/session_management.p                                                                                                         y", line 16, in begin
    with Session() as lib:
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/session.py", li                                                                                                         ne 183, in __enter__
    self.create("pygmt-session")
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/session.py", li                                                                                                         ne 336, in create
    restype=ctp.c_void_p,
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/session.py", li                                                                                                         ne 284, in get_libgmt_func
    self._libgmt = load_libgmt()
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/loading.py", li                                                                                                         ne 35, in load_libgmt
    lib_fullnames = clib_full_names()
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/loading.py", li                                                                                                         ne 99, in clib_full_names
    libnames = clib_names(os_name=sys.platform)  # e.g. libgmt.so, libgmt.dylib,                                                                                                          gmt.dll
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/clib/loading.py", li                                                                                                         ne 77, in clib_names
    raise GMTOSError('Operating system "{}" not supported.'.format(sys.platform)                                                                                                         )
pygmt.exceptions.GMTOSError: Operating system "freebsd12" not supported.
>>>

1 Like

@Andreas Thanks for your information. It’s really helpful. I’ve opened a PR (https://github.com/GenericMappingTools/pygmt/pull/700) for it.
You can install that branch by running:

pip install git+https://github.com/GenericMappingTools/pygmt.git@freebsd

and then you can test it in a Python console:

import pygmt
pygmt.show_versions()

Please let me know if you find any problems.

This is what I get after installing the branch you linked to:

$ python3
Python 3.7.9 (default, Oct  3 2020, 01:29:35)
[Clang 8.0.1 (tags/RELEASE_801/final 366581)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygmt
>>> pygmt.show_versions()
PyGMT information:
  version: v0.2.2.dev7+g07edbd3
System information:
  python: 3.7.9 (default, Oct  3 2020, 01:29:35)  [Clang 8.0.1 (tags/RELEASE_801/final 366581)]
  executable: /usr/local/bin/python3
  machine: FreeBSD-12.2-RELEASE-amd64-64bit-ELF
Dependency information:
  numpy: 1.19.4
  pandas: 1.1.4
  xarray: 0.16.1
  netCDF4: 1.5.4
  packaging: 20.4
  ghostscript: None
  gmt: 6.2.0_3390d08_2020.11.21
GMT library information:
  binary dir:
  cores: 4
  grid layout: rows
  library path: /usr/local/lib/libgmt.so
  padding: 2
  plugin dir: /usr/local/lib/gmt/plugins
  share dir: /usr/local/share
  version: 6.2.0
>>>

I’m able to create the figure as described here https://www.pygmt.org/latest/tutorials/first-figure.html.

Just a note on that; I’m getting an error when doing fig.show():

$ python3
Python 3.7.9 (default, Oct  3 2020, 01:29:35)
[Clang 8.0.1 (tags/RELEASE_801/final 366581)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygmt
>>> fig = pygmt.Figure()
>>> fig.basemap(region=[-90, -70, 0, 20], projection="M8i", frame=True)
>>> fig.coast(shorelines=True)
>>> fig.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/anbj/.local/lib/python3.7/site-packages/pygmt/figure.py", line 289, in show
    "or use 'external=True' to open in an external viewer.",
pygmt.exceptions.GMTError: Cannot find IPython. Make sure you have it installed or use 'external=True' to open in an external viewer.

Apparently missing IPython. Should this be installed as a dependency pr. default?