-
Notifications
You must be signed in to change notification settings - Fork 385
WIP Module developer documentation #3317
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
Open
PaulWessel
wants to merge
23
commits into
master
Choose a base branch
from
module-developer
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
d16f562
Create develop.rst
PaulWessel 2c85c8b
Update develop.rst
PaulWessel cb93733
Update develop.rst
PaulWessel b2cde42
Update doc/rst/source/develop.rst
PaulWessel ebd7ff1
Update doc/rst/source/develop.rst
PaulWessel d379281
Update doc/rst/source/develop.rst
PaulWessel bac45aa
Update doc/rst/source/develop.rst
PaulWessel 436cdbe
Update develop.rst
PaulWessel 89304ec
Add OpenMP comments
PaulWessel dbbbbe3
Update doc/rst/source/develop.rst
PaulWessel 33254fb
Update develop.rst
PaulWessel 09f3801
Hook to sidebar
PaulWessel c5cc380
Update doc/rst/source/develop.rst
PaulWessel 3cc6bab
Merge branch 'master' into module-developer
PaulWessel f75927f
Merge branch 'master' into module-developer
PaulWessel 59b7e5a
Merge branch 'master' into module-developer
PaulWessel 7257eb7
Merge branch 'master' into module-developer
PaulWessel 3f8efcc
Update develop.rst
PaulWessel 4ba098e
Merge branch 'master' into module-developer
PaulWessel 92a8802
Merge branch 'master' into module-developer
PaulWessel 395bc35
Merge branch 'master' into module-developer
PaulWessel a53bc18
Merge branch 'master' into module-developer
PaulWessel 315cf4a
Merge branch 'master' into module-developer
joa-quim File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
.. index:: ! develop | ||
|
||
********************************** | ||
Developing Modules and Supplements | ||
********************************** | ||
|
||
GMT developers do from time to time need to add new modules to the core library, | ||
and occasionally they add an entire new supplement to the official distribution. In | ||
addition, there are unofficial supplements that are not part of the GMT code base | ||
but needs to be built with GMT (or piggyback off the GMT build process), and then | ||
there are supplements that need to be built by themselves that have dependencies | ||
of various kinds on GMT. This document discusses the mechanics around those issues. | ||
|
||
Adding a new module | ||
------------------- | ||
|
||
To add a new module, the starting point is to duplicate the most similar module you can think | ||
of. It is not essential to get this right, but if your new module deals with grids then | ||
start with one of the grd modules such as :doc:`grd2xyz`, and if it needs to deal with tables | ||
then maybe something like :doc:`gmtselect`. If plotting is involved then start with one that | ||
makes plots, and so on. Obviously, there will be lots of changes to your starting point and | ||
those are completely dependent on what the new module will do. Yet, here are some steps | ||
you are likely to encounter and some of them are required exactly as is and for others you | ||
must adapt them to your module's specific purpose. | ||
|
||
#. The first C code lines below the initial comments list a set of seven define statements | ||
that start with **THIS_MODULE_**. Most of them are fairly easy to update, such as stating | ||
the new module's name and purpose. Then there is the **THIS_MODULE_OPTIONS** parameter which | ||
is just a listing of all the common GMT options this module can use. The next item is | ||
**THIS_MODULE_NEEDS** and it tells GMT if this module requires a region (e.g., via **-R**) | ||
and a projection (via **-J**). Modules that must set a region to operate will either have | ||
the codes **R** (must take **-R**), **d** (can determine the region from given data sets), | ||
or **g** (can determine the region from a given grid). There is also the mode **r** which | ||
means 'not normally required' but may be required depending on module options. As an example, | ||
consider :doc:`pslegend` which does not need **-R** if **-Dx** is used but *does* need **-R** if | ||
other selections are made. For the same reason there is the **j** code for projections when | ||
it depends on other options whether **-J** is needed or not. Most plot modules NEEDS will | ||
include **J**. Finally, there is the very cryptic **THIS_MODULE_KEYS** setting. At this point, | ||
please read all the comments in the code for *GMT_Encode_Options* in gmt_api.c. The **KEYS** | ||
are not used by the command line modules and only enters for some external interfaces, such | ||
as MATLAB and Julia. You should have a discussion with those maintainers about what those | ||
**KEYS** should be. | ||
|
||
#. Do some global replacements of strings: Replace the uppercase name of the template module | ||
with the new module uppercase name, and do the same for the lowercase name. This will ensure that | ||
your Ctrl structures and local static functions are named correctly (you may still need to | ||
delete some of them and add others). All functions local to this module shall have names | ||
starting with the module name and an underscores (e.g., *grdinfo_report_tiles*) and they shall | ||
be stated as GMT_LOCAL instead of static (GMT_LOCAL is normally defined to mean static but | ||
in certain debugging cases we may wish to change that). The exceptions to this rule are the | ||
functions *New_Ctrl*, *Free_Ctrl*, *usage*, and *parse*; they are all static and have the | ||
same names in all modules. | ||
|
||
#. After listing all local variables inside the main GMT_module function, all modules start with | ||
a section labeled *Standard module initialization and parsing*. It is extremely unlikely | ||
you will need to make any changes in this section. Ask for help if you think you do. | ||
|
||
#. For style, argument checking, usage layout, use of built-in constants for the synopsis line, | ||
just follow the module template and draw inspiration from other modules. | ||
|
||
#. Make sure you create a separate git branch and add your new code to that branch. New modules | ||
should never go into master and will have to undergo much scrutiny before the branch may | ||
be merged into master. | ||
|
||
#. To let CMake know about the new module, edit src/CMakeLists.txt and search for **GMT_PROGS_SRCS**. | ||
Add your new module to the list. | ||
|
||
#. Try to compile GMT with your new module. We automatically detect all the modules in the *src* | ||
directory (as well as supplemental source directories) and various needed "glue" functions | ||
are automatically created and compiled as part of the process. You are likely to get some | ||
compilation errors. Keep addressing them until the module compiles. Running gmt *modulename* | ||
should print the full usage message. | ||
|
||
#. The documentation of the module should be carefully designed. You will need to add at least a | ||
module.rst file in the doc/rst/source directory that explains what the module does. Again, | ||
start with a copy of another suitable module's RST file and make suitable changes. Make sure | ||
you add some examples that others can try without getting data (e.g., use remote files as much | ||
as possible). | ||
|
||
#. You must also edit the *modules.rst* and *modules-classic.rst* files and add your new module | ||
and its purpose in three separate places. Just search for a known module to see what is expected. | ||
Also change into src directory and run `gmt_make_module_purpose.sh` to update two module purpose files. | ||
With these edits you should be able to build the full documentation and have your module show up under the | ||
Modules page. | ||
|
||
#. Adding a new module to one of the official supplements pretty much follows the same steps. | ||
It is best to start from one of the other modules in that supplement since some of them | ||
have specific include files and setups. Including the new supplemental module in the build | ||
process is automatic (done by CMake). | ||
|
||
Using OpenMP pragmas | ||
-------------------- | ||
|
||
Many algorithms in GMT can be sped up considerably by using OpenMP. This scheme is deceptively | ||
simple and one only needs to add a set of three comments and great speed is attained. This | ||
section discusses our experiences with the "#pragma omp parallel for" statements in GMT. | ||
Here are some simple rules to live by; see actual examples in the modules. | ||
|
||
#. Due to cross-platform compatibility, we must for now always used signed for-loop variables | ||
in places where OpenMP is used. We hope this will go away one day. | ||
#. Every variable addressed by the for-loop must be listed in either the *private* or *shared* | ||
groups in the pragma statement. Be very careful when doing this as pretty much all failures | ||
to get it to work has to do with making mistakes here. This simple rule should help: If a | ||
variable is just *accessed* (read) inside the for-loop then it should go in *shared*, all else must go in | ||
*private*. None can be left out. Often, loops are over grids and the grid pointer is *shared* | ||
so that all threads can add their contributions - this is the whole point of the splitting. | ||
#. Try to avoid having if-tests inside the for-loop. It may be much faster to move the if-test | ||
outside the loop and possibly do a near-duplication of the loop. | ||
#. At this point, the OpenMP builds work well on all platforms, but not well integrated with | ||
the XCode framework on macOS. Building with gcc works well. | ||
|
||
Compiling supplements | ||
--------------------- | ||
|
||
For the purpose of this discussion, we will distinguish between several types of supplements: | ||
|
||
#. Regular supplements included in the GMT distribution (e.g., *seis*, *spotter*). | ||
#. External supplements not part of the GMT distribution but the developer wish to | ||
piggyback off the GMT build process instead of having a full-blown CMakeLists.txt setup. | ||
The modules depend on (and include) gmt_dev.h, just like the core modules. | ||
#. External supplements not part of the GMT distribution but has their own build setup. | ||
The modules depend on (and include) gmt_dev.h, just like the core modules. One such | ||
example are the MB-System src/gmt tools. | ||
#. External supplements not part of the GMT distribution but has their own build setup. | ||
THe modules only depend on (and include) gmt.h, the official GMT API. | ||
|
||
:: | ||
|
||
!! This section will be under construction as long as this sign is present !! | ||
|
||
Regular supplements | ||
=================== | ||
|
||
If you (presumably a developers) is considering to add a new official GMT supplement then | ||
you should completely model it based on one of the existing supplements. You will notice that | ||
your supplement name (the directory) needs to be added to src/CMakeLists.txt. Just search for | ||
an existing name there and it is obvious what to change. Rebuilding everything will automatically | ||
include your new modules. | ||
|
||
Lazy External supplements | ||
========================= | ||
|
||
These are supplements that uses the same layout as the official supplements but of course they | ||
are not blessed by us and thus cannot go into src. The solution is to place the supplemental | ||
directory somewhere else and then set a symbolic link from src to your supplement. These links | ||
must be called *newsuppl1*, *newsuppl2*, etc. Your supplements CMakeLists.txt must set a few | ||
variables to be included by the GMT build process: **SUPPL_LIB_NAME** is the name of your supplement. | ||
If it is set we build a separate shared library for it, but if not set it gets added to the GMT | ||
supplemental shared library. | ||
|
||
External supplements needing gmt_dev.h | ||
====================================== | ||
|
||
These are stand-alone software that can be built as shared libraries we can access from GMT | ||
via the **GMT_CUSTOM_LIBS** default setting. The MB-System is a good example of such a system, | ||
since it requires access to lower-level (developmental) libraries in GMT and thus must include | ||
gmt_dev.h. | ||
|
||
|
||
External supplements only using the API | ||
======================================= | ||
|
||
These are supplements that contains modules that are all build just using the GMT API, i.e., they | ||
only include gmt.h. These typically have their own build system and only link with libgmt. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.