在 C/C++ 中自动检测库依赖关系的最佳方法是什么?项目?

发布于 2024-08-08 06:52:54 字数 361 浏览 9 评论 0原文

在 C/C++ 项目中自动检测库依赖关系的最佳方法是什么?

我有一个项目,其中包含机器上的所有依赖项。它构建并运行。现在我想组装一个自动工具构建系统。我正在寻找一种好方法来自动检测所需的所有依赖项,例如使用的头文件和链接所需的库。

图书馆似乎是我最难弄清楚的。我希望能够为列表或其他内容中的每个函数生成 AC_CHECK_LIB 命令。我也许可以在 Perl 中做到这一点,但我必须想象它已经存在于其他地方。

我所知道的是,我可以使用 objdump 和 nm 查看符号,我可以使用这些实用程序找到函数属于哪个库,然后我可以在configure.ac 中手动输入 AC_CHECK_LIB 命令来检查它。在这一点上,自动化会很棒。

谢谢, 陈兹

What is the best way to auto detect library dependencies in a C/C++ project?

I have a project where I have all the dependencies on the machine. It builds and runs. Now I want to put together a autotools build system. I am looking for a good way to auto detect all the dependencies needed such as header files used and libraries needed for linking.

The library bit seems to be the hardest for me to figure out. I'd like to be able to say, generate AC_CHECK_LIB commands for every function in a list or something. I could probably do this in Perl, but I've got to imagine it already exists elsewhere.

What I know is that I can view symbols with objdump and nm, I can find what library a function belongs to with these utilties, then I can manually enter an AC_CHECK_LIB command in my configure.ac to check for it. Automation would be awesome at this point.

Thanks,
Chenz

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧时模样 2024-08-15 06:52:54

这种详尽的测试(即每个功能)是不必要的。更不用说它很难维护并且需要一段时间才能运行。

测试您知道值得测试的功能。如果您只是测试库是否存在,请选择一个常用函数在测试中使用。如果您想确保某些功能仅在较新版本中可用,请使用仅在这些较新版本中找到的功能进行测试。

That sort of exhaustive testing (i.e., every function) is unnecessary. Not to mention that it would be hard to maintain and take a while to run.

Test for features that you know warrant a test. If you're just testing for the existence of a library, pick a commonly used function to use in your test. If you want to make sure some feature only in newer vesions is available, test using a function only found in those newer versions.

凤舞天涯 2024-08-15 06:52:54

我现在也面临着类似的挑战。 autoconf 对于 C++ 技巧来说确实不太方便,但它有基本的砖块来构建顶部的功能。看了这里和那里后我的建议:

  • 阅读这篇文章 ,它会给你带来新鲜的想法
  • 查看 autoconf 宏的来源 ac-archive (它已包含在 Debian 中,因此您可以按原样使用它)
  • 我个人编写了简单的帮助程序,它是从 AC_CHECK_LIBAX_CXX_CHECK_LIB。是的,您需要编写一个小型测试程序,但这允许您测试类型、类(sizeof 可能有效,但构造函数呢?)、内联函数(您不能这样做)在链接器的帮助下)和外部函数(你不能用nm来做到这一点)。

来自 aclocal.m4

# SYNOPSIS
#
# AX_TRY_LINK(library, includes, function-body [, action-if-true [, action-if-false]])
#
# DESCRIPTION
#
# This function is a wrapper around AC_ARG_WITH, which adds -I"value" to CPPFLAGS.
# "--with-" variable is initialized to default value, if it is passed.
#
AC_DEFUN([AX_TRY_LINK], [
    dnl Below logic is a workaround for the limitation, that variables may not allow
    dnl symbols like "+" or "-". See AC_CHECK_LIB source comments for more information.
    m4_ifval([$4], , [AH_CHECK_LIB([$1])])
    AS_LITERAL_IF([$1],
        [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2])],
        [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1''_$2])])

    AC_CACHE_CHECK([for -l$1], [ac_Lib], [
        dnl Save the current state
        AC_LANG_SAVE
        AC_LANG_CPLUSPLUS
        ax_try_link_save_LIBS=$LIBS
        LIBS="-l$1 $LIBS"

        AC_TRY_LINK([$2], [$3], [AS_VAR_SET([ac_Lib], [yes])], [AS_VAR_SET([ac_Lib], [no])])

        dnl Restore the state to original regardless to the result
        LIBS=$ax_try_link_save_LIBS
        AC_LANG_RESTORE
    ])

    dnl If the variable is set, we define a constant and push library to LIBS by default or execute $4, otherwise execute $5.
    AS_VAR_IF([ac_Lib], [yes],
        [m4_default([$4], [
            AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1))
            dnl Do not prepend a library, if it is already in the list:
            (echo $LIBS | grep -q -- "-l$1 ") || LIBS="-l$1 $LIBS"
        ])],
        [$5]
    )
    AS_VAR_POPDEF([ac_Lib])
]) # AX_ARG_WITH

现在在 configure.ac 中:

AC_INIT([ABC], [1.2.3])
AC_LANG([C++])
AC_PROG_CXX
AC_CXX_HAVE_STL

if test "x${ac_cv_cxx_have_stl}" != "xyes"; then
    AC_MSG_ERROR([STL was not found; make sure you have installed libstdc++-dev])
