解决vcpkg无法交叉编译arm64版本 HDF5 库的问题
问题简述
在 linux x64 下使用交叉编译 arm64
版本的 hdf5
库会遇到一个问题,就是在编译出可执行文件
bin/H5detect
bin/H5make_libsettings
是 arm64
架构的,但是在编译过程中需要使用到他们去生成一些代码文件,导致出错无法编译。
这个错误与是不是使用 vcpkg
编译无关,直接使用 cmake
生成 Makefile
去编译也是一样的。
因为 x64
的机器无法直接运行 arm64
的程序。
这两个程序的调用分别在:
- hdf5/bin/batch/knl_H5detect.sl.in.cmake
# Inputs: Build directory, output file name, executable file name (username/email if available). PROGNAME=H5detect OUTPUT=H5Tinit.c CMD="@HDF5_BINARY_DIR@/bin/${PROGNAME} @HDF5_GENERATED_SOURCE_DIR@/${OUTPUT}" echo "Run $CMD" srun -n 1 $CMD echo "Done running $CMD"
- src/CMakeLists.txt
add_custom_command ( OUTPUT ${HDF5_BINARY_DIR}/H5lib_settings.c ${HDF5_BINARY_DIR}/gen_SRCS.stamp2 COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5make_libsettings> ARGS ${HDF5_BINARY_DIR}/H5lib_settings.c COMMAND ${CMAKE_COMMAND} ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2 DEPENDS H5make_libsettings WORKING_DIRECTORY ${HDF5_BINARY_DIR} )
这个其实是我在使用
vcpkg
编译 gdal 时候发现的问题,如果你不需要 gdal 支持相应的依赖(driver)可以打开vcpkg/ports/gdal/CONTORL
文件,把Build-Depends:
里面的相关项移除掉。
解决办法
这个解决也不难,从上面的代码可以知道,H5make_libsettings
是要在模拟器上运行的,所以这里可以做一点手脚。
先使用 vcpkg
编译了 x64
版本的程序,所以我本地是有 x64
版本的 H5make_libsettings
和 H5detect
,用他们去替换掉编译过程中生成的 arm64
版本即可。
但是 vcpkg
每次都会重新编译,所以必须要在编译过程中替换。所以可以自己写一个 EMULATOR 模拟器来做这件事。
下面的 vcpkg 所在路径请根据实际情况确定。
解决步骤如下:
- 1、写一个
hdf5emulator.sh
脚本文件,内容如下:#!/bin/bash mkdir -p /mnt/build/vcpkg/buildtrees/hdf5/arm64-linux-rel/bin/ cp -pPf /mnt/build/vcpkg/buildtrees/hdf5/x64-linux-rel/bin/H5* /mnt/build/vcpkg/buildtrees/hdf5/arm64-linux-rel/bin/ $@
- 2、修改
vcpkg
内的vim ports/hdf5/portfile.cmake
文件,找到vcpkg_configure_cmake
位置,在OPTIONS
下添加一行,修改后的结果如下:vcpkg_configure_cmake( SOURCE_PATH ${SOURCE_PATH} DISABLE_PARALLEL_CONFIGURE PREFER_NINJA OPTIONS -DCMAKE_CROSSCOMPILING_EMULATOR=/mnt/build/vcpkg/hdf5emulator.sh # 这行是添加的 ${FEATURE_OPTIONS} -DBUILD_TESTING=OFF -DHDF5_BUILD_EXAMPLES=OFF -DHDF5_INSTALL_DATA_DIR=share/hdf5/data -DHDF5_INSTALL_CMAKE_DIR=share -DHDF_PACKAGE_NAMESPACE:STRING=hdf5:: )
按照上面两步进行操作之后,重新编译即可正常生成。
对于是 cmake
生成 Makefile
进行编译的情况,也是大同小异的操作。