8

我想在安装二进制文件之前使用 automake 处理/修改它们。例如,我想将二进制文件中的符号提取到一个单独的文件和位置(像这样)。另一个示例是收集关键资产的 md5sum 以发布报告。

这是我拥有的简化(但具有代表性)的 Makefile.am:

abc_PROGRAMS = foo
foo_SOURCES = foo.cpp

pqr_PROGRAMS = bar
bar_SOURCES = bar.cpp

ALL_SYMS := $(PROGRAMS:%=%.sym)

sym_DATA = $(ALL_SYMS)

# A convenient target such as "make foo.sym" will trigger this rule:
$(ALL_SYMS): %.sym : %
   ...
   objcopy --preserve-dates --only-keep-debug $< $@
   objcopy --preserve-dates --strip-all --add-gnu-debuglink=$@ $<
   ...

在安装过程中,我尝试了几种方法来挂钩我的脚本,但收效甚微。

  1. 一种可能的方法是使用 install-exec-local:

    install-exec-local: $(ALL_SYMS)
    

    install-exec-local 的问题在于,当我使用:“make install -j”时,install-exec-local 目标与安装并行运行,因此二进制文件 foo 和 bar 被安装到它们各自的目标目录中,甚至当它们被 %.sym 规则修改时,可能会弄乱已安装的文件。但是,如果不使用 -j,则此解决方案有效。我想我是否可以利用使用 -j 的优势。

  2. 另一种可能的方法是使用 install-exec-hook:

    install-exec-hook: $(ALL_SYMS)
    

    install-exec-hook 的问题是程序 foo 和 bar 在我有机会使用 %.sym 规则修改它们之前已经安装。除了 foo 和 bar 安装在不同的位置之外,我没有通用的方法来获取它们的目标位置,同时编写合适的 install-exec-hook 规则。

  3. 另一种可能的方法是定义 STRIP_PROGRAM 或类似的东西,但这并不能很好地工作,因为我认为它不适用于“make install”目标,而只能用于“make install-strip -j”。我没有走这条路,因为我们的构建脚本使用“make install -j”。

  4. 另一种方法是创建在构建时间而不是安装时间运行的构建规则。但是这个真的很麻烦,它在构建目录中创建了很多文件,我想避免它。此外,项目中的新人在添加新程序时可以轻松绕过这些精心调整的精心安排。

    abc_PROGRAMS = foo
    foo : foo.tmp
    foo.sym : foo
    noinst_PROGRAMS = foo.tmp
    foo_tmp_SOURCES = foo.cpp
    
    
    pqr_PROGRAMS = bar
    bar : bar.tmp
    bar.sym : bar
    noinst_PROGRAMS += bar.tmp
    bar_tmp_SOURCES = bar.cpp
    
    sym_DATA = foo.sym bar.sym
    
    foo bar: % : %.tmp
    ...
    cp $@ $<
    objcopy --only-keep-debug $@ $@.sym
    objcopy --strip-all --add-gnu-debuglink=$@.sym $@
    

如果 automake 提供了一个在安装程序之前或在构建程序之后运行的钩子,我会喜欢的。

stackoverflow.com 社区确实对 Internet 上可用的解决方案的质量产生了影响。我相信一定有人遇到过和我类似的问题。我正在等待有关此问题的良好解决方案或行业最佳实践。最后,对于未能使问题更简短或更易于理解,我深表歉意。

4

2 回答 2

3

告诉 automake 在安装之前或链接之后在程序上运行一些命令

“刚刚链接后”部分可以使用libtool'postlink_cmds步骤完成。postlink_cmds记录在案

变量:postlink_cmds

完成链接程序所需的命令。postlink_cmds 在程序链接后立即执行。postlink_cmds 中出现的任何字符串@OUTPUT@ 都会在执行之前替换为创建的可执行文件的名称(即,如果生成了包装器,则不是包装器)。同样,@TOOL_OUTPUT@ 被@OUTPUT@ 的工具链格式替换。通常禁用(即 postlink_cmds 为空)。


下面是configure.ac用于sed修补libtool和创建postlink_cmds之后的 a 的一部分libtool。我们需要它在 Solaris 共享对象上应用软件功能,因为我们通过映射文件设置它们的链接选项-M <mapfile>被剥离(显然libtool保留了几乎所有-M选项)。

虽然libtool有一个postlink_cmds我们不知道如何更传统地设置它。也许有一个AC_XXX地方可以做到这一点。

#############################################################################
## Hack ahead. GNU's libtool does not honor our '-M cryptopp.mapfile' in AM_LDFLAGS
## for the libcryptopp.so recipe. Many thanks to John Martin of Oracle for help wielding
## elfedit. The hw_cap = 0x1800 is SSE2 SSE and its needed for old hardware when new
## instructions are present, like SSE4.1, SSE4.2, CLMUL, AES, RDRAND, RDSEED and SHA.
## TODO: determine if we are allowed to hijack libtool's postlink_cmds function. It
## works well but we may be violating a policy somewhere along the line.

if test "$IS_SUN_OS" -ne "0" && test "$IS_SUN_COMPILER" -ne "0"; then
   if test "$IS_IA32" -ne "0"; then

      echo "Adding postlink script"
      rm -f postlink.sh 2>/dev/null
      echo "echo \"Fixing shared object capabilities\"" >> postlink.sh
      echo "elfedit -e 'cap:hw1 0x1800' .libs/cryptest" >> postlink.sh
      echo "elfedit -e 'cap:hw1 0x1800' .libs/cryptestcwd" >> postlink.sh
      echo "elfedit -e 'cap:hw1 0x1800' .libs/libcryptopp.so.6.0.0" >> postlink.sh
      echo "" >> postlink.sh
      chmod +x postlink.sh

      echo "Adding postlink script to libtool postlink_cmds"
      sed 's|postlink_cmds=""|postlink_cmds="./postlink.sh"|g' libtool > libtool.fixed
      mv libtool.fixed libtool
      chmod +x libtool
   fi
fi

在使用 hack 之前sed,我尝试postlink_cmdsconfigure.ac. 不幸的是,它不起作用,导致postlink_cmds=""生成libtool. 这是不起作用的东西:

if test x"$postlink_cmds" = "x"; then
    postlink_cmds="./postlink.sh"
else
    postlink_cmds="~ ./postlink.sh"
fi

~是由于libtool手册说明:

... 用于命名保存 shell 命令以进行延迟评估的变量的约定是使用后缀 _cmd 需要单行有效的 shell 脚本,而后缀 _cmds 可能会延迟多行 shell 脚本以供以后评估. 按照惯例,_cmds 变量在必要时用 ~ 字符分隔评估单元。

于 2017-11-09T15:59:33.720 回答
2

按照选项 #3 的思路,在这种情况下,您可能会考虑设置其中一个INSTALL变量(INSTALL、INSTALL_DATA、INSTALL_PROGRAM、INSTALL_SCRIPT)并将其指向执行您想要的操作的脚本,并install在最后一步调用实数。

于 2012-10-22T19:54:26.733 回答