[程式] 初次使用 GMT 的 C API:環境架構 on Mac

GMT ( GENERIC MAPPING TOOL) 是一套架構完整的工具,除了直接使用 Binary 以外,也提供 C 的 API 讓使用者自己開發程式。這篇將記述如何在 Mac 上安裝 GMT,並成功編譯第一個範例。

安裝 GMT

首先,雖然有已經編譯完成的安裝檔,不過實際使用時由於編譯路徑不同,系統似乎會找不到相關的函式庫與標頭檔,故建議自行編譯。在 Mac 上,有好用的套件管理工具 Homebrew 可以讓你方便的安裝 GMT ,他會自動安裝需要的相依套件,所以推薦大家使用。

安裝 Homebrew

如果電腦尚未安裝 Homebrew ,請先以以下指令安裝:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

按下 Return 鍵繼續,待其安裝完成後,加入 Homebrew/Science 編譯的菜單,裡面有 GMT 的編譯菜單:

brew tap homebrew/science
#----- 範例輸出 -----
==> Tapping homebrew/science
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-science'...
remote: Counting objects: 660, done.
remote: Compressing objects: 100% (655/655), done.
remote: Total 660 (delta 0), reused 62 (delta 0), pack-reused 0
Receiving objects: 100% (660/660), 590.51 KiB | 0 bytes/s, done.
Checking connectivity... done.
Tapped 643 formulae (678 files, 1.8M)

完成後,我們就可以來看最新的 GMT 版本資訊了:

brew info gmt
#----- 範例輸出 -----
homebrew/science/gmt: stable 5.3.1 (bottled)
Tools for processing and displaying xy and xyz datasets
http://gmt.soest.hawaii.edu/
Conflicts with: gmt4
Not installed
From: https://github.com/Homebrew/homebrew-science/blob/master/gmt.rb
==> Dependencies
Build: cmake ✘
Required: gdal ✘, netcdf ✘, fftw ✘, pcre ✘
==> Caveats
GMT 5 is mostly (but not 100%) compatible with previous versions.
Moreover, the compatibility mode is expected to exist only during a
transitional period.

If you want to continue using GMT 4:
`brew install gmt4`

