openocd+Linaro工具链交叉编译
需求:用bitbake去编译openocd需要openbmc环境,构建起来很不方便,需要把openocd的编译过程从openbmc中分离出来,单独编译其依赖库和标准库,bmc环境中有相关库的so文件,因此我们只关心编译出的openocd二进制可执行文件实现方式:先用bitbake对openocd进行编译,获得openocd_git.bb文件,阅读bb文件依赖库为libusb-compat和libf
需求:用bitbake去编译openocd需要openbmc环境,构建起来很不方便,需要把openocd的编译过程从openbmc中分离出来,单独编译其依赖库和标准库,bmc环境中有相关库的so文件,因此我们只关心编译出的openocd二进制可执行文件
目标架构
用bitbake对openocd进行编译,获得openocd_git.bb文件,阅读bb文件
SUMMARY = "Free and Open On-Chip Debugging, In-System Programming and Boundary-Scan Testing"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
DEPENDS = "libusb-compat libftdi"
RDEPENDS:${PN} = "libusb1"
依赖库为libusb-compat和libftdi,运行时依赖为libusb1
再阅读bitbake编译过程中生成的do_compile log文件,得到在openbmc中bitbake编译openocd时使用的目标架构配置
arm-openbmc-linux-gnueabi-gcc -march=armv7-a -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security
目标架构指定 ARMv7-A 架构,确保生成的代码针对 ARMv7-A 指令集优化(-march=armv7-a)
浮点单元指定使用 VFPv4-D16 浮点单元,支持 16 个双精度寄存器(-mfpu=vfpv4-d16)
浮点ABI使用硬浮点 ABI,直接调用浮点硬件,生成的代码与硬浮点库(如 libc.so)兼容(-mfloat-abi=hard)
启用优化级别 2,平衡性能和编译时间,生成高效代码。
后面的配置是一些安全和调试的选项,具体作用如下:
-fstack-protector-strong
- 作用:启用栈溢出保护(buffer overflow protection),在函数中插入代码检查栈溢出,增强程序安全性。
- 影响:增加少量代码大小和运行时开销(通常微小),提高对栈溢出攻击的防御能力。
- 适用性:常见于嵌入式系统(如 OpenBMC),因为 BMC 固件可能面临安全威胁。
-D_FORTIFY_SOURCE=2
- 作用:启用源代码级别的缓冲区溢出保护,增强标准库函数(如 strcpy, memcpy)的安全检查。
- 影响:可能略微增加运行时检查开销,但显著提高安全性,防止常见漏洞。
- 适用性:Yocto/OpenBMC 默认启用,适合生产环境。
-Wformat -Wformat-security
- 作用:
- -Wformat:启用格式字符串警告,检查 printf 等函数的格式字符串是否安全。
- -Wformat-security:进一步检查格式字符串漏洞(如用户控制的格式字符串)。
- 影响:仅影响编译时,生成警告但不改变代码行为。
- 适用性:增强编译时安全检查,适合严格的开发环境。
-Werror=format-security
- 作用:将格式字符串安全警告升级为错误,强制修复潜在问题。
- 影响:如果代码有格式字符串问题,编译会失败,迫使开发者修复。
- 适用性:适合高质量代码要求(如 OpenBMC)。
从配置来看,-march=armv7-a -mfpu=vfpv4-d16 -mfloat-abi=hard -02,这四个配置足以确保两者的核心架构和优化一致,生成的 OpenOCD 可执行文件在功能上基本相同(支持相同的硬件接口和调试功能)。
bitbake使用yocto配方构建的工具链(arm-openbmc-linux-gnueabi-gcc),由bb文件(gcc_12.2.bb,glibc_2.34.bb)从源码编译而成,sysroot 动态生成,包含所有依赖(如 libusb, libconfuse)。
Linaro工具链交叉编译
我们要将openocd的编译过程分离出来,不能使用bitbake,手动实现交叉编译工具链过于复杂,且维护更新成本较高,因此使用linaro工具链,其中gcc, binutils, glibc等工具已经在目标架构上进行了预编译,解压工具链即可使用,因此实现过程只需要关注openocd依赖库以及本体软件的编译实现。
首先需要下载对应依赖库的tar压缩包并且分别解压到libusb,libcheck,libconfuse,libftdi,libusb-compat-0.1.5文件夹中,对应版本压缩包的下载链接已经贴到博客最后,用cp或者scp传到本地开发环境或者研发服务器中,可进行以下开发。
#!/bin/bash
# build_openocd.sh
# Cross-compile OpenOCD for armv7ahf-vfpv4d16-openbmc-linux-gnueabi on Ubuntu 22.04
set -e
# 配置
# CUSTOM_DIR="/home/lip" # 自定义文件夹路径,替换为实际路径
# 获取 CUSTOM_DIR
if [ -z "$1" ]; then
echo "请输入 CUSTOM_DIR 的路径"
read -r CUSTOM_DIR
if [ -z "$CUSTOM_DIR" ]; then
echo "错误:未提供 CUSTOM_DIR 路径"
exit 1
fi
else
CUSTOM_DIR="$1"
fi
# 验证 CUSTOM_DIR 是否有效
if [ ! -d "$CUSTOM_DIR" ]; then
echo "错误:目录 $CUSTOM_DIR 不存在,请确保路径正确"
exit 1
fi
DEPS_DIR="$CUSTOM_DIR/.openocd_deps"
TOOLCHAIN_DIR="$CUSTOM_DIR/arm-toolchain"
TARGET="arm-linux-gnueabihf"
TOOLCHAIN_URL="https://snapshots.linaro.org/gnu-toolchain/12.2-2022.09-1/arm-linux-gnueabihf/gcc-linaro-12.2.1-2022.09-x86_64_arm-linux-gnueabihf.tar.xz"
TOOLCHAIN_TARBALL="gcc-linaro-12.2.1-2022.09-x86_64_arm-linux-gnueabihf.tar.xz"
echo "验证主机依赖..."
for pkg in autoconf automake libtool pkgconf git make gcc g++ curl texinfo; do
if ! command -v $pkg >/dev/null 2>&1; then
echo "Error: $pkg is not installed."
echo "Installing $pkg..."
sudo apt-get update
sudo apt-get install -y $pkg
if [ "$pkg" = "libtool" ]; then
echo "Additionally installing libtool-bin..."
sudo apt-get install -y libtool-bin
fi
if ! command -v $pkg >/dev/null 2>&1; then
echo "Error: Failed to install $pkg."
exit 1
fi
fi
echo "$pkg found at $(command -v $pkg)"
done
echo "All host dependencies are installed."
# 下载并安装Linaro工具链
echo "Linaro toolchain..."
if [ ! -f "$TOOLCHAIN_DIR/bin/$TARGET-gcc" ]; then
echo "Downloading toolchain..."
curl -L -o "$CUSTOM_DIR/$TOOLCHAIN_TARBALL" "$TOOLCHAIN_URL"
mkdir -p "$TOOLCHAIN_DIR"
tar -xvf "$CUSTOM_DIR/$TOOLCHAIN_TARBALL" -C "$TOOLCHAIN_DIR" --strip-components=1
rm "$CUSTOM_DIR/$TOOLCHAIN_TARBALL"
fi
if [ ! -f "$TOOLCHAIN_DIR/bin/$TARGET-gcc" ]; then
echo "Error: $TARGET-gcc not found in $TOOLCHAIN_DIR/bin"
exit 1
fi
export PATH="$TOOLCHAIN_DIR/bin:$PATH"
export CC="$TARGET-gcc"
export CXX="$TARGET-g++"
export LD="$TARGET-ld"
export AR="$TARGET-ar"
export AS="$TARGET-as"
export RANLIB="$TARGET-ranlib"
export CFLAGS="-march=armv7-a -mfpu=vfpv4-d16 -mfloat-abi=hard -O2 -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security"
export LDFLAGS="-L$DEPS_DIR/usr/lib -L$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/lib"
export DEPS_DIR=$CUSTOM_DIR/.openocd_deps_test
export TOOLCHAIN_DIR=$CUSTOM_DIR/arm-toolchain
$CC --version || { echo "Error: Failed to run $CC"; exit 1; }
echo "Toolchain: $($CC --version)"
echo "Creating directories..."
mkdir -p "$DEPS_DIR/usr/lib" "$DEPS_DIR/usr/include" "$DEPS_DIR/usr/lib/pkgconfig" "$CUSTOM_DIR/openocd-install"
# 编译依赖
echo "正在编译依赖..."
# libusb-v1.0.25
if [ ! -d "$CUSTOM_DIR/libusb1" ]; then
echo "解压 libusb-1.0.25..."
mkdir -p "$CUSTOM_DIR/libusb1"
tar -xjf "$CUSTOM_DIR/libusb-1.0.25.tar.bz2" -C "$CUSTOM_DIR/libusb1" --strip-components=1
fi
if [ ! -f "$DEPS_DIR/usr/lib/libusb-1.0.so" ]; then
echo "Building libusb-1.0..."
cd "$CUSTOM_DIR"
cd libusb1
make clean >/dev/null 2>&1 || true
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig"
export ac_cv_func_malloc_0_nonnull=yes
export ac_cv_func_realloc_0_nonnull=yes
# ./autogen.sh --host="$TARGET" --prefix="$DEPS_DIR/usr" --disable-udev
./configure --host="$TARGET" --prefix="$DEPS_DIR/usr" \
--with-sysroot="$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc" \
CFLAGS="$CFLAGS -I$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/usr/include" \
LDFLAGS="$LDFLAGS" \
--disable-examples-build --disable-tests-build --disable-udev
make
make install
fi
echo "libusb-1.0 found at $DEPS_DIR/usr/lib/libusb-1.0.so"
# libcheck-v0.15.2
if [ ! -d "$CUSTOM_DIR/libcheck1" ]; then
echo "解压 libcheck-0.15.2..."
mkdir -p "$CUSTOM_DIR/libcheck1"
tar -xzf "$CUSTOM_DIR/check-0.15.2.tar.gz" -C "$CUSTOM_DIR/libcheck1" --strip-components=1
fi
if [ ! -f "$DEPS_DIR/usr/lib/libcheck.so" ]; then
cd "$CUSTOM_DIR"
cd libcheck1
make clean >/dev/null 2>&1 || true
# 运行 autoreconf 以重新生成构建系统
autoreconf -i
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig"
./configure --host=arm-linux-gnueabihf --prefix="$DEPS_DIR/usr" \
--with-sysroot="$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc" \
CFLAGS="$CFLAGS -I$DEPS_DIR/usr/include -I$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/usr/include" \
LDFLAGS="$LDFLAGS -L$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/lib"
make
make install
fi
echo "libcheck found at $DEPS_DIR/usr/lib/libcheck.so"
# libconfuse-v3.3
if [ ! -d "$CUSTOM_DIR/libconfuse" ]; then
echo "解压 libconfuse-3.3..."
mkdir -p "$CUSTOM_DIR/libconfuse"
tar -xzf "$CUSTOM_DIR/confuse-3.3.tar.gz" -C "$CUSTOM_DIR/libconfuse" --strip-components=1
fi
if [ ! -f "$DEPS_DIR/usr/lib/libconfuse.so" ]; then
echo "Building libconfuse..."
cd "$CUSTOM_DIR"
cd libconfuse
make clean >/dev/null 2>&1 || true
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig"
export ac_cv_func_malloc_0_nonnull=yes
export ac_cv_func_realloc_0_nonnull=yes
./configure --host="$TARGET" --prefix="$DEPS_DIR/usr" \
--enable-shared --disable-static \
CFLAGS="$CFLAGS -I$DEPS_DIR/usr/include -I$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/usr/include" \
LDFLAGS="$LDFLAGS -L$DEPS_DIR/usr/lib -L$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/lib"
make
make install
fi
echo "libconfuse found at $DEPS_DIR/usr/lib/libconfuse.so"
# libftdi-v1.5
if [ ! -d "$CUSTOM_DIR/libftdi" ]; then
echo "解压 libftdi-1.5..."
mkdir -p "$CUSTOM_DIR/libftdi"
tar -xjf "$CUSTOM_DIR/libftdi1-1.5.tar.bz2" -C "$CUSTOM_DIR/libftdi" --strip-components=1
fi
if [ ! -f "$DEPS_DIR/usr/lib/libftdi1.so" ]; then
echo "Processing libftdi-1.5..."
cd "$CUSTOM_DIR"
rm -rf libftdi-build # 清理旧的构建目录
mkdir -p libftdi-build
cd libftdi-build
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig:$PKG_CONFIG_PATH"
# 验证依赖文件是否存在
ls -l $DEPS_DIR/usr/lib/libusb-1.0.so || { echo "Error: libusb-1.0.so not found"; exit 1; }
ls -l $DEPS_DIR/usr/lib/libconfuse.so || { echo "Error: libconfuse.so not found"; exit 1; }
echo "运行 CMake 配置..."
cmake \
-DCMAKE_TOOLCHAIN_FILE="$CUSTOM_DIR/toolchain-arm-linux-gnueabihf.cmake" \
-DCMAKE_INSTALL_PREFIX=$DEPS_DIR/usr \
-DBUILD_SHARED_LIBS=ON \
-DLIBUSB_LIBRARIES=$DEPS_DIR/usr/lib/libusb-1.0.so \
-DLIBUSB_INCLUDE_DIR=$DEPS_DIR/usr/include/libusb-1.0 \
-DCONFUSE_LIBRARIES=$DEPS_DIR/usr/lib/libconfuse.so \
-DCONFUSE_INCLUDE_DIR=$DEPS_DIR/usr/include \
"$CUSTOM_DIR/libftdi"
if [ $? -ne 0 ]; then
echo "CMake 配置失败,请检查 cmake.log"
cmake \
-DCMAKE_TOOLCHAIN_FILE="$CUSTOM_DIR/toolchain-arm-linux-gnueabihf.cmake" \
-DCMAKE_INSTALL_PREFIX=$DEPS_DIR/usr \
-DBUILD_SHARED_LIBS=ON \
-DLIBUSB_LIBRARIES=$DEPS_DIR/usr/lib/libusb-1.0.so \
-DLIBUSB_INCLUDE_DIR=$DEPS_DIR/usr/include/libusb-1.0 \
-DCONFUSE_LIBRARIES=$DEPS_DIR/usr/lib/libconfuse.so \
-DCONFUSE_INCLUDE_DIR=$DEPS_DIR/usr/include \
"$CUSTOM_DIR/libftdi" > cmake.log 2>&1
exit 1
fi
make
make install
fi
echo "libftdi-1.5 found at $DEPS_DIR/usr/lib/libftdi1.so"
# libusb-compat-v0.1.5
if [ ! -d "$CUSTOM_DIR/libusb-compat" ]; then
echo "解压 libusb-compat-0.1.5..."
mkdir -p "$CUSTOM_DIR/libusb-compat"
tar -xjf "$CUSTOM_DIR/libusb-compat-0.1.5.tar.bz2" -C "$CUSTOM_DIR/libusb-compat" --strip-components=1
fi
if [ ! -f "$DEPS_DIR/usr/lib/libusb.so" ]; then
echo "Building libusb-compat-0.1.5..."
cd "$CUSTOM_DIR"
cd libusb-compat
make clean >/dev/null 2>&1 || true
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig:$PKG_CONFIG_PATH"
./configure --host="$TARGET" --prefix="$DEPS_DIR/usr" \
--enable-shared --disable-static \
CFLAGS="$CFLAGS -I$DEPS_DIR/usr/include -I$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/usr/include" \
LDFLAGS="$LDFLAGS -L$DEPS_DIR/usr/lib -L$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/lib"
make
make install
fi
echo "libusb-compat-0.1.5 found at $DEPS_DIR/usr/lib/libusb.so"
# openocd
if [ ! -f "$CUSTOM_DIR/ybopenocd-install/bin/openocd" ]; then
echo "Building OpenOCD..."
cd "$CUSTOM_DIR/openocd"
make clean >/dev/null 2>&1 || true
export PKG_CONFIG_PATH="$DEPS_DIR/usr/lib/pkgconfig:$PKG_CONFIG_PATH"
./bootstrap
./configure --host="$TARGET" --prefix="$CUSTOM_DIR/openocd-install" \
--with-sysroot="$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc" \
CFLAGS="$CFLAGS -I$DEPS_DIR/usr/include -I$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/usr/include" \
LDFLAGS="$LDFLAGS -L$DEPS_DIR/usr/lib -L$TOOLCHAIN_DIR/arm-linux-gnueabihf/libc/lib" \
--enable-ftdi
make
make install
fi
echo "OpenOCD found at $CUSTOM_DIR/openocd-install/bin/openocd"
在编译libftdi时,cmake工具链文件如下:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 指定交叉编译工具链
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# 指定 sysroot(工具链的根文件系统)
set(CMAKE_SYSROOT $ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc)
# 指定依赖库和头文件的查找路径
set(CMAKE_PREFIX_PATH $ENV{DEPS_DIR}/usr)
set(CMAKE_FIND_ROOT_PATH $ENV{DEPS_DIR}/usr $ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc)
# 确保 CMake 只查找目标系统的库和头文件
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)
# 设置 CFLAGS 和 LDFLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I$ENV{DEPS_DIR}/usr/include -I$ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/usr/include" CACHE STRING "C flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I$ENV{DEPS_DIR}/usr/include -I$ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/usr/include" CACHE STRING "C++ flags")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L$ENV{DEPS_DIR}/usr/lib -L$ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/lib" CACHE STRING "Linker flags")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L$ENV{DEPS_DIR}/usr/lib -L$ENV{TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/lib" CACHE STRING "Shared linker flags")
# 显式声明libconfuse的库和头文件
set(CONFUSE_LIBRARY /home/lip/.openocd_deps/usr/lib/libconfuse.so CACHE PATH "Path to libconfuse")
set(CONFUSE_INCLUDE_DIR /home/lip/.openocd_deps/usr/include CACHE PATH "Path to confuse include directory")
保存在~/toolchain-arm-linux-gnueabihf.cmake中
执行该脚本,编译好的依赖库文件保存在~/.openocd_deps下,openocd可执行文件保存在~/ybopenocd-install/bin中,把该可执行文件复制到bmc中/tmp路径下,相关板卡cfg文件需要被上传到相同路径下,即可在bmc环境下运行调试openocd
版本管理以及下载链接:
Linaro工具链-v12.2.1:
libusb-v1.0.25:
https://github.com/libusb/libusb/releases/download/v1.0.25/libusb-1.0.25.tar.bz2
libcheck-v0.15.2:
https://github.com/libcheck/check/releases/download/0.15.2/check-0.15.2.tar.gz
libconfuse-v3.3:
https://github.com/libconfuse/libconfuse/releases/download/v3.3/confuse-3.3.tar.gz
libftdi-v1.5:
https://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.5.tar.bz2
libusb-compat-v0.1.5
更多推荐
所有评论(0)