fi

...

dnl openbabel library

sr_openbabel_lib=yes

AC_CHECK_HEADERS([openbabel/mol.h openbabel/obconversion.h openbabel/builder.h], [], [sr_openbabel_lib=no])
AX_TRY_LINK([openbabel], [
    #include <openbabel/mol.h>
    #include <openbabel/obconversion.h>
    #include <openbabel/builder.h>
], [
    OpenBabel::OBAtom atom;
    OpenBabel::OBMol mol;
    OpenBabel::OBConversion conversion;

    atom.IsHeteroatom();
    atom.IsCarbon();

    mol.NumAtoms();
    mol.NumBonds();
    mol.NumRotors();
    mol.GetAtom(0);

    conversion.ReadString(&mol, "");
    conversion.WriteString(&mol, false);
], [], [sr_openbabel_lib=no])

if test ${sr_openbabel_lib} != yes; then
    AC_MSG_ERROR([openbabel headers or library was not found (use --with-openbabel to define custom header location)])
fi

I had a similar challenge now. autoconf is really not so handy for C++ tricks, but it has basic bricks to build the functionality on the top. My suggestions after looking here and there:

  • Read this article, it will bring you fresh ideas
  • Look at the sources for autoconf macros at ac-archive (it is included into Debian, so you can use it as is)
  • I personally have written simple helper, which is copied from AC_CHECK_LIB and AX_CXX_CHECK_LIB. Yes, you need to write a mini-test-program, but this allows you to test types, classes (sizeof might work, but what about constructors?), inline functions (this you can't do with help of linker) and external functions (you can't do it with nm).

From aclocal.m4:

# SYNOPSIS
#
# AX_TRY_LINK(library, includes, function-body [, action-if-true [, action-if-false]])
#
# DESCRIPTION
#
# This function is a wrapper around AC_ARG_WITH, which adds -I"value" to CPPFLAGS.
# "--with-" variable is initialized to default value, if it is passed.
#
AC_DEFUN([AX_TRY_LINK], [
    dnl Below logic is a workaround for the limitation, that variables may not allow
    dnl symbols like "+" or "-". See AC_CHECK_LIB source comments for more information.
    m4_ifval([$4], , [AH_CHECK_LIB([$1])])
    AS_LITERAL_IF([$1],
        [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2])],
        [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1''_$2])])

    AC_CACHE_CHECK([for -l$1], [ac_Lib], [
        dnl Save the current state
        AC_LANG_SAVE
        AC_LANG_CPLUSPLUS
        ax_try_link_save_LIBS=$LIBS
        LIBS="-l$1 $LIBS"

        AC_TRY_LINK([$2], [$3], [AS_VAR_SET([ac_Lib], [yes])], [AS_VAR_SET([ac_Lib], [no])])

        dnl Restore the state to original regardless to the result
        LIBS=$ax_try_link_save_LIBS
        AC_LANG_RESTORE
    ])

    dnl If the variable is set, we define a constant and push library to LIBS by default or execute $4, otherwise execute $5.
    AS_VAR_IF([ac_Lib], [yes],
        [m4_default([$4], [
            AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1))
            dnl Do not prepend a library, if it is already in the list:
            (echo $LIBS | grep -q -- "-l$1 ") || LIBS="-l$1 $LIBS"
        ])],
        [$5]
    )
    AS_VAR_POPDEF([ac_Lib])
]) # AX_ARG_WITH

Now in configure.ac:

AC_INIT([ABC], [1.2.3])
AC_LANG([C++])
AC_PROG_CXX
AC_CXX_HAVE_STL

if test "x${ac_cv_cxx_have_stl}" != "xyes"; then
    AC_MSG_ERROR([STL was not found; make sure you have installed libstdc++-dev])
fi

...

dnl openbabel library

sr_openbabel_lib=yes

AC_CHECK_HEADERS([openbabel/mol.h openbabel/obconversion.h openbabel/builder.h], [], [sr_openbabel_lib=no])
AX_TRY_LINK([openbabel], [
    #include <openbabel/mol.h>
    #include <openbabel/obconversion.h>
    #include <openbabel/builder.h>
], [
    OpenBabel::OBAtom atom;
    OpenBabel::OBMol mol;
    OpenBabel::OBConversion conversion;

    atom.IsHeteroatom();
    atom.IsCarbon();

    mol.NumAtoms();
    mol.NumBonds();
    mol.NumRotors();
    mol.GetAtom(0);

    conversion.ReadString(&mol, "");
    conversion.WriteString(&mol, false);
], [], [sr_openbabel_lib=no])

if test ${sr_openbabel_lib} != yes; then
    AC_MSG_ERROR([openbabel headers or library was not found (use --with-openbabel to define custom header location)])
fi
卸妝后依然美 2024-08-15 06:52:54

在 Windows 上,我使用 Dependency Walker 来完成类似的事情。它的输出很详细,但通常会显示可执行文件所需的每个库。

我不知道 Linux 或 Mac 上有类似的东西,但我确信一定有东西存在。

On Windows I've used Dependency Walker for stuff like that. Its output is verbose, but it will generally show you every library that is required by the executable.

I don't know of anything like that for linux or mac, but I'm sure something has to exist.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文