We agreed to the `triangle` license
(http://www.cs.cmu.edu/~quake/triangle.html) for you.
If this is unacceptable you should uninstall.

上面我們就可以看到 GMT 最新的版本為 5.3.1 (本文撰寫時間:2017.1.4)

最後,來安裝 GMT 吧!

brew install gmt

範例輸出如下:

==> Installing gmt from homebrew/science
==> Installing dependencies for homebrew/science/gmt: libpng, jpeg, giflib, libtiff, lzlib, proj, libgeotiff, geos, json-c, libxml2, pcre, readline, sqlite, freexl, liblwgeom, libspatialite, gdal, szip, hdf5, netcdf, fftw
==> Installing homebrew/science/gmt dependency: libpng
==> Downloading https://homebrew.bintray.com/bottles/libpng-1.6.27.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libpng-1.6.27.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libpng/1.6.27: 26 files, 1.2M
==> Installing homebrew/science/gmt dependency: jpeg
==> Downloading https://homebrew.bintray.com/bottles/jpeg-8d.yosemite.bottle.2.tar.gz
######################################################################## 100.0%
==> Pouring jpeg-8d.yosemite.bottle.2.tar.gz
🍺  /usr/local/Cellar/jpeg/8d: 19 files, 731K
==> Installing homebrew/science/gmt dependency: giflib
==> Downloading https://homebrew.bintray.com/bottles/giflib-4.2.3.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring giflib-4.2.3.yosemite.bottle.1.tar.gz
🍺  /usr/local/Cellar/giflib/4.2.3: 39 files, 622.2K
==> Installing homebrew/science/gmt dependency: libtiff
==> Downloading https://homebrew.bintray.com/bottles/libtiff-4.0.7.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libtiff-4.0.7.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libtiff/4.0.7: 248 files, 3.3M
==> Installing homebrew/science/gmt dependency: lzlib
==> Downloading https://homebrew.bintray.com/bottles/lzlib-1.8.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring lzlib-1.8.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/lzlib/1.8: 9 files, 129.9K
==> Installing homebrew/science/gmt dependency: proj
==> Downloading https://homebrew.bintray.com/bottles/proj-4.9.3.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring proj-4.9.3.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/proj/4.9.3: 54 files, 6M
==> Installing homebrew/science/gmt dependency: libgeotiff
==> Downloading https://homebrew.bintray.com/bottles/libgeotiff-1.4.1_2.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libgeotiff-1.4.1_2.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libgeotiff/1.4.1_2: 74 files, 6.4M
==> Installing homebrew/science/gmt dependency: geos
==> Downloading https://homebrew.bintray.com/bottles/geos-3.6.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring geos-3.6.1.yosemite.bottle.tar.gz
==> Caveats
Python modules have been installed and Homebrew's site-packages is not
in your Python sys.path, so you will not be able to import the modules
this formula installed. If you plan to develop with these modules,
please run:
  mkdir -p /Users/admin/Library/Python/2.7/lib/python/site-packages
  echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users/admin/Library/Python/2.7/lib/python/site-packages/homebrew.pth
==> Summary
🍺  /usr/local/Cellar/geos/3.6.1: 401 files, 7.4M
==> Installing homebrew/science/gmt dependency: json-c
==> Downloading https://homebrew.bintray.com/bottles/json-c-0.12.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring json-c-0.12.yosemite.bottle.1.tar.gz
🍺  /usr/local/Cellar/json-c/0.12: 26 files, 161K
==> Installing homebrew/science/gmt dependency: libxml2
==> Downloading https://homebrew.bintray.com/bottles/libxml2-2.9.4_1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libxml2-2.9.4_1.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/libxml2/lib
    CPPFLAGS: -I/usr/local/opt/libxml2/include
    PKG_CONFIG_PATH: /usr/local/opt/libxml2/lib/pkgconfig

==> Summary
🍺  /usr/local/Cellar/libxml2/2.9.4_1: 277 files, 9.8M
==> Installing homebrew/science/gmt dependency: pcre
==> Downloading https://homebrew.bintray.com/bottles/pcre-8.39.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring pcre-8.39.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/pcre/8.39: 203 files, 5.4M
==> Installing homebrew/science/gmt dependency: readline
==> Downloading https://homebrew.bintray.com/bottles/readline-7.0.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring readline-7.0.1.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

macOS provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only.


Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/readline/lib
    CPPFLAGS: -I/usr/local/opt/readline/include

==> Summary
🍺  /usr/local/Cellar/readline/7.0.1: 46 files, 2.1M
==> Installing homebrew/science/gmt dependency: sqlite
==> Downloading https://homebrew.bintray.com/bottles/sqlite-3.16.0.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring sqlite-3.16.0.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

macOS provides an older sqlite3.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/sqlite/lib
    CPPFLAGS: -I/usr/local/opt/sqlite/include
    PKG_CONFIG_PATH: /usr/local/opt/sqlite/lib/pkgconfig

==> Summary
🍺  /usr/local/Cellar/sqlite/3.16.0: 11 files, 3.0M
==> Installing homebrew/science/gmt dependency: freexl
==> Downloading https://homebrew.bintray.com/bottles/freexl-1.0.2.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring freexl-1.0.2.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/freexl/1.0.2: 11 files, 119.6K
==> Installing homebrew/science/gmt dependency: liblwgeom
==> Downloading https://homebrew.bintray.com/bottles/liblwgeom-2.1.5_3.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring liblwgeom-2.1.5_3.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Conflicts with PostGIS, which also installs liblwgeom.dylib

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/liblwgeom/lib
    CPPFLAGS: -I/usr/local/opt/liblwgeom/include

==> Summary
🍺  /usr/local/Cellar/liblwgeom/2.1.5_3: 11 files, 2.2M
==> Installing homebrew/science/gmt dependency: libspatialite
==> Downloading https://homebrew.bintray.com/bottles/libspatialite-4.3.0a_3.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libspatialite-4.3.0a_3.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libspatialite/4.3.0a_3: 31 files, 19.3M
==> Installing homebrew/science/gmt dependency: gdal
==> Downloading https://homebrew.bintray.com/bottles/gdal-1.11.5_1.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring gdal-1.11.5_1.yosemite.bottle.1.tar.gz
==> Caveats
Python modules have been installed and Homebrew's site-packages is not
in your Python sys.path, so you will not be able to import the modules
this formula installed. If you plan to develop with these modules,
please run:
  mkdir -p /Users/admin/Library/Python/2.7/lib/python/site-packages
  echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users/admin/Library/Python/2.7/lib/python/site-packages/homebrew.pth
==> Summary
🍺  /usr/local/Cellar/gdal/1.11.5_1: 232 files, 31.0M
==> Installing homebrew/science/gmt dependency: szip
==> Downloading https://homebrew.bintray.com/bottles/szip-2.1.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring szip-2.1.yosemite.bottle.1.tar.gz
🍺  /usr/local/Cellar/szip/2.1: 11 files, 110.3K
==> Installing homebrew/science/gmt dependency: hdf5
==> Downloading https://homebrew.bintray.com/bottles-science/hdf5-1.8.18.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring hdf5-1.8.18.yosemite.bottle.1.tar.gz
🍺  /usr/local/Cellar/hdf5/1.8.18: 181 files, 10.6M
==> Installing homebrew/science/gmt dependency: netcdf
==> Downloading https://homebrew.bintray.com/bottles-science/netcdf-4.3.3.1_6.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring netcdf-4.3.3.1_6.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/netcdf/4.3.3.1_6: 53 files, 4.0M
==> Installing homebrew/science/gmt dependency: fftw
==> Downloading https://homebrew.bintray.com/bottles/fftw-3.3.5.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring fftw-3.3.5.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/fftw/3.3.5: 45 files, 10.8M
==> Installing homebrew/science/gmt 
==> Downloading https://homebrew.bintray.com/bottles-science/gmt-5.3.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring gmt-5.3.1.yosemite.bottle.tar.gz
==> Caveats
GMT 5 is mostly (but not 100%) compatible with previous versions.
Moreover, the compatibility mode is expected to exist only during a
transitional period.

If you want to continue using GMT 4:
`brew install gmt4`

We agreed to the `triangle` license
(http://www.cs.cmu.edu/~quake/triangle.html) for you.
If this is unacceptable you should uninstall.

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> Summary
🍺  /usr/local/Cellar/gmt/5.3.1: 1,623 files, 202.3M

安裝完以後的位置在:

/usr/local/Cellar/gmt/5.3.1

範例則在:

/usr/local/Cellar/gmt/5.3.1/share/doc/gmt/examples

編譯 GMT C 程式:

官方說明上提供的第一個範例如下:

#include "gmt.h"
int main (int argc, char *argv[]) {
    void *API;                        /* The API control structure */
    struct GMT_DATASET *D = NULL;     /* Structure to hold input dataset */
    struct GMT_GRID *G = NULL;        /* Structure to hold output grid */
    char input[GMT_STR16] = {""};     /* String to hold virtual input filename */
    char output[GMT_STR16] = {""};    /* String to hold virtual output filename */
    char args[128] = {""};            /* String to hold module command arguments */

    /* Initialize the GMT session */
    API = GMT_Create_Session ("test", 2U, 0, NULL);
    /* Read in our data table to memory */
    D = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_PLP, GMT_READ_NORMAL, NULL,
        "table_5.11", NULL);
    /* Associate our data table with a virtual file */
    GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_PLP, GMT_IN, D, input);
    /* Create a virtual file to hold the resulting grid */
    GMT_Open_VirtualFile (API, GMT_IS_GRID, GMT_IS_SURFACE, GMT_OUT, NULL, output);
    /* Prepare the module arguments */
    sprintf (args, "-R0/7/0/7 -I0.2 -D1 -St0.3 %s -G%s", input, output);
    /* Call the greenspline module */
    GMT_Call_Module (API, "greenspline", GMT_MODULE_CMD, args);
    /* Obtain the grid from the virtual file */
    G = GMT_Read_VirtualFile (API, output);
    /* Close the virtual files */
    GMT_Close_VirtualFile (API, 0, input);
    GMT_Close_VirtualFile (API, 0, output);
    /* Write the grid to file */
    GMT_Write_Data (API, GMT_IS_GRID, GMT_IS_FILE, GMT_IS_SURFACE, GMT_READ_NORMAL, NULL,
        "junk.nc", G);
    /* Destroy the GMT session */
    GMT_Destroy_Session (API);
};

