针对OpenWRT的CMake/Linker交叉编译

CMake/Linker cross compile for OpenWRT

本文关键字:Linker 交叉编译 CMake OpenWRT 针对      更新时间:2023-10-16

不幸的是,由于链接问题,我暂停了在OpenWRT下移植我的一个软件,但为了深入了解上述问题,我需要简要地向您介绍我的软件的一些细节。

它由三个模块组成:LIB-1、LIB-2和APP。

我正在使用Netbeans/C++和CMake在LUbuntu下开发它。我是CMake的交叉编译(我成功地遵循了本指南http://www.vtk.org/Wiki/CMake_Cross_Com…chain_file)和一个我已经通过最新的官方BUILDROOT工具构建了一个工具链和一个目标Generic-x86 OpenWRT映像(它在VirtualBox下像魅力一样工作)。

我将CMAKE_LIBRARY_OUTPUT_DIRECTORY和CMAKE_RUNTIME_OUTPUT_DIRECT设置为一个公用文件夹(${CMAKE_BINARY_DIR}/bin),以便将所有二进制文件都放在同一文件夹中。

现在,我为LUbuntu构建了项目,在ouput文件夹中,我找到了LIB-1.so、LIB-2.so和APP,正如预期的那样。然后我在APP上执行"ldd",我看到它像预期的那样引用了LIB-1.so和LIB-2.so。通过详细的CMake输出,我还看到CMake设置(如预期)指向"${CMake_BINARY_DIR}/bin"的RPATH。

现在进入问题细节。。。

我为OpenWRT构建了项目,在输出文件夹中,我找到了所有这三个文件,正如预期的那样。然后我执行ldd和objdump-x,我看到APP链接到/bin/LIB-1.so和/bin/LIB-2.so'(文件名加上相对路径前缀!!)。另一个区别是CMake(我不知道为什么)没有在链接命令行上添加RPATH!

为了让APP链接到两个库,而不使用相对的"/bin'路径,我必须将两个SO文件放在APP链接文件夹中,并手动运行链接器剥离'/bin/"前缀,并添加"-Wl,-rpath,${CMAKE_BINARY_DIR}/bin"。

有人能解释一下吗:

1) 为什么CMake使用不同的命令行参数链接两个平台?

2) 如何链接CMake避免嵌入相对。SO路径?

3) 如果没有读者使用CMake,有人能告诉我是否存在G++链接器的额外参数,以从引用的LIB中剥离相对路径吗?

非常感谢!

目前我找到了一个解决方法。

我创建了一个类似这样的bash脚本(openwrt-fix-libs):

#!/bin/bash
TARGET_NAME=$1
OUTPUT_DIR=$2
# Prologue
ECHO_PREFIX=[----] 
echo "$ECHO_PREFIX Fixing OpenWRT library imports for "$TARGET_NAME"..."
# Dependencies copy
echo "$ECHO_PREFIX Copying libraries locally from "$OUTPUT_DIR"...";
cp $OUTPUT_DIR/*.so .
if [ $? != 0 ]; then
  exit 1
fi
# Link command hacking
LINK_COMMAND=./CMakeFiles/$TARGET_NAME.dir/link.txt
echo "$ECHO_PREFIX Hacking link command at "$LINK_COMMAND"..." 
LINK_COMMAND=$(cat $LINK_COMMAND | sed -e 's/../bin///g')
#echo "$ECHO_PREFIX <$LINK_COMMAND>"
if [ $? != 0 ]; then
  exit 1
fi
# Re-linking
echo "$ECHO_PREFIX Re-linking...";
$LINK_COMMAND
if [ $? != 0 ]; then
  exit 1
fi
# Update rebuilt binary
echo "$ECHO_PREFIX Updating "$TARGET_NAME" binary..."
cp *$TARGET_NAME* ${OUTPUT_DIR}
if [ $? != 0 ]; then
  exit 1
fi
# Epilogue
echo "$ECHO_PREFIX Libraries imports successfully fixed."

然后,我在我需要的任何模块的CMakeLists.txt文件中添加了这个自定义命令:

if (_PLATFORM STREQUAL "OPENWRT")
  add_custom_command(
    TARGET             ${_TARGET_NAME}
    POST_BUILD COMMAND ${_GLOBAL_SCRIPTS_DIR}/openwrt-fix-libs ${_TARGET_NAME} ${_GLOBAL_OUTPUT_DIR}
  )
endif (_PLATFORM STREQUAL "OPENWRT")

其中_PLATFORM是我为OpenWRT编译时在命令行上设置的符号,_GLOBAL_SCRIPTS_DIR为我的项目脚本文件夹,_GLOBAL_OUTPUT_DIR然后bin位于CMake构建根目录中。

我希望它对你也有用。