diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c0775e..895eb18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,5 @@ # -# $Id: CMakeLists.txt 11803 2013-06-24 23:06:22Z pwessel $ -# -# Copyright (c) 1991-2017 by P. Wessel, W. H. F. Smith, R. Scharroo, J. Luis, and F. Wobbe +# Copyright (c) 1991-2020 by the GMT Team (https://www.generic-mapping-tools.org/team.html) # See LICENSE.TXT file for copying and redistribution conditions. # # This program is free software; you can redistribute it and/or modify @@ -13,11 +11,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # -# Contact info: gmt.soest.hawaii.edu +# Contact info: www.generic-mapping-tools.org #------------------------------------------------------------------------------- # -# To modify the cmake process: Edit your cmake/ConfigUser.cmake file -# # To build out-of-source do (for example): # # mkdir build @@ -26,14 +22,10 @@ # # CMAKE_BUILD_TYPE can be: empty, Debug, Release, RelWithDebInfo or MinSizeRel # -# cmake creates a new file cmake/ConfigUser.cmake if it does not already -# exist. You can configure additional options there. -# -## Section 0: Define project name. Change this to what your plugin should be named. +## Define project name. Change this to what your plugin should be named. project (custom) -#------------------------------------------------------------------------ # Make sure the user doesn't play dirty with symlinks get_filename_component (srcdir "${CMAKE_SOURCE_DIR}" REALPATH) get_filename_component (bindir "${CMAKE_BINARY_DIR}" REALPATH) @@ -54,16 +46,14 @@ cmake_minimum_required (VERSION 2.8.5) set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/" CACHE INTERNAL "Location of our custom CMake modules." FORCE) -# Include configuration options (default options and options overridden by user). -include (ConfigCMake) - -# Find UNIX commands -include (FindUnixCommands) - # Add subdirectories add_subdirectory (src) -get_property(GMT_CUSTOM_LIB_PATH TARGET customlib PROPERTY LOCATION) -GET_FILENAME_COMPONENT (GMT_CUSTOM_LIB_NAME ${GMT_CUSTOM_LIB_PATH} NAME) + +# Get name of the custom supplemental library +get_directory_property (_suppl_lib_name DIRECTORY "src" DEFINITION "SUPPL_LIB_NAME") +get_target_property (_name ${_suppl_lib_name} OUTPUT_NAME) +get_target_property (_prefix ${_suppl_lib_name} PREFIX) +set (GMT_CUSTOM_LIB_NAME ${_prefix}${_name}${CMAKE_SHARED_MODULE_SUFFIX}) # Configuration done message( @@ -76,5 +66,3 @@ message( "* CUSTOM library : ${GMT_CUSTOM_LIB_NAME}\n" "* Installing CUSTOM in : ${CMAKE_INSTALL_PREFIX}\n" "* CUSTOM_SHARE_PATH : ${CMAKE_INSTALL_PREFIX}/${CUSTOM_SHARE_PATH}") - -# vim: textwidth=78 noexpandtab tabstop=2 softtabstop=2 shiftwidth=2 diff --git a/cmake/modules/FindGMT.cmake b/cmake/modules/FindGMT.cmake new file mode 100644 index 0000000..433ebaa --- /dev/null +++ b/cmake/modules/FindGMT.cmake @@ -0,0 +1,124 @@ +# +# +# Locate GMT +# +# This module accepts the following environment variables: +# +# GMT_DIR or GMT_ROOT - Specify the location of GMT +# +# This module defines the following CMake variables: +# +# GMT_FOUND - True if libgmt is found +# GMT_LIBRARY - A variable pointing to the GMT library +# GMT_INCLUDE_DIR - Where to find the headers +# GMT_INCLUDE_DIRS - Where to find the headers +# GMT_DEFINITIONS - Extra compiler flags + +#============================================================================= +# Inspired by FindGDAL +# +# Distributed under the OSI-approved bsd license (the "License") +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See COPYING-CMAKE-SCRIPTS for more information. +#============================================================================= + +# This makes the presumption that you include gmt.h like +# +#include "gmt.h" + +if (UNIX AND NOT GMT_FOUND) + # Use gmt-config to obtain the libraries + find_program (GMT_CONFIG gmt-config + HINTS + ${GMT_DIR} + ${GMT_ROOT} + $ENV{GMT_DIR} + $ENV{GMT_ROOT} + PATH_SUFFIXES bin + PATHS + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + /usr/local + ) + + if (GMT_CONFIG) + execute_process (COMMAND ${GMT_CONFIG} --cflags + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE GMT_CONFIG_CFLAGS) + if (GMT_CONFIG_CFLAGS) + string (REGEX MATCHALL "(^| )-I[^ ]+" _gmt_dashI ${GMT_CONFIG_CFLAGS}) + string (REGEX REPLACE "(^| )-I" "" _gmt_includepath "${_gmt_dashI}") + string (REGEX REPLACE "(^| )-I[^ ]+" "" _gmt_cflags_other ${GMT_CONFIG_CFLAGS}) + endif (GMT_CONFIG_CFLAGS) + execute_process (COMMAND ${GMT_CONFIG} --libs + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE GMT_CONFIG_LIBS) + if (GMT_CONFIG_LIBS) + # Ensure -l is precedeced by whitespace to not match + # '-l' in '-L/usr/lib/x86_64-linux-gnu/hdf5/serial' + string (REGEX MATCHALL "(^| )-l[^ ]+" _gmt_dashl ${GMT_CONFIG_LIBS}) + string (REGEX REPLACE "(^| )-l" "" _gmt_lib "${_gmt_dashl}") + string (REGEX MATCHALL "(^| )-L[^ ]+" _gmt_dashL ${GMT_CONFIG_LIBS}) + string (REGEX REPLACE "(^| )-L" "" _gmt_libpath "${_gmt_dashL}") + endif (GMT_CONFIG_LIBS) + endif (GMT_CONFIG) + if (_gmt_lib) + list (REMOVE_DUPLICATES _gmt_lib) + list (REMOVE_ITEM _gmt_lib gmt) + endif (_gmt_lib) +endif (UNIX AND NOT GMT_FOUND) + +find_path (GMT_INCLUDE_DIR gmt.h + HINTS + ${_gmt_includepath} + ${GMT_DIR} + ${GMT_ROOT} + $ENV{GMT_DIR} + $ENV{GMT_ROOT} + PATH_SUFFIXES + include/gmt + include + PATHS + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + /usr/local +) + +find_library (GMT_LIBRARY + NAMES gmt + HINTS + ${_gmt_libpath} + ${GMT_DIR} + ${GMT_ROOT} + $ENV{GMT_DIR} + $ENV{GMT_ROOT} + PATH_SUFFIXES lib + PATHS + /sw + /opt/local + /opt/csw + /opt + /usr/local +) + +# find all libs that gmt-config reports +foreach (_extralib ${_gmt_lib}) + find_library (_found_lib_${_extralib} + NAMES ${_extralib} + PATHS ${_gmt_libpath}) + list (APPEND GMT_LIBRARY ${_found_lib_${_extralib}}) +endforeach (_extralib) + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (GMT + DEFAULT_MSG GMT_LIBRARY GMT_INCLUDE_DIR) + +set (GMT_LIBRARIES ${GMT_LIBRARY}) +set (GMT_INCLUDE_DIRS ${GMT_INCLUDE_DIR}) +string (REPLACE "-DNDEBUG" "" GMT_DEFINITIONS "${_gmt_cflags_other}") diff --git a/cmake/modules/FindNETCDF.cmake b/cmake/modules/FindNETCDF.cmake new file mode 100644 index 0000000..c0183dd --- /dev/null +++ b/cmake/modules/FindNETCDF.cmake @@ -0,0 +1,141 @@ +# +# +# Locate netcdf +# +# This module accepts the following environment variables: +# +# NETCDF_DIR or NETCDF_ROOT - Specify the location of NetCDF +# +# This module defines the following CMake variables: +# +# NETCDF_FOUND - True if libnetcdf is found +# NETCDF_LIBRARY - A variable pointing to the NetCDF library +# NETCDF_INCLUDE_DIR - Where to find the headers +# NETCDF_INCLUDE_DIRS - Where to find the headers +# NETCDF_DEFINITIONS - Extra compiler flags + +#============================================================================= +# Inspired by FindGDAL +# +# Distributed under the OSI-approved bsd license (the "License") +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See COPYING-CMAKE-SCRIPTS for more information. +#============================================================================= + +# This makes the presumption that you are include netcdf.h like +# +#include "netcdf.h" + +if (UNIX AND NOT NETCDF_FOUND) + # Use nc-config to obtain the libraries + find_program (NETCDF_CONFIG nc-config + HINTS + ${NETCDF_DIR} + ${NETCDF_ROOT} + $ENV{NETCDF_DIR} + $ENV{NETCDF_ROOT} + PATH_SUFFIXES bin + PATHS + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + /usr/local + ) + + if (NETCDF_CONFIG) + execute_process (COMMAND ${NETCDF_CONFIG} --cflags + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE NETCDF_CONFIG_CFLAGS) + if (NETCDF_CONFIG_CFLAGS) + string (REGEX MATCHALL "(^| )-I[^ ]+" _netcdf_dashI ${NETCDF_CONFIG_CFLAGS}) + string (REGEX REPLACE "(^| )-I" "" _netcdf_includepath "${_netcdf_dashI}") + string (REGEX REPLACE "(^| )-I[^ ]+" "" _netcdf_cflags_other ${NETCDF_CONFIG_CFLAGS}) + endif (NETCDF_CONFIG_CFLAGS) + execute_process (COMMAND ${NETCDF_CONFIG} --libs + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE NETCDF_CONFIG_LIBS) + if (NETCDF_CONFIG_LIBS) + # Ensure -l is precedeced by whitespace to not match + # '-l' in '-L/usr/lib/x86_64-linux-gnu/hdf5/serial' + string (REGEX MATCHALL "(^| )-l[^ ]+" _netcdf_dashl ${NETCDF_CONFIG_LIBS}) + string (REGEX REPLACE "(^| )-l" "" _netcdf_lib "${_netcdf_dashl}") + string (REGEX MATCHALL "(^| )-L[^ ]+" _netcdf_dashL ${NETCDF_CONFIG_LIBS}) + string (REGEX REPLACE "(^| )-L" "" _netcdf_libpath "${_netcdf_dashL}") + endif (NETCDF_CONFIG_LIBS) + endif (NETCDF_CONFIG) + if (_netcdf_lib) + list (REMOVE_DUPLICATES _netcdf_lib) + list (REMOVE_ITEM _netcdf_lib netcdf) + endif (_netcdf_lib) +endif (UNIX AND NOT NETCDF_FOUND) + +find_path (NETCDF_INCLUDE_DIR netcdf.h + HINTS + ${_netcdf_includepath} + ${NETCDF_DIR} + ${NETCDF_ROOT} + $ENV{NETCDF_DIR} + $ENV{NETCDF_ROOT} + PATH_SUFFIXES + include/netcdf + include/netcdf-4 + include/netcdf-3 + include + PATHS + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + /usr/local +) + +find_library (NETCDF_LIBRARY + NAMES netcdf + HINTS + ${_netcdf_libpath} + ${NETCDF_DIR} + ${NETCDF_ROOT} + $ENV{NETCDF_DIR} + $ENV{NETCDF_ROOT} + PATH_SUFFIXES lib + PATHS + /sw + /opt/local + /opt/csw + /opt + /usr/local +) + +# find all libs that nc-config reports +foreach (_extralib ${_netcdf_lib}) + find_library (_found_lib_${_extralib} + NAMES ${_extralib} + PATHS ${_netcdf_libpath}) + list (APPEND NETCDF_LIBRARY ${_found_lib_${_extralib}}) +endforeach (_extralib) + +if (NETCDF_LIBRARY AND NETCDF_INCLUDE_DIR AND NOT HAVE_NETCDF4) + # Ensure that NetCDF with version 4 extensions is installed + include (CMakePushCheckState) + include (CheckSymbolExists) + cmake_push_check_state() # save state of CMAKE_REQUIRED_* + set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${NETCDF_INCLUDE_DIR}) + set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${NETCDF_LIBRARY}) + set (HAVE_NETCDF4 HAVE_NETCDF4) # to force check_symbol_exists again + check_symbol_exists (nc_def_var_deflate netcdf.h HAVE_NETCDF4) + cmake_pop_check_state() # restore state of CMAKE_REQUIRED_* + if (NOT HAVE_NETCDF4) + message (SEND_ERROR "Library found but netCDF-4/HDF5 format unsupported. Do not configure netCDF-4 with --disable-netcdf-4.") + endif (NOT HAVE_NETCDF4) +endif (NETCDF_LIBRARY AND NETCDF_INCLUDE_DIR AND NOT HAVE_NETCDF4) + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (NETCDF + DEFAULT_MSG NETCDF_LIBRARY NETCDF_INCLUDE_DIR HAVE_NETCDF4) + +set (NETCDF_LIBRARIES ${NETCDF_LIBRARY}) +set (NETCDF_INCLUDE_DIRS ${NETCDF_INCLUDE_DIR}) +string (REPLACE "-DNDEBUG" "" NETCDF_DEFINITIONS "${_netcdf_cflags_other}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8447602..72cec1d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,4 @@ # -# $Id: CMakeLists.txt 11838 2013-06-28 06:49:32Z pwessel $ -# # Copyright (c) 1991-2020 by GMT Team (https://www.generic-mapping-tools.org/team.html) # See LICENSE.TXT file for copying and redistribution conditions. # @@ -48,3 +46,29 @@ set (SUPPL_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/custom_config.h) set (CUSTOM_PACKAGE_VERSION "6.1.0") configure_file (custom_config.h.in custom_config.h) + +find_package (GMT REQUIRED) +include_directories (${GMT_INCLUDE_DIR}) + +find_package (NETCDF REQUIRED) +include_directories (${NETCDF_INCLUDE_DIR}) + +add_library (${SUPPL_LIB_NAME} MODULE + ${SUPPL_LIB_SRCS} + ${CMAKE_CURRENT_BINARY_DIR}/custom_config.h + gmt_custom_glue.c + ) + +target_link_libraries (${SUPPL_LIB_NAME} + ${GMT_LIBRARIES} + ${NETCDF_LIBRARIES} +) + +set_target_properties (${SUPPL_LIB_NAME} + PROPERTIES + OUTPUT_NAME ${SUPPL_LIB_NAME} + RUNTIME_OUTPUT_NAME ${SUPPL_LIB_NAME} + LIBRARY_OUTPUT_DIRECTORY plugins + RUNTIME_OUTPUT_DIRECTORY plugins + PREFIX "" + DEFINE_SYMBOL "LIBRARY_EXPORTS") diff --git a/src/gmt_custom_glue.c b/src/gmt_custom_glue.c new file mode 100644 index 0000000..2f76947 --- /dev/null +++ b/src/gmt_custom_glue.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012-2020 by the GMT Team (https://www.generic-mapping-tools.org/team.html) + * See LICENSE.TXT file for copying and redistribution conditions. + */ +/* gmt_custom_glue.c populates the external array of this shared lib with + * module parameters such as name, group, purpose and keys strings. + * This file also contains the following convenience functions to + * display all module purposes, list their names, or return keys or group: + * + * int custom_module_show_all (void *API); + * int custom_module_list_all (void *API); + * int custom_module_classic_all (void *API); + * + * These functions may be called by gmt --help and gmt --show-modules + * + * Developers of external APIs for accessing GMT modules will use this + * function indirectly via GMT_Encode_Options to retrieve option keys + * needed for module arg processing: + * + * const char * custom_module_keys (void *API, char *candidate); + * const char * custom_module_group (void *API, char *candidate); + * + * All functions are exported by the shared custom library so that gmt can call these + * functions by name to learn about the contents of the library. + */ + +#include "gmt_dev.h" + +/* Sorted array with information for all GMT custom modules */ +static struct GMT_MODULEINFO modules[] = { + {"gmtaverage", "gmtaverage", "custom", "Block average (x,y,z) data tables by mean, median, or mode estimation", "DO,RG-"}, + {"gmtmercmap", "gmtmercmap", "custom", "Make a Mercator color map from ETOPO 1, 2, or 5 arc min global relief grids", "CCi,>XO,RG-"}, + {"gmtparser", "gmtparser", "custom", "Demonstrate parsing of input data, defaults, and options", ""}, + {"grdfourier", "grdfourier", "custom", "Create a grid, add a spike, filter it in frequency domain, and write output", "RVabdefghior" "H" /* The H is for possible compatibility with GMT4 syntax */ -#include "custom_version.h" /* Must include this to use Custom_version */ - struct GMTAVERAGE_CTRL { /* All local control options for this program (except common args) */ struct E { /* -E[b] */ unsigned int active; diff --git a/src/gmtmercmap.c b/src/gmtmercmap.c index 13b4138..849a4c6 100644 --- a/src/gmtmercmap.c +++ b/src/gmtmercmap.c @@ -35,8 +35,6 @@ #define THIS_MODULE_NEEDS "JR" #define THIS_MODULE_OPTIONS "->BKOPRUVXYcnptxy" -#include "custom_version.h" /* Must include this to use Custom_version */ - #define MAP_BAR_GAP "36p" /* Offset color bar 36 points below map */ #define MAP_BAR_HEIGHT "8p" /* Height of color bar, if used */ #define MAP_OFFSET "100p" /* Start map 100p from paper edge when colorbar is requested */ @@ -157,7 +155,7 @@ static int parse (void *API, struct GMTMERCMAP_CTRL *Ctrl, struct GMT_OPTION *op break; case 'W': /* Map width */ Ctrl->W.active = 1; - GMT_Get_Value (API, opt->arg, &Ctrl->W.width); + GMT_Get_Values (API, opt->arg, &Ctrl->W.width, 1); break; case 'S': /* Draw scale beneath map */ Ctrl->S.active = 1; @@ -213,8 +211,8 @@ EXTERN_MSC int GMT_gmtmercmap (void *API, int mode, void *args) { double area, z, z_min, z_max, wesn[4]; - char file[256], z_file[GMT_STR16], i_file[GMT_STR16]; - char cmd[BUFSIZ], c_file[GMT_STR16], t_file[GMT_STR16], def_unit[16]; + char file[256], z_file[GMT_VF_LEN], i_file[GMT_VF_LEN]; + char cmd[BUFSIZ], c_file[GMT_VF_LEN], t_file[GMT_VF_LEN], def_unit[16]; static char unit[3] = "cip"; struct GMT_GRID *G = NULL, *I = NULL; diff --git a/src/gmtparser.c b/src/gmtparser.c index 93f3433..370e40e 100644 --- a/src/gmtparser.c +++ b/src/gmtparser.c @@ -21,7 +21,7 @@ * Version: 5 API * * Brief synopsis: gmtparser tests API conversions, common settings, - * and parameters via GMT_Get_Value, GMT_Get_Default, GMT_Get_Common + * and parameters via GMT_Get_Values, GMT_Get_Default, GMT_Get_Common * */ @@ -35,7 +35,6 @@ #define THIS_MODULE_NEEDS "" #define THIS_MODULE_OPTIONS "-BIJKOPRUVXYadefghinorst" /* All the GMT common options */ -#include "custom_version.h" /* Must include this to use Custom_version */ #include static int usage (void *API, int level) { @@ -95,7 +94,7 @@ EXTERN_MSC int GMT_gmtparser (void *API, int mode, void *args) { GMT_Message (API, GMT_TIME_CLOCK, "Enter various lengths, distances, coordinates, either one-by-one or comma/slash separated. End with - (a single hyphen):\n"); while (scanf ("%s", input) == 1 && input[0]) { /* As long as user provides input... */ if (!strcmp (input, "-")) break; /* OK, the end signal */ - ret = GMT_Get_Value (API, input, value); /* Convert one or more strings to doubles */ + ret = GMT_Get_Values (API, input, value, 10); /* Convert one or more strings to doubles */ report (input, ret, value); /* Report them as decimal values */ } diff --git a/src/grdfourier.c b/src/grdfourier.c index 7320308..3b9f908 100644 --- a/src/grdfourier.c +++ b/src/grdfourier.c @@ -39,8 +39,6 @@ #define MY_FFT_DIM 2 /* Dimension of FFT needed */ -#include "custom_version.h" /* Must include this to use Custom_version */ - /* Add any other include files needed by your program */ #include #include @@ -145,7 +143,7 @@ static int parse (void *API, struct GMT_GRDFOURIER_CTRL *Ctrl, struct GMT_OPTION break; case 'A': /* Location of spike */ Ctrl->A.active = 1; - if ((ret = GMT_Get_Value (API, opt->arg, value)) == 2) { + if ((ret = GMT_Get_Values (API, opt->arg, value, 2)) == 2) { Ctrl->A.row = (unsigned int)value[0]; Ctrl->A.col = (unsigned int)value[1]; } @@ -160,7 +158,7 @@ static int parse (void *API, struct GMT_GRDFOURIER_CTRL *Ctrl, struct GMT_OPTION break; case 'F': /* Gaussian filter width */ Ctrl->F.active = 1; - if ((ret = GMT_Get_Value (API, opt->arg, value)) == 1) Ctrl->F.width = value[0]; + if ((ret = GMT_Get_Values (API, opt->arg, value, 1)) == 1) Ctrl->F.width = value[0]; break; case 'G': /* Output file */ Ctrl->G.active = 1; @@ -234,10 +232,10 @@ EXTERN_MSC int GMT_grdfourier (void *API, int mode, void *args) { y = GMT_Get_Coord (API, GMT_IS_GRID, GMT_Y, Grid); /* Get array of y coordinates */ if (!Ctrl->A.active) { /* We know the grid dimension so we can select the mid point */ - Ctrl->A.row = Grid->header->ny / 2; - Ctrl->A.col = Grid->header->nx / 2; + Ctrl->A.row = Grid->header->n_rows / 2; + Ctrl->A.col = Grid->header->n_columns / 2; } - if (Ctrl->A.row >= Grid->header->ny || Ctrl->A.col >= Grid->header->nx) { + if (Ctrl->A.row >= Grid->header->n_rows || Ctrl->A.col >= Grid->header->n_columns) { GMT_Message (API, GMT_TIME_CLOCK, "Spike is placed outside the grid! We give up.\n"); Return (EXIT_FAILURE); }