使用 GEOS 和 PostGIS 的 PostgreSQL 扩展 - 未定义符号:lwgeom_geos_error
PostgreSQL extension using GEOS and PostGIS - undefined symbol: lwgeom_geos_error
我试着写了一些 PostgreSQL 扩展,只是一个基于这个 tutorial 的简单函数。它
有效,但后来我想编写一个使用一些 GEOS 代码的扩展。所以我根据Postgis函数ST_RelateMatch写了函数(但是对于多个模式参数),但是我在编译过程中遇到了问题(可能与链接有关)。
这是我用 C:
编写的函数
#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
#include "utils/builtins.h"
// here I had to add path to headers because I got fatal error: lwgeom_geos.h: No such file or directory
#include "./postgis-3.0.0/liblwgeom/lwgeom_geos.h"
#include "./postgis-3.0.0/libpgcommon/lwgeom_pg.h"
#include <string.h>
#include <assert.h>
/* #define POSTGIS_DEBUG_LEVEL 4 */
/* My RelateMatchFunction */
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(myrelatematch);
Datum myrelatematch(PG_FUNCTION_ARGS)
{
char *mat, *pat;
text *mat_text, *pat_text;
int result, arg;
mat_text = (PG_GETARG_TEXT_P(0));
mat = text_to_cstring(mat_text);
initGEOS(lwpgnotice, lwgeom_geos_error);
for (arg=1; arg < PG_NARGS(); arg++)
{
if (!PG_ARGISNULL(arg))
{
pat_text = (PG_GETARG_TEXT_P(arg));
pat = text_to_cstring(pat_text);
result = GEOSRelatePatternMatch(mat, pat);
if (result == 2)
{
lwfree(mat); lwfree(pat);
lwpgerror("GEOSRelatePatternMatch: %s", lwgeom_geos_errmsg);
PG_RETURN_NULL();
} else if (result == 1)
{
lwfree(mat); lwfree(pat);
PG_RETURN_BOOL(result);
}
}
}
PG_RETURN_BOOL(0);
}
然后我使用了教程中的Makefile
:
MODULES = myrelatematch
EXTENSION = myrelatematch
DATA = myrelatematch--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
这是我的 SQL 代码:
CREATE OR REPLACE FUNCTION
myrelatematch(text,variadic text[]) RETURNS int AS 'MODULE_PATHNAME','myrelatematch'
LANGUAGE C STRICT;
现在如果我 运行 make
在 Ubuntu 18.04 上没有错误。它创建共享对象,如果我 运行 sudo make install
没有错误但是如果我在数据库中 运行 CREATE EXTENSION myrelatematch
我得到这个错误:
ERROR: could not load library "/usr/lib/postgresql/11/lib/myrelatematch.so": /usr/lib/postgresql/11/lib/myrelatematch.so: undefined symbol: lwgeom_geos_error
我是 运行ning Ubuntu 18.04,Postgis 的所有库都在服务器上(我能够从源代码编译 Postgis)。 Postgresql 版本为 11.6.
我没有经验,我总是在编译软件的较大部分时发现问题。我以为链接库有问题,但经过一整天的调试后我需要帮助。
编辑
如果我复制 gcc 命令并添加 -Wl,--no-undefined
我从链接器中得到错误:
/home/username/myrelatematch/myrelatematch.c:26: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:27: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwgeom_geos_error'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwpgnotice'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `initGEOS'
/home/username/myrelatematch/myrelatematch.c:35: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:36: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:38: undefined reference to `GEOSRelatePatternMatch'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwgeom_geos_errmsg'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwpgerror'
如果我添加-L/home/username/myrelatematch/postgis-3.0.0/liblwgeom
没有变化,错误是一样的。
这是完整的 gcc 命令:
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -fPIC -L/usr/lib/x86_64-linux-gnu -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/llvm-6.0/lib -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed -L/home/username/myrelatematch/postgis-3.0.0/liblwgeom -Wl,--no-undefined -shared -o myrelatematch.so myrelatematch.o
基于这些问题 (pgxs question - linking c-functions to external libraries and PGXS ignores SHLIB_LINK when linking modules) 我找到了解决方案。
Here is the example of Makefile with third party libraries
还有我的 GEOS
、LIBLWGEOM
一个 LIBPGCOMMON
库的 Makefile:
EXTENSION = vectgen
DATA = vectgen--0.0.1.sql
OBJS = vectgen.o
MODULE_big = vectgen
# postgres build stuff
SHLIB_LINK = -lgeos_c -llwgeom -lpgcommon
PG_LDFLAGS += -L /home/username/CLionProjects/test_geos/libpgcommon
PG_CPPFLAGS = -I /home/username/CLionProjects/test_geos/libpgcommon
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
我必须为 MODULE_big
更改 MODULES
,然后 SHLIB_LINK
被考虑在编译中,因此 -l
标志适用于库。之后我将 libpgcommon
从 PostGIS 复制到我的项目中并与 PG_LDFLAGS
.
链接
我试着写了一些 PostgreSQL 扩展,只是一个基于这个 tutorial 的简单函数。它 有效,但后来我想编写一个使用一些 GEOS 代码的扩展。所以我根据Postgis函数ST_RelateMatch写了函数(但是对于多个模式参数),但是我在编译过程中遇到了问题(可能与链接有关)。
这是我用 C:
编写的函数#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
#include "utils/builtins.h"
// here I had to add path to headers because I got fatal error: lwgeom_geos.h: No such file or directory
#include "./postgis-3.0.0/liblwgeom/lwgeom_geos.h"
#include "./postgis-3.0.0/libpgcommon/lwgeom_pg.h"
#include <string.h>
#include <assert.h>
/* #define POSTGIS_DEBUG_LEVEL 4 */
/* My RelateMatchFunction */
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(myrelatematch);
Datum myrelatematch(PG_FUNCTION_ARGS)
{
char *mat, *pat;
text *mat_text, *pat_text;
int result, arg;
mat_text = (PG_GETARG_TEXT_P(0));
mat = text_to_cstring(mat_text);
initGEOS(lwpgnotice, lwgeom_geos_error);
for (arg=1; arg < PG_NARGS(); arg++)
{
if (!PG_ARGISNULL(arg))
{
pat_text = (PG_GETARG_TEXT_P(arg));
pat = text_to_cstring(pat_text);
result = GEOSRelatePatternMatch(mat, pat);
if (result == 2)
{
lwfree(mat); lwfree(pat);
lwpgerror("GEOSRelatePatternMatch: %s", lwgeom_geos_errmsg);
PG_RETURN_NULL();
} else if (result == 1)
{
lwfree(mat); lwfree(pat);
PG_RETURN_BOOL(result);
}
}
}
PG_RETURN_BOOL(0);
}
然后我使用了教程中的Makefile
:
MODULES = myrelatematch
EXTENSION = myrelatematch
DATA = myrelatematch--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
这是我的 SQL 代码:
CREATE OR REPLACE FUNCTION
myrelatematch(text,variadic text[]) RETURNS int AS 'MODULE_PATHNAME','myrelatematch'
LANGUAGE C STRICT;
现在如果我 运行 make
在 Ubuntu 18.04 上没有错误。它创建共享对象,如果我 运行 sudo make install
没有错误但是如果我在数据库中 运行 CREATE EXTENSION myrelatematch
我得到这个错误:
ERROR: could not load library "/usr/lib/postgresql/11/lib/myrelatematch.so": /usr/lib/postgresql/11/lib/myrelatematch.so: undefined symbol: lwgeom_geos_error
我是 运行ning Ubuntu 18.04,Postgis 的所有库都在服务器上(我能够从源代码编译 Postgis)。 Postgresql 版本为 11.6.
我没有经验,我总是在编译软件的较大部分时发现问题。我以为链接库有问题,但经过一整天的调试后我需要帮助。
编辑
如果我复制 gcc 命令并添加 -Wl,--no-undefined
我从链接器中得到错误:
/home/username/myrelatematch/myrelatematch.c:26: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:27: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwgeom_geos_error'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwpgnotice'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `initGEOS'
/home/username/myrelatematch/myrelatematch.c:35: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:36: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:38: undefined reference to `GEOSRelatePatternMatch'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwgeom_geos_errmsg'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwpgerror'
如果我添加-L/home/username/myrelatematch/postgis-3.0.0/liblwgeom
没有变化,错误是一样的。
这是完整的 gcc 命令:
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -fPIC -L/usr/lib/x86_64-linux-gnu -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/llvm-6.0/lib -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed -L/home/username/myrelatematch/postgis-3.0.0/liblwgeom -Wl,--no-undefined -shared -o myrelatematch.so myrelatematch.o
基于这些问题 (pgxs question - linking c-functions to external libraries and PGXS ignores SHLIB_LINK when linking modules) 我找到了解决方案。
Here is the example of Makefile with third party libraries
还有我的 GEOS
、LIBLWGEOM
一个 LIBPGCOMMON
库的 Makefile:
EXTENSION = vectgen
DATA = vectgen--0.0.1.sql
OBJS = vectgen.o
MODULE_big = vectgen
# postgres build stuff
SHLIB_LINK = -lgeos_c -llwgeom -lpgcommon
PG_LDFLAGS += -L /home/username/CLionProjects/test_geos/libpgcommon
PG_CPPFLAGS = -I /home/username/CLionProjects/test_geos/libpgcommon
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
我必须为 MODULE_big
更改 MODULES
,然后 SHLIB_LINK
被考虑在编译中,因此 -l
标志适用于库。之后我将 libpgcommon
从 PostGIS 复制到我的项目中并与 PG_LDFLAGS
.