archlinux环境下交叉编译的问题
在给rockchip mpp项目做交叉编译时,我使用了如下交叉编译配置文件:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
if(NOT DEFINED TOOLCHAIN_TRIPLE)
set(TOOLCHAIN_TRIPLE aarch64-linux-gnu)
endif()
if(NOT DEFINED TOOLCHAIN_PREFIX)
set(TOOLCHAIN_PREFIX /usr/bin/${TOOLCHAIN_TRIPLE}-)
endif()
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}ranlib)
set(CMAKE_STRIP ${TOOLCHAIN_PREFIX}strip)
set(CMAKE_NM ${TOOLCHAIN_PREFIX}nm)
if((NOT DEFINED CMAKE_SYSROOT OR CMAKE_SYSROOT STREQUAL "") AND DEFINED SYSROOT AND NOT SYSROOT STREQUAL "")
set(CMAKE_SYSROOT ${SYSROOT})
endif()
if(NOT DEFINED CMAKE_SYSROOT OR CMAKE_SYSROOT STREQUAL "")
message(FATAL_ERROR "Please set CMAKE_SYSROOT (or SYSROOT) for cross compile")
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_SYSROOT_COMPILE ${CMAKE_SYSROOT})
set(CMAKE_SYSROOT_LINK ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
get_filename_component(_toolchain_dir "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
set(_extra_ldflags "")
foreach(_dir IN LISTS _sysroot_link_dirs)
if(EXISTS "${_dir}")
string(APPEND _extra_ldflags " -L${_dir} -Wl,-rpath-link,${_dir}")
endif()
endforeach()
set(CMAKE_C_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}")
set(CMAKE_CXX_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}")
set(CMAKE_ASM_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}")
set(CMAKE_EXE_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}${_extra_ldflags}")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}${_extra_ldflags}")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}${_extra_ldflags}")
set(ENV{PKG_CONFIG_ALLOW_CROSS} 1)
set(ENV{PKG_CONFIG_DIR} "")
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/${TOOLCHAIN_TRIPLE}/pkgconfig:${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
然后使用make编译,但是在编译时一直会提示:
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: skipping incompatible /lib/libc.so.6 when searching for /lib/libc.so.6
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: cannot find /lib/libc.so.6: file in wrong format
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: skipping incompatible /lib/libc.so.6 when searching for /lib/libc.so.6
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: skipping incompatible /lib/libc_nonshared.a when searching for /lib/libc_nonshared.a
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: cannot find /lib/libc_nonshared.a: file in wrong format
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: skipping incompatible /lib/libc_nonshared.a when searching for /lib/libc_nonshared.a
/usr/lib/gcc/aarch64-linux-gnu/15.1.0/../../../../aarch64-linux-gnu/bin/ld: cannot find /lib/ld-linux-aarch64.so.1: No such file or directory
然后使用gpt 5.3 codex帮我修改了一个下午,但是一直没有办法找到libc,然后在archlinux论坛搜到了这一篇文章:
FS#70688 - [aarch64-linux-gnu-gcc] Can't link a simple C program using custom --sysroot
其中Chia-I Wu (olv)用户提到了,archlinux交叉编译时如果sysroot使用 /usr/aarch64-linux-gnu之外的路径会有问题,于是我修改cmake命令中定义的sysroot到/usr/aarch64-linux-gnu(-DCMAKE_SYSROOT=/usr/aarch64-linux-gnu/)后,重新编译,编译通过。
那么可能的原因?
我运行了以下命令:
>aarch64-linux-gnu-gcc --print-sysroot
/usr/aarch64-linux-gnu
>gcc --print-sysroot
也就是说aarch64-linux-gnu-gcc是默认指定了sysroot的而gcc没有。按照GPT的说法,编译时可能会使用相对路径(相对于内置的sysroot),如果使用其他sysroot就会导致问题。
所以最佳的解决办法?
我认为直接使用系统aarch64-linux-gnu-gcc的sysroot不是一个好办法,因为这个root自带的库不多,而且很难用包管理器安装新的库,如果指定其他的sysroot则会向我这样随机出现问题。
所以感觉最好还是用docker容器,拉取一个ubuntu的镜像用于开发,然后所有的交叉编译开发都使用这个容器,所有东西都在容器内。这样也能方便将工作流移植到github/gitlab等托管网站的ci/cd流程。