將上面的檔案存為 example1.c ,另外,範例所需的原始資料如下,請存為 table_5.11

0.3	6.1	870
1.4	6.2	793
2.4	6.1	755
3.6	6.2	690
5.7	6.2	800
1.6	5.2	800
2.9	5.1	730
3.4	5.3	728
3.4	5.7	710
4.8	5.6	780
5.3	5.0	804
6.2	5.2	855
0.2	4.3	830
0.9	4.2	813
2.3	4.8	762
2.5	4.5	765
3.0	4.5	740
3.5	4.5	765
4.1	4.6	760
4.9	4.2	790
6.3	4.3	820
0.9	3.2	855
1.7	3.8	812
2.4	3.8	773
3.7	3.5	812
4.5	3.2	827
5.2	3.2	805
6.3	3.4	840
0.3	2.4	890
2.0	2.7	820
3.8	2.3	873
6.3	2.2	875
0.6	1.7	873
1.5	1.8	865
2.1	1.8	841
2.1	1.1	862
3.1	1.1	908
4.5	1.8	855
5.5	1.7	850
5.7	1.0	882
6.2	1.0	910
0.4	0.5	940
1.4	0.6	915
1.4	0.1	890
2.1	0.7	880
2.3	0.3	870
3.1	0.0	880
4.1	0.8	960
5.4	0.4	890
6.0	0.1	860
5.7	3.0	830
3.6	6.0	705

接下來就是編譯設定了,我們用 gcc 來編譯的話,需要設定 header 與 library 的旗標。

inc=`gmt-config --cflags`
lib=`gmt-config --libs`
gcc example1.c $inc $lib -o example1

如果是裝已經編譯好的 app 的話,這邊的設定就會有問題,因為 gmt-config –cflags 與 gmt-config –libs 會連結到編譯時那台電腦的設定,因此會找不到相關的函式庫。

gmt-config --cflags
#----- 範例輸出 -----
-I/usr/local/include/gmt
gmt-config --libs
#----- 範例輸出 -----
-L/usr/local/lib -lgmt

最後執行 compile.sh 啦!

sh compile.sh

完成後,可以跑編譯完成的檔案:

./example1

這時候會生成「junk.nc」,我們可以用

gmt grdimage junk.nc > junk.ps

輸出為 postscript 檔,這樣就可以用預覽程式來檢視了!

完成!

 

後記:

編譯時,可能出現錯誤:

example1.c: In function 「main」:
example1.c:26:5: 錯誤:提供給函式 「GMT_Close_VirtualFile」 的引數太多
     GMT_Close_VirtualFile (API, 0, input);
     ^
In file included from example1.c:1:0:
/usr/local/include/gmt/gmt.h:94:16: 附註:declared here
 EXTERN_MSC int GMT_Close_VirtualFile  (void *API, const char *string);
                ^
example1.c:27:5: 錯誤:提供給函式 「GMT_Close_VirtualFile」 的引數太多
     GMT_Close_VirtualFile (API, 0, output);
     ^
In file included from example1.c:1:0:
/usr/local/include/gmt/gmt.h:94:16: 附註:declared here
 EXTERN_MSC int GMT_Close_VirtualFile  (void *API, const char *string);

這時候將

GMT_Close_VirtualFile (API, 0, input);
GMT_Close_VirtualFile (API, 0, output);

改為

GMT_Close_VirtualFile (API, input);
GMT_Close_VirtualFile (API, output);

應該就可以過關了!

One thought on “[程式] 初次使用 GMT 的 C API:環境架構 on Mac

請多多指教!

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料