用介子构建gobject库导致未定义的符号
Building a gobject library with meson leads to undefined symbols
我想实现一个基于 gobject 类型系统的库。所以每个 object 都是 GObjectClass
的实例
在 header gwl-registry.h
我有:
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
声明类型和获取类型的函数。根据 gobject 教程,这是我应该做的:https://developer.gnome.org/gobject/stable/howto-gobject.html 如果我理解正确,这些宏应该扩展为包括实例转换 GWL_REGISTRY()
和类型检查宏 GWL_IS_REGISTRY()
。然而,这两个函数都依赖于函数 gwl_registry_get_type()。
如果我没记错的话,这应该在源文件 gwl-registry.c
中实现。在这里,我使用以下代码定义类型:
G_DEFINE_TYPE_WITH_PRIVATE(GwlRegistry, gwl_registry, G_TYPE_OBJECT)
这个宏应该展开来创建 GType gwl_registry_get_type()
。
我使用介子创建了一个目前看起来像这样的库:
├── data
│ └── xdg-shell.xml
├── include
│ ├── gwl-display.h
│ ├── gwl.h
│ ├── gwl-import.h
│ ├── gwl-registry.h
│ ├── gwl-registry-private.h
│ └── meson.build
├── meson.build
├── src
│ ├── gwayland.c
│ ├── gwl-display.c
│ ├── gwl-registry.c
│ └── meson.build
└── test
├── display-test.c
├── gwayland-test.c
├── meson.build
├── registry-test.c
└── tests.h
顶层 meson.build 看起来像:
project(
'GWayland', 'c',
version : '0.1',
default_options : ['warning_level=3']
)
glib_dep = dependency('glib-2.0')
gobject_dep = dependency('gobject-2.0')
wayland_dep = dependency('wayland-client')
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_GWL']
subdir('src')
subdir('include')
# Make this library usable as a Meson subproject.
gwayland_dep = declare_dependency(
include_directories: include_directories('./include'),
dependencies: [glib_dep, gobject_dep, wayland_dep],
link_with : gwayland_shared_lib
)
subdir('test')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : 'GWayland',
filebase : 'gwayland',
description : 'Meson sample project.',
subdirs : 'gwayland',
libraries : gwayland_shared_lib,
version : '0.1',
)
src meson.build 看起来像:
gwayland_srcs = [
'gwl-display.c',
'gwl-registry.c',
]
gwayland_shared_lib = shared_library(
'gwayland',
gwayland_srcs,
install : true,
c_args : lib_args,
gnu_symbol_visibility : 'hidden',
include_directories : '../include',
dependencies : [glib_dep, gobject_dep, wayland_dep],
)
和测试:
test_sources = [
'gwayland-test.c',
'tests.h',
'display-test.c',
'registry-test.c',
]
test_deps = [glib_dep, wayland_dep]
test_exe = executable(
'gwayland_test',
test_sources,
dependencies: gwayland_dep,
# link_with : gwayland_shared_lib
env : [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_source_dir())
]
)
test('gwayland', test_exe)
目前在测试中我正在调用转换宏 GWL_IS_REGISTRY()
g_assert_true(GWL_IS_REGISTRY(registry));
这会导致以下错误:
cc -o test/gwayland_test test/gwayland_test.p/gwayland-test.c.o test/gwayland_test.p/display-test.c.o test/gwayland_test.p/registry-test.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group src/libgwayland.so /usr/lib/x86_64-linux-gnu/libglib-2.0.so /usr/lib/x86_64-linux-gnu/libgobject-2.0.so /usr/lib/x86_64-linux-gnu/libwayland-client.so -Wl,--end-group '-Wl,-rpath,$ORIGIN/../src' -Wl,-rpath-link,/home/duijn119/github/gwayland/build/src
test/gwayland_test.p/registry-test.c.o: In function `GWL_IS_REGISTRY':
/home/duijn119/github/gwayland/build/../include/gwl-registry.h:30: undefined reference to `gwl_registry_get_type'
collect2: error: ld returned 1 exit status
如果我用 nm 检查库:
nm src/libgwayland.so | egrep 'get_type|new.'
000000000000193f t gwl_display_get_type
0000000000001fcd T gwl_display_new_address
000000000000231f t gwl_registry_get_type
似乎不知何故 gwl_registry_get_type 没有导出到库外使用,在 library/compilation 单元旁边我可以很好地调用函数。
谁能帮我 glib/gobject 告诉我我做错了什么,或者我在构建库和测试时遇到介子问题。
您已明确要求默认情况下不从库中导出符号:
gnu_symbol_visibility : 'hidden'
要么更改默认值,要么使用 G_MODULE_EXPORT
.
明确标记要导出的符号
您可以使用
明确标记要导出的gwl_display_get_type()
符号
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_MODULE_EXPORT
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
因为 get_type()
函数保证是 G_DECLARE_DERIVABLE_TYPE
宏发出的第一个东西。
我想实现一个基于 gobject 类型系统的库。所以每个 object 都是 GObjectClass
的实例在 header gwl-registry.h
我有:
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
声明类型和获取类型的函数。根据 gobject 教程,这是我应该做的:https://developer.gnome.org/gobject/stable/howto-gobject.html 如果我理解正确,这些宏应该扩展为包括实例转换 GWL_REGISTRY()
和类型检查宏 GWL_IS_REGISTRY()
。然而,这两个函数都依赖于函数 gwl_registry_get_type()。
如果我没记错的话,这应该在源文件 gwl-registry.c
中实现。在这里,我使用以下代码定义类型:
G_DEFINE_TYPE_WITH_PRIVATE(GwlRegistry, gwl_registry, G_TYPE_OBJECT)
这个宏应该展开来创建 GType gwl_registry_get_type()
。
我使用介子创建了一个目前看起来像这样的库:
├── data
│ └── xdg-shell.xml
├── include
│ ├── gwl-display.h
│ ├── gwl.h
│ ├── gwl-import.h
│ ├── gwl-registry.h
│ ├── gwl-registry-private.h
│ └── meson.build
├── meson.build
├── src
│ ├── gwayland.c
│ ├── gwl-display.c
│ ├── gwl-registry.c
│ └── meson.build
└── test
├── display-test.c
├── gwayland-test.c
├── meson.build
├── registry-test.c
└── tests.h
顶层 meson.build 看起来像:
project(
'GWayland', 'c',
version : '0.1',
default_options : ['warning_level=3']
)
glib_dep = dependency('glib-2.0')
gobject_dep = dependency('gobject-2.0')
wayland_dep = dependency('wayland-client')
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_GWL']
subdir('src')
subdir('include')
# Make this library usable as a Meson subproject.
gwayland_dep = declare_dependency(
include_directories: include_directories('./include'),
dependencies: [glib_dep, gobject_dep, wayland_dep],
link_with : gwayland_shared_lib
)
subdir('test')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : 'GWayland',
filebase : 'gwayland',
description : 'Meson sample project.',
subdirs : 'gwayland',
libraries : gwayland_shared_lib,
version : '0.1',
)
src meson.build 看起来像:
gwayland_srcs = [
'gwl-display.c',
'gwl-registry.c',
]
gwayland_shared_lib = shared_library(
'gwayland',
gwayland_srcs,
install : true,
c_args : lib_args,
gnu_symbol_visibility : 'hidden',
include_directories : '../include',
dependencies : [glib_dep, gobject_dep, wayland_dep],
)
和测试:
test_sources = [
'gwayland-test.c',
'tests.h',
'display-test.c',
'registry-test.c',
]
test_deps = [glib_dep, wayland_dep]
test_exe = executable(
'gwayland_test',
test_sources,
dependencies: gwayland_dep,
# link_with : gwayland_shared_lib
env : [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_source_dir())
]
)
test('gwayland', test_exe)
目前在测试中我正在调用转换宏 GWL_IS_REGISTRY()
g_assert_true(GWL_IS_REGISTRY(registry));
这会导致以下错误:
cc -o test/gwayland_test test/gwayland_test.p/gwayland-test.c.o test/gwayland_test.p/display-test.c.o test/gwayland_test.p/registry-test.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group src/libgwayland.so /usr/lib/x86_64-linux-gnu/libglib-2.0.so /usr/lib/x86_64-linux-gnu/libgobject-2.0.so /usr/lib/x86_64-linux-gnu/libwayland-client.so -Wl,--end-group '-Wl,-rpath,$ORIGIN/../src' -Wl,-rpath-link,/home/duijn119/github/gwayland/build/src
test/gwayland_test.p/registry-test.c.o: In function `GWL_IS_REGISTRY':
/home/duijn119/github/gwayland/build/../include/gwl-registry.h:30: undefined reference to `gwl_registry_get_type'
collect2: error: ld returned 1 exit status
如果我用 nm 检查库:
nm src/libgwayland.so | egrep 'get_type|new.'
000000000000193f t gwl_display_get_type
0000000000001fcd T gwl_display_new_address
000000000000231f t gwl_registry_get_type
似乎不知何故 gwl_registry_get_type 没有导出到库外使用,在 library/compilation 单元旁边我可以很好地调用函数。
谁能帮我 glib/gobject 告诉我我做错了什么,或者我在构建库和测试时遇到介子问题。
您已明确要求默认情况下不从库中导出符号:
gnu_symbol_visibility : 'hidden'
要么更改默认值,要么使用 G_MODULE_EXPORT
.
您可以使用
明确标记要导出的gwl_display_get_type()
符号
#define GWL_TYPE_REGISTRY gwl_registry_get_type()
G_MODULE_EXPORT
G_DECLARE_DERIVABLE_TYPE(GwlRegistry, gwl_registry, GWL, REGISTRY, GObject)
因为 get_type()
函数保证是 G_DECLARE_DERIVABLE_TYPE
宏发出的第一个东西。