【问题标题】:Linking against an external object file (.o) with autoconf使用 autoconf 链接外部对象文件 (.o)
【发布时间】:2026-01-23 13:50:01
【问题描述】:

出于工作目的,我需要链接另一个程序生成并在其文件夹中找到的目标文件,情况是我没有找到有关这种链接的信息。我认为如果我硬编码路径并将name-of-obj.o 放在package_LDADD 变量前面应该可以工作,但情况是我不想那样做。

如果找不到对象,我希望配置失败并告诉用户name-of-obj.o 丢失。

我尝试使用AC_LIBOBJ([name-of-obj.o]),但这会尝试在根目录中找到一个name-of-obj.c 并编译它。

关于这个问题的任何提示或解决方案?

谢谢!

【问题讨论】:

    标签: makefile gnu autotools configure autoconf


    【解决方案1】:

    我需要链接另一个程序生成的目标文件,并且 在其文件夹中找到

    您所描述的是一个非常不寻常的要求,而不是那些 Autotools 旨在干净或轻松处理的要求。特别是,与库相比,Autoconf 没有专门适用于搜索裸对象文件的机制,并且 Automake 在链接时没有特别自动化包含此类对象。尽管如此,这些工具确实有足够的通用功能来做你想做的事。它不会像你想的那样整洁。

    我认为如果我对路径进行硬编码并将 name-of-obj.o 前面的 package_LDADD 变量应该可以工作,但是 情况是我不想那样做。

    我认为这是您要避免的“硬编码路径”部分。将项目添加到适当的LDADD 变量是不可协商的;这是让您的对象包含在链接中的正确方法。

    如果找不到对象,我希望配置失败并告诉 name-of-obj.o 丢失的用户。

    那么,关键似乎是让configure 执行对您的目标文件的搜索。 Autoconf 没有内置的机制来执行这样的搜索,但它只是一个基于宏的 shell-script 生成器,所以你可以在 shell script + Autoconf 中编写这样的搜索,可能是这样的:

    AC_MSG_CHECKING([for name-of-obj.o])
    OTHER_LOCATION=
    for my_dir in
        /some/location/other_program/src
        /another/location/other_program.12345/src
        $srcdir/../relative/location/other_program/src; do
      AS_IF([test -r "${my_dir}/name-of-obj.o"], [
        # optionally, perform any desired test to check that the object is usable
        # ... perhaps one using AC_LINK_IFELSE ...
        # if it passes, then
        OTHER_LOCATION=${my_dir}
        break
      ])
    done
    
    # Check whether the object was in fact discovered, and act appropriately
    AS_IF([test "x${OTHER_LOCATION}" = x], [
      # Not found
      AC_MSG_RESULT([not found])
      AC_MSG_ERROR([Cannot configure without name-of-obj.o])
    ], [
      AC_MSG_RESULT([${OTHER_LOCATION}/name-of-obj.o])
      AC_SUBST([OTHER_LOCATION])
    ])
    

    这是功能性的,但您当然可以进行修饰,例如让包生成器通过命令行参数 (AC_ARG_WITH(...)) 指定要使用的位置。如果您想对多个对象执行此操作,那么您可能希望至少将其中的一部分封装到自定义宏中。

    Automake 方面的参与要少得多。要获取链接的对象,只需将其添加到相应的LDADD 变量中,使用上面创建的输出变量,例如:

    foo_LDADD = $(OTHER_LOCATION)/name-of-obj.o
    

    请注意,如果您只构建一个程序目标,则可以使用通用的LDADD 而不是foo_LDADD,但请注意,默认情况下,这些是替代而不是补充。


    话虽如此,总体而言这是一个坏主意。如果你想链接不属于你的项目的东西,那么你应该从已安装的库中获取它。当然,这可以是一个本地的、定制的库,只要它是一个库,而不是一个裸目标文件,并且它已安装。如果您不想依赖或分发单独的共享库,它可以是静态库。

    另一方面,如果您的项目是较大构建的一部分,那么最好的方法可能是将其集成到该构建中,也许作为子项目。最好还是链接一个库而不是一个裸对象文件,但在子项目上下文中,使用未安装到构建系统的库可能是有意义的。与告诉它在哪里可以找到所需库的命令行参数结合使用,这可以使所需的 Autoconf 代码更加简洁明了。

    【讨论】: