[已解决]obs 打包错误,未定义的引用

我在个人仓库上打包 xbindkeys_config,原本 Makefile 用了 gtk-config,蜥蜴上找不到,更加通用的是 pkg-config,debian 的开发者提供了一个补丁,修复这个 issue。此外这个补丁还废弃了源码中使用 gtk 好几年前已经不用的头文件函数等。
补丁已经正确打上了,但是编译的时候,

gcc -o xbindkeys_config pkg-config --libs --cflags gtk+-2.0 *.c *.h

这里 pkg-config 是用来查找系统上 gtk±2.0 的头文件,链接库的,并加上对应的 -L -I 选项,这样子编译的时候才能找到链接库和头文件等等。
但是在 OBS 上编译却会出现很多的未定义引用的错误,说明 pkg-config 根本没起作用啊。OBS 上的和本地机器在这里有什么不同吗?

我的个人仓库 xbindkeys_config

  • BuildRequires: pkg-config
  • BuildRequires: gtk2-devel
  • BuildRequires: pkgconfig(gtk±2.0)

这样?

楼上那个改法不对,不是编译依赖的问题,那个有问题要么直接 configure 失败,要么是 file or directory not found 或隐性引用。

Sent from my iPhone 5s using Tapatalk

看了一下,你先犯了一个最简单的错误:人家有 Makefile 你非要自己 gcc。解压源代码看一下都不会出现这种低级错误。

你自己 gcc 又犯了一个错误,引用系统头文件不在 CFLAGS 里告诉系统头文件的路径:

gcc -I/usr/include pkg-config --cflags --libs gtk+-2.0 *.c *.h -o xbindkeys_config

或者直接 make 完全没有任何问题。

PS:

  1. 你的补丁不是用 UTF-8 格式保存的,自己去 OBS 预览一下就能发现
  2. 生成补丁为啥生成了一套 debian 目录?
  3. 那个 Makefile 依然有问题就是 CFLAGS 里没有 %{optflags} 这样出不来 debuginfo 包。需要

CFLAGS="$CFLAGS %{optflags}"
make

或者

gcc -I/usr/include %{optflags} pkg-config --cflags --libs gtk+-2.0 *.c *.h -o xbindkeys_config

1赞

他的Makefile直接写 prefix=/usr,本地测试发现 %install 就会安装到系统的 /usr 下去了。补丁是 Debian 的开发者写的,有 debian 目录也很正常啊。
昨天给原开发者发邮件,结果邮件被退回了。看样子这个项目算是废弃了。可惜啊

来自我的 Nexus 5 上的 Tapatalk

这里的 pkg-config --cflags --libs gtk+2.0 就给 gcc 编译的是所需要的链接 gtk+2.0 的东西:

-pthread -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/freetype2 -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype

那些未定义的引用都是定义在 /usr/include/gtk-2.0 下的头文件里的。看到编译 log 里,gcc 编译的那行:

gcc -pthread -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/freetype2 -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype menu.c middle.c speedc.c xbindkeys_config.c menu.h middle.h speedc.h version.h -o xbindkeys_config

具体的 --cflgs --libs 也展开了,这些是正确的啊。为什么还会有未定义的引用这种错误?

你还没明白怎么回事?

你没发现你真正编译时候根本没有用 -I/usr/include %{optflags} 吗?

解决方法是对的,你没有能够用上。

我找到了问题的根源,是 ld 的 --as-needed 参数,作用是让链接器去除命令行引入但是并没有被使用的 lib。这种情况下 lib 和目标文件的顺序很重要,否则会丢弃需要的 lib,导致 undefined reference。
这里有一篇 gentoo-wiki 的文章说的很清楚: wiki.gentoo.org/wiki/Project:Quality_Assurance/As-needed

所以,Makefile 的 link 顺序改下,OBJS 在前面就通过了。 build.opensuse.org/package/show/home:limon7:branches:home:hottea/xbindkeys_config

main: $(OBJS)
        $(CC) $(OBJS) $(GTK) -o $(NOM)

在本地编译没有设置这个参数所以能通过,而 obs 上是强制的。如果安装了 post-build-checks,本地编译就会发现和 obs 同样的错误,这个包在 /etc/profile.d/suse-buildsystem.sh 里定义了 SUSE_ASNEEDED=1

这个问题在列表里也有人讨论过。
lists.opensuse.org/opensuse-buildservice/2014-03/msg00045.html

也可以直接

%build
export SUSE_ASNEEDED=0

不错,复杂的链接关系自己清理也很头疼,这样能偷个懒。。。

这回 ok 了,加上了

%build
export SUSE_ASNEEDED=0

这打包也真不是一般的复杂啊,还需要多多学习。多谢各位指点 :1: