PKG_CHECK_MODULES 认为有害吗?

Posted

技术标签:

【中文标题】PKG_CHECK_MODULES 认为有害吗?【英文标题】:PKG_CHECK_MODULES considered harmful? 【发布时间】:2012-04-30 13:07:12 【问题描述】:

各种开发人员不鼓励使用PKG_CHECK_MODULES(例如,this answer),但就我所寻找的原因而言,没有明确、全面的解释。所以,我问:

为什么PKG_CHECK_MODULES 会有害? 有哪些替代方案?

我今天第一次使用它。我发现它非常有用,特别是对于处理非常复杂的库集,例如 GTK+,我拥有所有这些依赖项:

-I/usr/lib/i386-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0
-I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 
-I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 
-I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 
-I/usr/include/freetype2 -I/usr/include/libpng12

-lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 
-lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0
-lgthread-2.0 -lrt -lglib-2.0 

【问题讨论】:

尽管 William Pursell 通常提出的 pkg-config 替代方案背后的原因是合理的,但现实情况是,像 GTK 这样的整个平台都以“错误”的方式工作,修复它需要所有这些库以更改它们自己安装的目录。这将导致现有应用程序的构建系统的大量破坏。由于我认为“错误”的方式实际上不会造成任何伤害,因此不值得改变。 另外,pkg-config 允许您保持并行安装的不兼容版本的库(例如 GTK 2 和 GTK 3)。虽然我确信 William Pursell 已经考虑过这一点,并且很乐意解释如何按照他的方式去做 ;-) @ptomato 不,我严格来说是一个非 gui 人,从未直接与 gtk 打过交道。但我相信完全有可能做类似 "LDFLAGS=-L$( pkg-config --libs-only-L gtk+-2.0 ) CPPFLAGS=$( pkg-config --cflags gtk+-2.0 ) LIBS=$ ( pkg-config --libs-only-l gtk+-2.0 )",这些选项可以放在 config.site 中。需要明确的是,我对 pkg-config 没有异议,但我不喜欢 PKG_CHECK_MODULES,原因在我的回答中列出。 @至于安装不兼容版本的库...这就是 pkgsrc 的用途! @elmarco pkgsrc 起源于 NetBSD,但适用于许多平台。 【参考方案1】:

PKG_CHECK_MODULES 的一个重要问题是它会导致不应该出现的故障。如果用户在/p/a/t/h 中安装libfoo 并使用LDFLAGS=-L/p/a/t/h 调用configure 脚本,则用户有理由期望配置找到libfoo。但是,用户还必须设置PKG_CONFIG_PATH,以便configure 脚本可以找到foo.pc,以便配置成功,在我看来,这已被破坏。如果通过标准机制找不到库,则可以调用AC_CHECK_LIB,然后仅调用PKG_CHECK_MODULES 以避免该问题。另一个问题是PKG_CHECK_MODULES 完全有可能找到一个信息不准确的.pc 文件,从而导致构建失败。在这种情况下,需要在PKG_CHECK_MODULES 之后调用AC_CHECK_LIB

简而言之,要正确使用PKG_CHECK_MODULES,需要先调用AC_CHECK_LIBS,然后有条件调用PKG_CHECK_MODULES,再调用AC_CHECK_LIBS,以验证PKG_CHECK_MODULES找到的信息。维护者所有这些额外的工作只是为了让用户更容易在非标准位置安装他们的库是荒谬的。用户应该设置他们的工具链来通过标准机制查找库。

-- 编辑--

为了澄清,我并不是建议使用鼓励使用 PKG_CHECK_MODULES 的库的包应避免在其配置中使用它。相反,我建议图书馆不要鼓励使用它并停止分发.pc 文件。 .pc 文件试图解决的问题最好在更高级别上解决。自动工具不是包管理系统,这是一个包管理工具应该解决的问题。

【讨论】:

.pc 的一个巧妙之处在于它为您提供了库所需的 CFLAGS,例如 -mms-bitfield。还有静态编译所需的库、冲突的模块以及各种运行时详细信息,例如模块安装的位置等。因此,您关于“依赖标准机制”的建议似乎并未涵盖这些情况。这不仅仅是找到一个库和一个符号。尽管我同意在某些情况下添加更多链接时间检查可能会有所帮助,但这也会稍微减慢配置时间。依靠一分钟。 sys 的正确性类似于依赖一些缓存的结果 所有这些都是说回到您建议的标准机制是不可行的,依靠具有 PKG_CONFIG_LIBDIR 的正确系统使我可以轻松地为各种系统交叉编译而没有任何痛苦。 @elmarco 您可以使用 pkg-config 来填充 CFLAGS、CPPFLAGS、LDFLAGS 和 LIBS,而无需使用 PKG_CHECK_MODULES,因此您可以在不依赖 PKG_CHECK_MODULES 的情况下获得 pkg-config 的所有好处。 (请参阅我对问题的评论) @elmarco 关于“静态编译所需的库”,它们非常有用,但我认为 PKG_CHECK_MODULES 不支持静态链接(pkg-config 的 --static 标志)是对的吗? 您说“使用 pkg-config 在不使用 PKG_CHECK_MODULES 的情况下填充 CFLAGS、CPPFLAGS、LDFLAGS 和 LIBS”,但您的回答是“我建议库停止分发 .pc 文件”。嗯?【参考方案2】:

这里有一篇博文详细介绍了 PKG_CHECK_MODULES 的缺点:

http://tirania.org/blog/archive/2012/Oct-20.html

或者这个***问题:

Using the pkg-config macro PKG_CHECK_MODULES failing

它基本上归结为:如果有人试图运行 autoconf 并且没有安装 pkg-config,它会导致非常无用的错误。这是我今天运行 autoconf && ./configure 时遇到的错误示例:

./configure: line 5283: syntax error near unexpected token `FFMPEG,'
./configure: line 5283: `   PKG_CHECK_MODULES(FFMPEG, libavutil libavformat libavcodec libswscale, HAVE_FFMPEG=yes)'

对于只是试图编译软件包的用户/开发人员来说,这并不意味着“你需要安装 pkg-config”。

如果(如文章建议的那样)您只是直接调用 pkg-config,您会得到更多有用的错误,例如:

AC_SUBST(MONO_LIBS)
AC_SUBST(MONO_CFLAGS)
if pkg-config --atleast-version=2.10 mono; then
   MONO_CFLAGS=`pkg-config --cflags mono`
   MONO_LIBS=`pkg-config --libs mono`
else
   AC_MSG_ERROR(Get your mono from www.go-mono.com)
fi

编辑:Helmut Grohne 在评论中说:

请不要直接调用 pkg-config。这样做会破坏交叉编译。使用 AC_PATH_TOOL(PKG_CONFIG,pkg-config) 或更好的 PKG_PROG_PKG_CONFIG 来发现要使用哪个 $PKG_CONFIG。

我认为这是正确的,你应该听从他的建议,但我没有亲自尝试过。

其他人建议根本不要使用 pkg-config;这是一个单独的问题。

【讨论】:

我很困惑为什么拥有pkg-config 会影响./configure/bin/sh 脚本)的行为方式。安装 pkg-config 后,/bin/sh 是否能够解释 PKG_CHECK_MODULES 之类的内容? @sid-kap 在“autoconf”阶段出现问题 - 如果未安装 pkg-config,则 PKG_CHECK_MODULES 宏不会扩展(因为该宏由 pkg-config 提供) . autoconf 返回成功,但生成无效的配置脚本。问题不在于失败,而是运行配置失败并显示一个非常无用的错误消息,不会让最终用户认为“啊,我需要安装 pkg-config 并重新运行 autoconf”。跨度> 维护者通常负责运行auto(re)conf 来生成configure 脚本。如果需要 pkg-config,那么应该在预构建说明中提及(或放入autogen.sh 作为检查)。 请不要直接拨打pkg-config。这样做会破坏交叉编译。使用AC_PATH_TOOL(PKG_CONFIG,pkg-config) 或更好的PKG_PROG_PKG_CONFIG 来发现要使用哪个$PKG_CONFIG @HelmutGrohne 谢谢!我不知道这可能是一个问题。我已将您的评论添加为对帖子的编辑。

以上是关于PKG_CHECK_MODULES 认为有害吗?的主要内容,如果未能解决你的问题,请参考以下文章

ios 阻止本地通知是不是被认为是有害的?

Response.End() 被认为是有害的吗?

显式的serialVersionUID 被认为是有害的?

Rspec/Capybara 正在加载,循环要求被认为是有害的

PHP忽略从被认为有害的函数返回的引用?

php变量可以安全地保存有害代码吗? [关闭]