Skip to content

Commit 05da092

Browse files
Deploy dev from 0cd622a
1 parent f279a7c commit 05da092

496 files changed

Lines changed: 4400 additions & 2693 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dev/.buildinfo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Sphinx build info version 1
22
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3-
config: ae553980f48d866fc661601a1468a842
3+
config: 02b8c3d052548af0c8f62ec7983f39dc
44
tags: 645f666f9bcd5a90fca523b33c5a78b7
0 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.

dev/_images/GMT_-B_geo_2.png

285 Bytes
Loading

dev/_images/GMT_App_N_1.png

-1.1 KB
Loading

dev/_images/ex08.png

1.49 KB
Loading

dev/_sources/changes.rst.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
Changelog
77
=========
88

9+
New Features in GMT 6.7
10+
=======================
11+
12+
* Add quadratic (**Q**) and cubic (**B**) Bezier curve commands to the custom symbol
13+
macro language, enabling smooth curves in ``.def`` symbol files. Both commands
14+
extend the path from the previous **M** or **D** point; **Q** takes one control point
15+
plus endpoint, **B** takes two control points plus endpoint. See
16+
:ref:`Custom Symbols <custom-symbols>` for details.
17+
918
New Features in GMT 6.6
1019
=======================
1120

dev/_sources/coast.rst.txt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ specify fill of water-areas then the latter will be transparent (i.e.,
6161
earlier graphics drawn in those areas will not be overwritten).
6262
Likewise, if the water-areas are painted and no land fill is set then
6363
the land-areas will be transparent. A map projection must be supplied.
64-
At least one of options -C, -G, -S, -E, -I, -N, -Q and -W must be specified.
64+
At least one of options |-C|, |-G|, |-S|, |-E|, |-I|, |-N|, |-Q| and |-W|
65+
must be specified.
6566

6667
Required Arguments
6768
------------------
@@ -137,7 +138,7 @@ Optional Arguments
137138
- **+L** to see states/territories for Argentina, Australia, Brazil, Canada, China, India, Norway, Russia and the US.
138139
- **+l**\|\ **+L** to **-E**\ =\ *continent* or **-E**\ *code* to only list countries or states in that continent
139140
or country, respectively; repeat if more than one continent or country is requested.
140-
- **+n** to list the named :ref:`DCW collections dcw-collections>` or regions (**-E**\ *code*\ **+n** will list
141+
- **+n** to list the named :ref:`DCW collections <dcw-collections>` or regions (**-E**\ *code*\ **+n** will list
141142
collections that contains the listed codes). All names are case-insensitive.
142143
- **+c** to set up an inside clip path based on your selection.
143144
- **+C** to set up an outside (area between selection and map boundary) clip path based on your selection.
@@ -175,7 +176,7 @@ Optional Arguments
175176

176177
.. _-G:
177178

178-
**-G**\ [*fill*] :ref:`(more ...) -Gfill_attrib>`
179+
**-G**\ [*fill*] :ref:`(more ...) <-Gfill_attrib>`
179180
Select filling or clipping of "dry" areas. Append the shade, color,
180181
or pattern; or give no argument for clipping [Default is no fill].
181182

@@ -252,7 +253,7 @@ Optional Arguments
252253

253254
.. _-S:
254255

255-
**-S**\ [*fill*] :ref:`(more ...) -Gfill_attrib>`
256+
**-S**\ [*fill*] :ref:`(more ...) <-Gfill_attrib>`
256257
Select filling or clipping of "wet" areas. Append the shade, color,
257258
or pattern; or give no argument for clipping [Default is no fill].
258259

@@ -272,7 +273,7 @@ Optional Arguments
272273

273274
.. _-W:
274275

275-
**-W**\ [[*level*/]\ *pen*] :ref:`(more ...) set-pens>`
276+
**-W**\ [[*level*/]\ *pen*] :ref:`(more ...) <set-pens>`
276277
Draw shorelines [Default is no shorelines]. Append pen attributes
277278
[Defaults: width = 0.25p, color = black, style = solid] which
278279
apply to all four levels. To set the pen for each level differently,
@@ -295,9 +296,9 @@ Optional Arguments
295296
.. _-g:
296297

297298
**-gD**\ *dist*
298-
Short version of the global **-g** option. Here it is used to set the _dist_ distance, in map units,
299-
higher then which we consider to have a gap. Useful for the Spilhaus projection (though we automatically set it)
300-
and when line wrapping on dateline was not correctly detected. As an example of this, see for instance
299+
Short version of the global **-g** option. Here it is used to set the *dist* distance, in map units,
300+
higher than which we consider to have a gap. Useful for the Spilhaus projection (though we automatically set it)
301+
and when line wrapping on dateline was not correctly detected. As an example of this, see for instance
301302
the old issue `#3667 <https://github.com/GenericMappingTools/gmt/issues/3667>`_ that can be fixed
302303
by adding **-gD**\ 1 to the command line.
303304

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
:orphan:
2+
3+
Custom GMT Supplements --- In-Tree vs Out-of-Tree
4+
=================================================
5+
6+
.. note::
7+
8+
The investigation underlying this document and the document itself
9+
(including the accompanying template files under
10+
:file:`src/custom_supp_templates/`) were produced by Claude Opus 4.7
11+
(Anthropic), working from the GMT source tree and a real-world
12+
out-of-tree supplement port (MB-System's ``mbsystem.dll``). Treat
13+
the contents as a starting point that has been mechanically verified
14+
against the GMT source as of the date of writing but has not been
15+
human-reviewed for stylistic or policy fit with the GMT project.
16+
Corrections welcome.
17+
18+
This document describes the two ways to build a GMT supplemental shared
19+
library ("supplement" or "suppl"): the **in-tree** path (your supplement
20+
lives under :file:`gmt/src/<name>/` and is built when GMT itself is
21+
built) and the **out-of-tree** path (your supplement is built by an
22+
independent CMake project that links against an already-installed GMT).
23+
Both produce a DLL or shared module that exposes GMT modules via
24+
``gmt --show-modules``, ``gmt --help``, and the external-API key/group
25+
lookup used by Julia, Python, and MATLAB wrappers.
26+
27+
The accompanying :file:`src/custom_supp_templates/in-tree-template/`
28+
and :file:`src/custom_supp_templates/out-of-tree-template/` directories
29+
contain copy-and-modify starter trees for each case.
30+
31+
How a GMT supplement actually works
32+
-----------------------------------
33+
34+
A GMT supplement is just a shared library that the GMT core loads at
35+
runtime through ``dlopen`` / ``LoadLibrary``. GMT discovers libraries
36+
from the ``GMT_CUSTOM_LIBS`` GMT default (or the built-in supplement
37+
path). For each loaded library, GMT looks up symbols **by name**, using
38+
the library **basename** as a prefix. For a supplement DLL named
39+
``mylib``, GMT resolves these five symbols with ``dlsym``:
40+
41+
.. list-table::
42+
:widths: 35 65
43+
:header-rows: 1
44+
45+
* - Symbol
46+
- Purpose
47+
* - ``mylib_module_show_all``
48+
- Pretty-print all modules + purpose for ``gmt --help``
49+
* - ``mylib_module_list_all``
50+
- Plain list of modern module names for ``gmt --show-modules``
51+
* - ``mylib_module_classic_all``
52+
- Plain list of classic module names for ``gmt --show-classic``
53+
* - ``mylib_module_keys``
54+
- Return ``THIS_MODULE_KEYS`` string for an external-API consumer
55+
* - ``mylib_module_group``
56+
- Return ``THIS_MODULE_LIB`` string for an external-API consumer
57+
58+
Per individual module ``xxx``, GMT also looks up the actual entry point
59+
``GMT_xxx`` (for example ``GMT_grdbarb``, ``GMT_psbarb``). That function
60+
must be exported from the DLL
61+
(``EXTERN_MSC int GMT_xxx(void *API, int mode, void *args);``).
62+
63+
The five ``_module_*`` lookup functions all share a per-supplement
64+
table called ``static struct GMT_MODULEINFO modules[]``, populated with
65+
one row per module:
66+
67+
.. code-block:: c
68+
69+
struct GMT_MODULEINFO {
70+
const char *mname; /* THIS_MODULE_MODERN_NAME */
71+
const char *cname; /* THIS_MODULE_CLASSIC_NAME */
72+
const char *component; /* THIS_MODULE_LIB */
73+
const char *purpose; /* THIS_MODULE_PURPOSE */
74+
const char *keys; /* THIS_MODULE_KEYS */
75+
};
76+
77+
The table is the heart of a supplement. Everything else is plumbing
78+
around it. The lookup-function bodies are nearly identical across all
79+
supplements; they just delegate to ``GMT_Show_ModuleInfo`` /
80+
``GMT_Get_ModuleInfo`` from GMT's public API.
81+
82+
Because the body is boilerplate and the table content is derived
83+
mechanically from ``#define THIS_MODULE_*`` macros in each module's
84+
``.c``, GMT auto-generates both during the build. That generation is
85+
what the in-tree mechanism gives you for free --- and what the
86+
out-of-tree case must reproduce by hand.
87+
88+
The in-tree mechanism
89+
---------------------
90+
91+
Look at :file:`src/windbarbs/` for the canonical, minimal example: two
92+
module sources (``grdbarb.c``, ``psbarb.c``) plus one shared helper
93+
(``windbarb.c``) and a fourteen-line :file:`CMakeLists.txt`. That
94+
``CMakeLists.txt`` declares only the sources --- no ``add_library``, no
95+
glue file, no ``gen_*`` command:
96+
97+
.. code-block:: cmake
98+
99+
set (SUPPL_NAME windbarbs)
100+
set (SUPPL_PROGS_SRCS grdbarb.c psbarb.c)
101+
set (SUPPL_LIB_SRCS ${SUPPL_PROGS_SRCS} windbarb.c)
102+
set (SUPPL_EXAMPLE_FILES README.windbarb)
103+
104+
:file:`src/CMakeLists.txt` does the rest. The loop in that file walks
105+
every supplement directory listed in ``GMT_SUPPL_DIRS`` (which by
106+
default includes ``geodesy gsfml gshhg img mgd77 potential segy seis
107+
spotter x2sys windbarbs`` plus anything the user puts in
108+
``SUPPL_EXTRA_DIRS``) and for each one:
109+
110+
1. Calls ``add_subdirectory(<dir>)`` so the supplement's
111+
:file:`CMakeLists.txt` sets ``SUPPL_NAME``, ``SUPPL_PROGS_SRCS``,
112+
``SUPPL_LIB_SRCS``, optionally ``SUPPL_LIB_NAME``,
113+
``SUPPL_EXTRA_LIBS``, ``SUPPL_EXTRA_INCLUDES``, ``SUPPL_DLL_RENAME``.
114+
2. Reads those variables back via ``get_subdir_var``.
115+
3. Accumulates per-library source lists into
116+
``SUPPL_<lib>_PROGS_SRCS`` and ``SUPPL_<lib>_LIB_SRCS``. (Multiple
117+
supplement directories can contribute to one library by sharing
118+
``SUPPL_LIB_NAME``.)
119+
4. For each resulting library:
120+
121+
- Runs ``gen_gmt_moduleinfo_h`` from
122+
:file:`cmake/modules/GmtGenExtraHeaders.cmake`. The macro greps
123+
every module source for ``THIS_MODULE_MODERN_NAME``,
124+
``THIS_MODULE_CLASSIC_NAME``, ``THIS_MODULE_LIB``,
125+
``THIS_MODULE_PURPOSE``, ``THIS_MODULE_KEYS`` and writes
126+
:file:`gmt_<lib>_moduleinfo.h` (one row per module).
127+
- Runs ``configure_file(gmt_glue.c.in gmt_<lib>_glue.c)`` substituting
128+
``@SHARED_LIB_NAME@`` and ``@SHARED_LIB_PURPOSE@``. The generated
129+
``.c`` ``#include`` s the generated ``.h`` to fill in ``modules[]``
130+
and defines the five ``<lib>_module_*`` entry points as
131+
``EXTERN_MSC``.
132+
- Builds the shared library / module from the union of accumulated
133+
module sources, library sources, generated glue, and generated
134+
header.
135+
136+
5. Installs the library into :file:`gmt/plugins/`.
137+
138+
That is the entire mechanism. The supplement author writes only the
139+
module sources (with the right ``THIS_MODULE_*`` macros at the top)
140+
plus a fourteen-line :file:`CMakeLists.txt`; everything that exposes
141+
the modules to the runtime is generated.
142+
143+
Adding a custom in-tree supplement
144+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145+
146+
1. Create :file:`gmt/src/<myname>/` containing your ``.c`` sources
147+
plus a :file:`CMakeLists.txt` shaped like
148+
:file:`src/windbarbs/CMakeLists.txt`. See the
149+
:file:`src/custom_supp_templates/in-tree-template/` directory.
150+
2. Edit (or create) :file:`cmake/ConfigUserAdvanced.cmake` and set
151+
``set (SUPPL_EXTRA_DIRS <myname>)``. (Multiple custom supplement
152+
directories can be listed.)
153+
3. Configure and build GMT normally. Your DLL appears under
154+
:file:`gmt/plugins/` alongside the official supplements.
155+
4. Verify with ``gmt --show-modules`` (your module names should appear)
156+
and ``gmt <yourmodule>``.
157+
158+
The five-symbol contract and the ``THIS_MODULE_*`` macro requirement
159+
described above are non-negotiable in either path. The in-tree
160+
mechanism just satisfies them automatically.
161+
162+
The out-of-tree mechanism
163+
-------------------------
164+
165+
A custom supplement built **outside** the GMT source tree (as part of
166+
an independent project --- for example MB-System builds ``mbsystem.dll``
167+
from its own CMake project that links against an installed GMT) does
168+
**not** get the auto-generated glue and moduleinfo header. The
169+
supplement author has to either:
170+
171+
(a) Reproduce the generation in the host project's CMake, or
172+
(b) Hand-author :file:`gmt_<lib>_glue.c` and
173+
:file:`gmt_<lib>_moduleinfo.h` and treat them as ordinary source
174+
files.
175+
176+
Option (a) is strongly recommended --- the moduleinfo header should
177+
track the module sources automatically, and hand-editing it is
178+
error-prone. The :file:`src/custom_supp_templates/out-of-tree-template/`
179+
directory shows option (a) end-to-end.
180+
181+
What out-of-tree projects must provide
182+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183+
184+
1. **Their own copy of** :file:`gmt_glue.c.in`. GMT does not install
185+
:file:`gmt_glue.c.in` to a public location (it lives in the source
186+
tree only). Vendor a copy into your project; you only need to
187+
change ``@SHARED_LIB_NAME@`` and ``@SHARED_LIB_PURPOSE@``.
188+
189+
2. **Their own moduleinfo generator.** GMT's
190+
:file:`cmake/modules/GmtGenExtraHeaders.cmake` is similarly
191+
source-tree-only and the ``gen_gmt_moduleinfo_h`` macro is tightly
192+
coupled to GMT's own directory layout (it reads from
193+
``${GMT_SRC}/src/${prog}``). Vendor a standalone CMake ``-P``
194+
script that does the same regex extraction over your project's
195+
module sources. See
196+
:file:`src/custom_supp_templates/out-of-tree-template/cmake/GenSupplModuleInfo.cmake`.
197+
198+
3. **A CMakeLists.txt that wires up the generator → glue → library.**
199+
See
200+
:file:`src/custom_supp_templates/out-of-tree-template/CMakeLists.txt`.
201+
202+
4. **The right library output name.** GMT calls ``dlsym`` using the
203+
**DLL basename**, so the CMake target's ``OUTPUT_NAME`` (and any
204+
``*_DLL_RENAME``) must match the ``SHARED_LIB_NAME`` you bake into
205+
the glue. If the DLL is :file:`mylib.dll`, the glue must export
206+
``mylib_module_list_all`` etc. --- mismatch means GMT silently
207+
finds nothing.
208+
209+
5. **DLL export visibility.** On Windows the entry points need
210+
``__declspec(dllexport)``. The vendored :file:`gmt_glue.c.in` uses
211+
``EXTERN_MSC``, which GMT's :file:`declspec.h` flips to
212+
``dllexport`` when ``LIBRARY_EXPORTS`` is defined. Add
213+
214+
.. code-block:: cmake
215+
216+
target_compile_definitions(<target> PRIVATE LIBRARY_EXPORTS)
217+
218+
to your CMakeLists. Each module's ``GMT_<modulename>`` entry point
219+
should also be declared ``EXTERN_MSC`` (or you can rely on CMake's
220+
``CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS``, but the explicit attribute is
221+
cleaner and matches what in-tree supplements do).
222+
223+
Real-world worked example
224+
~~~~~~~~~~~~~~~~~~~~~~~~~
225+
226+
MB-System builds ``mbsystem.dll`` out-of-tree against an installed GMT.
227+
Its :file:`src/gmt/CMakeLists.txt` followed the recipe above (using a
228+
vendored ``MbsysGenModuleInfo.cmake`` and ``gmt_mbsystem_glue.c.in``)
229+
after diagnosing that an earlier hand-written ``mbgmt_module.c``
230+
exported the wrong symbol names (``gmt_mbgmt_module_show_all`` instead
231+
of ``mbsystem_module_list_all``), which is why ``gmt --show-modules``
232+
showed nothing and Julia's ``GMT_Encode_Options`` returned null keys.
233+
234+
The MB-System fix is a close analogue of the
235+
:file:`src/custom_supp_templates/out-of-tree-template/` provided here;
236+
consult that project as a secondary reference if you want to see the
237+
mechanism integrated into a larger codebase.
238+
239+
Module source requirements (both paths)
240+
---------------------------------------
241+
242+
Every module ``.c`` must define these macros near the top, before any
243+
``#include "gmt_dev.h"``:
244+
245+
.. code-block:: c
246+
247+
#define THIS_MODULE_CLASSIC_NAME "mymodule" /* required */
248+
#define THIS_MODULE_MODERN_NAME "mymodule" /* required */
249+
#define THIS_MODULE_LIB "mylib" /* must equal DLL basename */
250+
#define THIS_MODULE_PURPOSE "One-line description"
251+
#define THIS_MODULE_KEYS "<G{,>X}" /* API key string; "" if none */
252+
#define THIS_MODULE_NEEDS "Jg" /* projection requirements; "" if none */
253+
#define THIS_MODULE_OPTIONS "->BJKOPRUVXY" /* common options accepted */
254+
255+
The legacy ``THIS_MODULE_NAME`` (a single string used by very old GMT5
256+
ports) is **not** recognised by the modern generator. If you are
257+
porting old code, add explicit ``THIS_MODULE_MODERN_NAME`` and
258+
``THIS_MODULE_CLASSIC_NAME`` (typically both equal to the old name) or
259+
adapt your generator to fall back. The vendored
260+
:file:`src/custom_supp_templates/out-of-tree-template/cmake/GenSupplModuleInfo.cmake`
261+
does the fallback for convenience; the in-tree GMT generator does not.
262+
263+
Each module must also expose:
264+
265+
.. code-block:: c
266+
267+
EXTERN_MSC int GMT_mymodule(void *V_API, int mode, void *args);
268+
269+
as a defined function (not just a declaration). That is what GMT
270+
dispatches to when the user runs ``gmt mymodule``.
271+
272+
Loading a custom supplement at runtime
273+
--------------------------------------
274+
275+
After building and installing, point GMT at the new library. Either:
276+
277+
- Set the GMT default ``GMT_CUSTOM_LIBS`` to the absolute path of the
278+
DLL (or to a colon/semicolon separated list of paths), for example
279+
``gmt set GMT_CUSTOM_LIBS C:/path/to/mylib.dll``.
280+
- Or drop the DLL into GMT's default plugin directory
281+
(:file:`<gmt-install>/lib/gmt/plugins/` on Unix,
282+
:file:`<gmt-install>/bin/gmt_plugins/` on Windows).
283+
284+
Verify:
285+
286+
.. code-block:: sh
287+
288+
gmt --show-modules # your modules should appear in the list
289+
gmt mymodule --help # your module should run
290+
291+
If ``gmt --show-modules`` does not list your modules but the DLL
292+
clearly loaded (no error printed), the most likely cause is a mismatch
293+
between the DLL basename and the ``SHARED_LIB_NAME`` baked into the
294+
glue. Inspect the DLL with ``dumpbin /exports mylib.dll`` (MSVC) or
295+
``nm -D mylib.so`` (Unix) and confirm that ``mylib_module_list_all``
296+
and friends are present.
297+
298+
File overview in :file:`src/custom_supp_templates/`
299+
---------------------------------------------------
300+
301+
.. code-block:: text
302+
303+
src/custom_supp_templates/
304+
├── README.md this document (markdown copy)
305+
├── in-tree-template/
306+
│ ├── CMakeLists.txt drop-in for src/<myname>/
307+
│ └── mymodule.c skeleton module source
308+
└── out-of-tree-template/
309+
├── CMakeLists.txt standalone CMake project
310+
├── gmt_mylib_glue.c.in vendored from gmt_glue.c.in
311+
├── mymodule.c skeleton module source
312+
└── cmake/
313+
└── GenSupplModuleInfo.cmake vendored moduleinfo generator

0 commit comments

Comments
 (0)