- 第 1 步. 建立工作空间目录
- 第 2 步. 建立构建环境
- 安装依赖包
- 安装 CMake
- 从源码构建 alsa-lib 和 alsa-utils
- 第 3 步. 从源码构建工具链
- crosstool-ng
- 工具链
- 附加的头文件
- 第 4 步. 构建并签名固件二进制文件
- 重新配置并从头构建
- 增量构建
- 固件构建输出
- 第 5 步. 构建拓扑和工具
- 从头开始一步重新构建
- 增量构建
- 拓扑和工具构建结果
- 第 6 步. 构建 Linux 内核
你可以在目标机器或 VM 上启动并测试 Sound Open Firmware。当前支持的目标 Intel 平台包括:Bay Trail,Cherry Trail,Haswell,Broadwell,Apollo Lake,Cannon Lake,Ice Lake,Jasper Lake,和 Tiger Lake。
SOF 也支持 NXP i.MX8/i.MX8X/i.MX8M 平台。
下面的步骤描述了如何在 Ubuntu 16.04,18.04,18.10,和 20.04,及 Fedora 36 上安装 SOF 开发环境。这些步骤应该只需要少量修改或不需要修改,即可用在 Ubuntu 19.04,19.10 和其它 Linux 发行版上。
注意
从源码构建工具链可能需要花费几个小时。我们建议你使用 Docker 构建 SOF。更多信息,请参考 用 Docker 构建 SOF。
第 1 步. 建立工作空间目录
设置环境变量 $SOF_WORKSPACE
指向保存所有 SOF 相关工作的目录。
下面的代码示例假设 $SOF_WORKSPACE
是最顶层的工作目录。需要在相同的目录层级克隆所有的 git 仓库,因为一些默认的配置文件使用 ../sof/
这样的相对位置引用其它仓库。
请确保 $SOF_WORKSPACE
目录在构建工具链时,具有充足的磁盘空间。每个工具链大概需要 15GB 的磁盘空间。工具链构建完成后,你可以回收一些磁盘空间。
SOF_WORKSPACE=$HOME/data/work_sof
mkdir -p "$SOF_WORKSPACE"
第 2 步. 建立构建环境
安装依赖包
注意
这份指南使用了 Ubuntu/Fedora 作为示例,但任何现代的 Linux 发行版都可以用于 SOF 开发。
由于 Linux 发行版中持续的更新默认包含的软件包,对于一些可能缺失的工具和软件包,SOF 文档中可能没有包含明确的说明。遇到这种缺失的依赖时,你可以参考你的 Linux 发行版的文档来了解如何安装它们。
- Fedora (在 v36 版上做了测试,近期的其它版本应该也可以很好的工作):
sudo dnf group install "Development Tools" "C Development Tools and Libraries"
sudo dnf install ncurses-devel gtk3-devel gettext-devel texinfo help2man \
glibc-static libstdc++-static openssl-devel tree
- Ubuntu 20.04:
sudo apt install build-essential git autoconf flex bison texinfo help2man \
gawk libtool-bin libncurses5 libncurses5-dev libssl-dev libgtk-3-dev \
tree ninja-build gettext libasound2-dev
- Ubuntu 18.10:
sudo apt-get install build-essential git libgtk-3-dev libsdl1.2-dev \
libspice-protocol-dev libspice-server-dev libusb-1.0-0-dev \
libusbredirhost-dev libtool-bin acpica-tools valgrind texinfo \
virt-manager qemu-kvm libvirt-daemon-system libvirt-clients virtinst \
libfdt-dev libssl-dev pkg-config help2man gawk libncurses5 \
libncurses5-dev
- Ubuntu 16.04 和 18.04:
sudo apt-get install build-essential git libgtk-3-dev libsdl1.2-dev \
libspice-protocol-dev libspice-server-dev libusb-1.0-0-dev \
libusbredirhost-dev libtool-bin iasl valgrind texinfo virt-manager \
qemu-kvm libvirt-bin virtinst libfdt-dev libssl-dev pkg-config help2man \
gawk libncurses5 libncurses5-dev
如果你正在使用 Ubuntu 16.04,则必须将 gcc 的版本更新到 gcc 7.3+,以便于构建 Advanced Linux Sound Architecture (ALSA)。
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-7 g++-7
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 --slave /usr/bin/g++ g++ /usr/bin/g++-7
安装 CMake
如果你在使用 Ubuntu 18.04+ 或 Fedora,你可以使用 apt/dnf 安装 CMake,Ubuntu:
sudo apt-get install cmake
Fedora:
sudo dnf install cmake
对于 Ubuntu 16.04 等系统,apt 中的 CMake 版本已经太老了,必须从源码等方式安装 CMake。可以参考这份指南:https://cmake.org/install/。如果要从二进制安装包安装 CMake,首先在 https://cmake.org/download/ 下载对应操作系统和 CPU 架构的二进制安装包,如 x86-64 CPU 架构,Linux 操作系统,3.28.0 版的 CMake,cmake-3.28.0-linux-x86_64.sh,然后执行这个脚本安装:
$ wget https://github.com/Kitware/CMake/releases/download/v3.28.0/cmake-3.28.0-linux-x86_64.sh
$ chmod a+x cmake-3.28.0-linux-x86_64.sh
$ ./cmake-3.28.0-linux-x86_64.sh --help
Usage: ./cmake-3.28.0-linux-x86_64.sh [options]
Options: [defaults in brackets after descriptions]
--help print this message
--version print cmake installer version
--prefix=dir directory in which to install
--include-subdir include the cmake-3.28.0-linux-x86_64 subdirectory
--exclude-subdir exclude the cmake-3.28.0-linux-x86_64 subdirectory
--skip-license accept license
$ ./cmake-3.28.0-linux-x86_64.sh --prefix=$HOME/.local
从源码构建 alsa-lib 和 alsa-utils
这个项目需要 https://git.alsa-project.org/?p=alsa-lib.git 和 https://git.alsa-project.org/?p=alsa-utils.git 的一些新特性,因此需要从源码构建最新的 ALSA。
警告
在系统范围内安装 alsa-lib 可能会破坏一些音频应用。仅在你知道你在做什么时才这样做。我们建议你在本地目录 (
$HOME
目录下) 安装或使用 Docker (请参考 用 Docker 构建 SOF)。
cd "$SOF_WORKSPACE"
git clone git://git.alsa-project.org/alsa-lib
cd alsa-lib
# To install alsa-lib locally
./gitcompile --prefix=$HOME/.local
make install
如果要在系统范围内安装 alsa-lib,则把上面执行的 ./gitcompile --prefix=$HOME/.local
命令替换为 ./gitcompile
,同时在执行 make install
前加上 sudo
,以便获得根文件系统的写权限:
# To install alsa-lib systemwide
./gitcompile
sudo make install
(可选的) 如果要启用 alsabat 的频率分析,则在配置 alsa-utils 之前安装 FFT 库,Ubuntu:
sudo apt-get install libfftw3-dev libfftw3-doc
Fedora:
sudo dnf install fftw3-devel
克隆,构建,并安装 alsa-utils。
cd "$SOF_WORKSPACE"
git clone git://git.alsa-project.org/alsa-utils
cd alsa-utils
# To install alsa-utils locally
./gitcompile --prefix=$HOME/.local \
--with-alsa-inc-prefix=$HOME/.local/include \
--with-alsa-prefix=$HOME/.local/lib \
--with-systemdsystemunitdir=$HOME/.local/lib/systemd \
--with-udev-rules-dir=$HOME/.local/lib/udev
make install
如果要在系统范围内安装 alsa-utils,则把上面执行的 ./gitcompile --prefix=$HOME/.local . . .
命令替换为 ./gitcompile
,同时在执行 make install
前加上 sudo
以便获得根文件系统的写权限:
# To install alsa-lib systemwide
./gitcompile
sudo make install
如果你遇到了 alsa-lib 的链接错误,则可以加个 libdir
参数重新构建它。
cd ../alsa-lib
./gitcompile --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu/
sudo make install
cd ../alsa-utils
./gitcompile --prefix=/usr --with-curses=ncurses --disable-xmlto --disable-bat
sudo make install
注意
如果
gitcompile
脚本不工作,则可以参考 INSTALL 文件手动构建。
创建或给 LD_LIBRARY_PATH
环境变量附加内容。
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH
第 3 步. 从源码构建工具链
通过 crosstool-ng 为 Intel Bay Trail,Cherry Trail,Haswell,Broadwell,Apollo Lake,Cannon Lake,Ice Lake,Jasper Lake,Tiger Lake 平台和 NXP i.MX8/i.MX8X/i.MX8M 平台构建 xtensa 交叉编译工具链。构建工具链可能需要大约一个小时,但只需要执行一次,且它不需要依赖 Docker 镜像。
更多信息请参考 https://crosstool-ng.github.io/。
crosstool-ng
克隆这些 git 仓库,并分别切换到 sof-gcc10.2
和 sof-gcc10x
分支。
cd "$SOF_WORKSPACE"
git clone https://github.com/thesofproject/xtensa-overlay
git clone https://github.com/thesofproject/crosstool-ng
git -C xtensa-overlay/ checkout sof-gcc10.2
git -C crosstool-ng/ checkout sof-gcc10x
构建 crosstool-ng 并把它安装到它自己的源码目录。
cd crosstool-ng/
./bootstrap
./configure --prefix=$(pwd)
make
make install
工具链
crosstool-ng 根目录下有许多配置文件,如:
crosstool-ng$ ls config-*gcc10.2*
config-acp_6_3-gcc10.2-gdb9 config-imx8m-gcc10.2-gdb9 config-mt8195-gcc10.2-gdb9
config-apl-gcc10.2-gdb8.3 config-imx8ulp-gcc10.2-gdb9 config-rmb-gcc10.2-gdb9
config-apl-gcc10.2-gdb9 config-imx-gcc10.2-gdb9 config-rn-gcc10.2-gdb9
config-byt-gcc10.2-gdb9 config-lx7hifi4-gcc10.2-gdb9 config-vangogh-gcc10.2-gdb9
config-cnl-gcc10.2-gdb9 config-mt8186-gcc10.2-gdb9
config-hsw-gcc10.2-gdb9 config-mt8188-gcc10.2-gdb9
这些配置文件中的每一个都引用 ../xtensa-overlay/
下的文件,并指向不同的 ./builds/xtensa-*-elf
子目录。将想要构建的目标平台的配置文件拷贝到 .config
,并为目标平台构建交叉编译器。注意,./ct-ng build
需要网络连接来下载 gcc 组件。其它步骤最多需要几分钟,依赖于你的网络连接和系统性能,构建所有的工具链可能需要大约一个小时。
通过如下脚本为部分目标平台构建工具链:
#!/usr/bin/bash
unset LD_LIBRARY_PATH
# byt = Bay Trail / Cherry Trail
# hsw = Haswell/Broadwell
# apl = Apollo Lake
# cnl = Cannon Lake, Ice Lake, Jasper Lake, and Tiger Lake
# imx = i.MX8/i.MX8X
# imx8m = i.MX8M
SOF_WORKSPACE=$HOME/data/work_sof
cd "${SOF_WORKSPACE}"/crosstool-ng
# Omit the toolchains you don't want to save (a lot of) time
time for i in byt hsw apl cnl imx imx8m; do
cp config-$i-gcc10.2-gdb9 .config &&
time ./ct-ng build || break
done
具体的目标平台在 for
语句中指定。替换上面的 for
语句构建所有的工具链:
# ... or just build all toolchains
time for i in config*gcc10.2-gdb9; do
cp "$i" .config && time ./ct-ng build || break
done
./ct-ng
是一个 Linux 内核风格的 Makefile;因此下面的示例命令可用于修复一些过时的 config-*-gcc10.2-gdb9
文件,或者从中寻找缺失的默认值:
./ct-ng help
cp config-apl-gcc10.2-gdb9 .config
./ct-ng oldconfig V=1
diff -u config-apl-gcc10.2-gdb9 .config
./ct-ng
命令在执行之前,需要先 unset 环境变量 LD_LIBRARY_PATH,否则报如下错误:
~/data/work_sof/crosstool-ng$ ./ct-ng build
[INFO ] Performing some trivial sanity checks
[ERROR] Don't set LD_LIBRARY_PATH. It screws up the build.
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_Abort[scripts/functions@487]
[ERROR] >> called from: CT_TestAndAbort[scripts/functions@507]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@58]
[ERROR] >>
[ERROR] >> For more info on this error, look at the file: 'build.log'
[ERROR] >> There is a list of known issues, some with workarounds, in:
[ERROR] >> https://crosstool-ng.github.io/docs/known-issues/
[ERROR] >>
[ERROR] >> NOTE: Your configuration includes features marked EXPERIMENTAL.
[ERROR] >> Before submitting a bug report, try to reproduce it without enabling
[ERROR] >> any experimental features. Otherwise, you'll need to debug it
[ERROR] >> and present an explanation why it is a bug in crosstool-NG - or
[ERROR] >> preferably, a fix.
[ERROR] >>
[ERROR] >> NOTE: You configuration uses non-default patch sets. Please
[ERROR] >> select 'bundled' as the set of patches applied and attempt
[ERROR] >> to reproduce this issue. Issues reported with other patch
[ERROR] >> set selections (none, local, bundled+local) are going to be
[ERROR] >> closed without explanation.
[ERROR] >>
[ERROR] >> If you feel this is a bug in crosstool-NG, report it at:
[ERROR] >> https://github.com/crosstool-ng/crosstool-ng/issues/
[ERROR] >>
[ERROR] >> Make sure your report includes all the information pertinent to this issue.
[ERROR] >> Read the bug reporting guidelines here:
[ERROR] >> http://crosstool-ng.github.io/support/
[ERROR]
[ERROR] (elapsed: 28505387:07.64)
[00:00] / make: *** [ct-ng:261:build] 错误 1
在 $SOF_WORKSPACE
中创建各个工具链的符号链接,以在期望的位置安装它们:
ls builds/
# xtensa-apl-elf xtensa-byt-elf xtensa-cnl-elf xtensa-hsw-elf xtensa-imx-elf xtensa-imx8m-elf
cd "$SOF_WORKSPACE"
for i in crosstool-ng/builds/xtensa-*; do ln -s "$i"; done
移除临时的构建文件 (每个工具链大约 7GB):
rm -rf $SOF_WORKSPACE/crosstool-ng/.build
注意
Haswell 和 Broadwell 使用相同的工具链:xtensa-hsw-elf
Bay Trail 和 Cherry Trail 使用相同的工具链:xtensa-byt-elf
Cannon Lake,Ice Lake,Jasper Lake 和 Tiger Lake 使用相同的工具链:xtensa-cnl-elf
i.MX8 和 i.MX8X 使用相同的工具链:xtensa-imx-elf
附加的头文件
为了获得一些必须的头文件,克隆如下的 newlib 仓库,并切换到 xtensa 分支:
cd "$SOF_WORKSPACE"
git clone https://github.com/jcmvbkbc/newlib-xtensa
cd newlib-xtensa
git checkout -b xtensa origin/xtensa
newlib 是 SOF 使用的标准 C 库实现。临时地将工具链的路径添加进 PATH 环境变量。当使用下一节描述的高级的 “每日” 构建脚本时,这不是必须的。只有在一次性地构建 newlib
库,或手动调用 CMake 时是必须的。换句话说,你不需要永久性地修改你的 PATH 环境变量,这会干扰到其它的,非 SOF 的工作。
for i in "${SOF_WORKSPACE}"/xtensa-*-elf; do PATH="$PATH:$i"/bin; done
为每个工具链构建并安装 newlib
库:
#!/usr/bin/bash
SOF_WORKSPACE=$HOME/data/work_sof
XTENSA_ROOT="${SOF_WORKSPACE}"/xtensa-root
cd "${SOF_WORKSPACE}"/newlib-xtensa
time for toolchain in ../xtensa-*-elf; do
./configure --target="${toolchain#../}" --prefix="$XTENSA_ROOT" &&
make && make install || break;
rm etc/config.cache
done
ls "$XTENSA_ROOT"
可以看到:
share xtensa-byt-elf xtensa-hsw-elf xtensa-imx-elf
xtensa-apl-elf xtensa-cnl-elf xtensa-imx8m-elf
这应该会花费几分钟。
注意
--prefix=
的值为一个绝对路径。根据你的环境变量定义XTENSA_ROOT
。
必须的头文件现在位于 "$SOF_WORKSPACE"/xtensa-root
,至此 xtensa DSP 的交叉编译工具链搭建完毕。
第 4 步. 构建并签名固件二进制文件
SOF 环境搭建完成之后,克隆 sof 仓库:
cd "$SOF_WORKSPACE"
git clone --recursive https://github.com/thesofproject/sof
cd sof
将示例配置文件 installer/sample-config.mk
拷贝到 installer/config.mk
,然后选择一个平台列表,并在后面的文件中提供一个可选的目标主机名。运行安装程序:
make -C installer/ [ -j 4 ]
installer/config.mk
配置文件看起来像下面这样:
# To customize the installation, copy this file to config.mk and edit
# it. Leave undefined to use default values.
# As usual with Make, all these can also be passed as either CLI
# arguments or environment variables. Warning: undefined is NOT the
# same as blank!
# You MUST "make cleanall" after changing anything here
# Everything is installed by default. To install and deploy fewer
# patforms override the default lists like this:
# UNSIGNED_list :=
SIGNED_list := imx8 imx8m
# The default FW_DESTDIR is the local /lib/firmware/intel directory
# _remote := test-system.local
# FW_DESTDIR := root@${_remote}:/lib/firmware/intel
# USER_DESTDIR := ${_remote}:bin/
# Passed to ./scripts/xtensa-build-all.sh -i
# Ignored by incremental builds, MUST cleanall after changing this
# IPC_VERSION := IPC4
# Define this empty for a plain sof/ directory and no sof -> sof-v1.2.3
# symbolic links. This is _only_ to override the top-level directory
# name; for sof_versions.h see version.cmake and try sof/.tarball-version
# SOF_VERSION :=
#
SOF_VERSION := $(shell git describe --tags )
# SOF_VERSION := v1.6.14
# Uncomment this to have the build_*_?cc/ directories at the top-level
BUILDS_ROOT := ${CURDIR}/..
# The build is not deterministic; use this to reduce noise when testing
# the installer/ itself
# BUILD_ONLY_ONCE := true
平台列表在 SIGNED_list
中指定。make
命令的 -C
参数用于在执行之前先切换目录。make
命令默认查找构建配置文件的顺序为 "GNUmakefile"、"makefile"、"Makefile",也可以用 -f [makefile path]
参数为 make
命令指定 makefile 的路径。SOF 项目中用了 "GNUmakefile",而不是更常见的 "makefile" 或 "Makefile"。
SOF 的 installer/GNUmakefile 文件会包含 config.mk,以获得其中的配置。如果在 makefile 中未设置 .DEFAULT_GOAL
,那么 make 的默认目标是不以点号 '.' 开头的第一个目标。不过 SOF 的 makefile 设置了 .DEFAULT_GOAL
。installer/GNUmakefile 默认构建的目标如下:
.DEFAULT_GOAL := stage
. . . . . .
stage: signed unsigned ldicts aliases topologies tools
. . . . . .
#
# 1. Stages all *.ri files
#
# 2. Create symbolic links, including (broken) intel-signed symbolic
# links that must be fixed in a final release, otherwise the release
# is incomplete. To check all symlinks: file $(find -type l)
#
# '%' is the platform name
SIGNED_FWS := ${SIGNED_list:%=${COMMUNITY}/sof-%.ri}
# $(info SIGNED_FWS = ${SIGNED_FWS})
signed: ${SIGNED_FWS}
${SIGNED_FWS}: ${COMMUNITY}/sof-%.ri: \
${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri \
| ${COMMUNITY} ${INTEL_SIGNED}
install ${INSTALL_OPTS} $< $@
ln -sfT intel-signed/sof-$*.ri ${STAGING_SOF_VERSION}/sof-$*.ri
# '%' is the platform name
UNSIGNED_FWS := ${UNSIGNED_list:%=${STAGING_SOF_VERSION}/sof-%.ri}
# $(info UNSIGNED_FWS = ${UNSIGNED_FWS})
unsigned: ${UNSIGNED_FWS}
${UNSIGNED_FWS}: ${STAGING_SOF_VERSION}/sof-%.ri: \
${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri
install ${INSTALL_OPTS} $< $@
BUILD_SOF_RIS := \
${UNSIGNED_list:%=${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri} \
${SIGNED_list:%=${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri}
# When the build is not deterministic use this to reduce noise when testing
# this Makefile.
# Also very useful with XCC, see next comment.
ifneq (true,${BUILD_ONLY_ONCE})
.PHONY: ${BUILD_SOF_RIS}
endif
# Incremental builds are not possible with XCC because the entire
# toolchain requires $XTENSA_SYSTEM but CMake does not support
# build-time environment variables. In the future we could move the
# XTENSA_SYSTEM values out of xtensa-build-all.sh and into some shared
# config file included here.
${BUILD_SOF_RIS}: ${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri: | ${BUILDS_ROOT}
cd ${BUILDS_ROOT} && bdir="$$(dirname $@)" && \
if [ -e $${bdir}/build.ninja -o -e $${bdir}/Makefile ] && \
[ xcc != "${TOOLCHAIN}" ] ; then \
cmake --build $${bdir} -- bin; else \
$(CURDIR)/../scripts/xtensa-build-all.sh -i "${IPC_VERSION}" $*; fi
make
命令会调 cmake
或 sof/scripts/xtensa-build-all.sh
脚本构建 SOF。当 {TOOLCHAIN} 目录下,存在 build.ninja 或 Makefile 文件时,调用 cmake
,否则调用 sof/scripts/xtensa-build-all.sh
脚本。{TOOLCHAIN} 目录如 sof/build_imx8m_gcc。
第一次执行 make
命令时,'{TOOLCHAIN}' 目录还不存在,也就更不用说 build.ninja 或 Makefile 文件了,则 make
命令将调用 sof/scripts/xtensa-build-all.sh
脚本。sof/scripts/xtensa-build-all.sh
脚本创建构建环境,如:
for platform in "${PLATFORMS[@]}"
do
printf '\n ------\n %s\n ------\n' "$platform"
HAVE_ROM='no'
DEFCONFIG_PATCH=''
PLATFORM_PRIVATE_KEY=''
source "${SOF_TOP}"/scripts/set_xtensa_params.sh "$platform" ||
die 'set_xtensa_params.sh failed'
test -z "${PRIVATE_KEY_OPTION}" || PLATFORM_PRIVATE_KEY="${PRIVATE_KEY_OPTION}"
if [ -n "$XTENSA_TOOLS_ROOT" ]
then
XTENSA_TOOLS_DIR="$XTENSA_TOOLS_ROOT/install/tools/$TOOLCHAIN_VER"
XTENSA_BUILDS_DIR="$XTENSA_TOOLS_ROOT/install/builds/$TOOLCHAIN_VER"
# make sure the required version of xtensa tools is installed
if [ -d "$XTENSA_TOOLS_DIR" ]
then
XCC="xt-xcc"
else
XCC="none"
>&2 printf 'WARNING: %s
\t is not a directory, reverting to gcc\n' "$XTENSA_TOOLS_DIR"
fi
fi
# CMake uses ROOT_DIR for includes and libraries a bit like
# --sysroot would.
ROOT="$SOF_TOP/../xtensa-root/$HOST"
if [ "$XCC" == "xt-xcc" ]
then
TOOLCHAIN=xt
ROOT="$XTENSA_BUILDS_DIR/$XTENSA_CORE/xtensa-elf"
# CMake cannot set (evil) build-time environment variables at configure time:
# https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-get-or-set-environment-variables
export XTENSA_SYSTEM=$XTENSA_BUILDS_DIR/$XTENSA_CORE/config
printf 'XTENSA_SYSTEM=%s\n' "${XTENSA_SYSTEM}"
PATH=$XTENSA_TOOLS_DIR/XtensaTools/bin:$OLDPATH
COMPILER="xcc"
else
TOOLCHAIN=$HOST
PATH=$SOF_TOP/../$HOST/bin:$OLDPATH
COMPILER="gcc"
DEFCONFIG_PATCH=""
printf 'My PATH=%s\n' "$PATH"
fi
BUILD_DIR=build_${platform}_${COMPILER}
printf "Build in %s\n" "$BUILD_DIR"
# only delete binary related to this build
rm -fr "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
printf 'PATH=%s\n' "$PATH"
( set -x # log the main commands and their parameters
cmake -DTOOLCHAIN="$TOOLCHAIN" \
-DROOT_DIR="$ROOT" \
-DMEU_OPENSSL="${MEU_OPENSSL}" \
"${MEU_PATH_OPTION}" \
"${PLATFORM_PRIVATE_KEY}" \
-DINIT_CONFIG=${PLATFORM}${DEFCONFIG_PATCH}_defconfig \
-DEXTRA_CFLAGS="${EXTRA_CFLAGS}" \
"$SOF_TOP"
)
sof/scripts/xtensa-build-all.sh
脚本执行 scripts/set_xtensa_params.sh
脚本设置平台相关俄参数,导出适当的环境变量,删除已经存在的构建目录,并创建新的,随后执行 cmake
命令。
后续再次执行 make
命令时,由于{TOOLCHAIN} 目录下,已经存在 build.ninja 或 Makefile 文件,则会进行增量编译。
如果指定的平台得到支持,通常是调用 cmake
。当指定的平台不支持时,sof/scripts/xtensa-build-all.sh
脚本会输出支持的平台列表,如:
work_sof/sof/installer$ make
UNSIGNED_list =
SIGNED_list = byt
ALIAS_list =
cd /media/data/work_sof/sof/installer/.. && bdir="$(dirname /media/data/work_sof/sof/installer/../build_byt_gcc/sof.ri)" && \
if [ -e ${bdir}/build.ninja -o -e ${bdir}/Makefile ] && \
[ xcc != "gcc" ] ; then \
cmake --build ${bdir} -- bin; else \
/media/data/work_sof/sof/installer/../scripts/xtensa-build-all.sh -i "" byt; fi
Error: Unknown platform specified: byt
Known platforms are: imx8m imx8ulp rn rmb vangogh mt8186 mt8195 mt8188 acp_6_3
make: *** [GNUmakefile:192:/media/data/work_sof/sof/installer/../build_byt_gcc/sof.ri] 错误 1
调整示例命令中的 -j 4
为你的 CPU 核数,或者构建失败时可以移除它。
这个构建配置并发地构建多个平台,并将固件和拓扑文件部署到你配置的本地或远程目的地的 /lib/firmware/intel/
。它第一次以默认的平台配置构建,然后切换到增量构建,这将保留你所做的任何 make menuconfig
或其它配置更改。下面将介绍这两种构建方法,如果你需要更好地控制构建系统和配置,请继续阅读。否则,你可以跳过接下来的两部分。
安装程序还从 sof/tools/
子目录构建和部署一些用户空间二进制文件。
注意
安装程序比它所依赖的更底层的
./scripts/
脚本快得多,因为它不会每次运行时都删除构建目录。然而,一些 “大” 的配置更改,比如切换到不同的工具链,或一些罕见的构建失败,可能会使installer-builds/build_*
目录处于一种不恰当的状态。在这种情况下,则删除这些目录并再次运行安装程序。
rm -rf $SOF_WORKSPACE/sof/installer-builds
make -C installer/
重新配置并从头构建
要从头构建 Sound Open Firmware,上面的安装程序 Makefile 依赖 https://github.com/thesofproject/sof/tree/master/scripts/xtensa-build-all.sh 脚本。如果你需要更好地控制构建过程,或调试一些构建问题,你也可以直接使用它。要为所有平台构建固件,则执行:
cd "$SOF_WORKSPACE"/sof/
./scripts/xtensa-build-all.sh -a
注意
这个脚本只有在交叉编译器和
xtensa-root
位于相同的sof
目录中时才能工作,如上面说明的那样。
截至 2021 年 5 月,你可以指定如下平台参数中的一个或多个:byt
,cht
,bdw
,hsw
,apl
,skl
,kbl
,cnl
,sue
,icl
,jsl
,tgl
,tgl-h
,imx8
,imx8x
,imx8m
。例如:
./scripts/xtensa-build-all.sh byt
./scripts/xtensa-build-all.sh byt apl
运行脚本而不带任何参数,可以获得最新的平台列表和帮助消息。你也可以通过 -d 来启用调试构建,通过 -r 来启用 rom 构建,和通过 -j [n] 来加速构建。
./scripts/xtensa-build-all.sh -d byt
./scripts/xtensa-build-all.sh -d -r apl
./scripts/xtensa-build-all.sh -d -r -j 4 apl
注意
xtensa-build-all.sh
脚本使用rimage
来构建最终的固件镜像。rimage
默认使用 sof 仓库中包含的公钥来签名。然而,如果你需要使用一些其它的外部密钥来签名,你可以在调用构建之前,通过环境变量来指定你的密钥的路径:export PRIVATE_KEY_OPTION=-DRIMAGE_PRIVATE_KEY=/path_to_key/private.pem
相同的导出机制在通过 Docker 构建时也应该能工作。
增量构建
这是一个 sof 仓库更详细的构建指南。不像 xtensa-build-all.sh
,它不会每次都重新构建所有东西。上面的 installer Makefile 依赖它做增量构建。
下面的代码片段假设你的当前目录是 sof
克隆 ("$SOF_WORKSPACE"/sof/
) 的根目录。
CMake 推荐在源码树外面构建。其中,这允许你从相同的源码在不同的构建目录中构建不同的配置/平台,而无需从头开始。
注意
-j
参数告诉 make,要并发使用多少个进程。选择一个与你的构建系统匹配的值。
对于 Bay Trail:
mkdir build_byt && cd build_byt
cmake -DTOOLCHAIN=xtensa-byt-elf -DROOT_DIR="$XTENSA_ROOT"/xtensa-byt-elf -DINIT_CONFIG=baytrail_defconfig ..
make help # lists all available targets
make bin -j4 VERBOSE=1
你可以将上面的 byt
替换为 sof/scripts/xtensa-build-all.sh
的帮助输出中列出的任何其它平台。查找与同一脚本或以上脚本中各个平台匹配的工具链。
上面 cmake
命令的执行,需要有一个合适的执行环境,包括 XTENSA_ROOT
、PATH
等环境变量的适当设置,及准备好的工具链等。使用 make
命令编译时,执行环境由 make
和 sof/scripts/xtensa-build-all.sh
等脚本创建。直接在命令行中执行 cmake
命令,需要手动创建执行环境。PATH
环境变量需要添加工具链的 bin
目录路径,如 $SOF_TOP/../$HOST/bin
,XTENSA_ROOT
环境变量需要指向 $SOF_WORKSPACE/xtensa-root
目录。
-DINIT_CONFIG
用于指定配置文件的名称。sof 的 src/arch/xtensa/configs 目录下包含一些平台预定以的默认配置,如:
/media/data/work_sof/sof$ ls src/arch/xtensa/configs/
acp_6_3_defconfig imx8m_defconfig imx8x_defconfig mt8188_defconfig override renoir_defconfig
imx8_defconfig imx8ulp_defconfig mt8186_defconfig mt8195_defconfig rembrandt_defconfig vangogh_defconfig
-DINIT_CONFIG
需要定义为目标平台的配置文件名称。INIT_CONFIG
在 scripts/cmake/kconfig.cmake 文件中处理,如:
if(NOT INIT_CONFIG_found)
# Brand new build directory, search for initial configuration
# Default value when no -DINIT_CONFIG on the command line
set(INIT_CONFIG "initial.config" CACHE STRING "Initial .config file")
# - ".' is the top source directory.
# - "src/arch/${arch}/configs" is for convenience and compatibility with
# defconfigs.cmake.
# - First found wins.
# - If two archs ever use the same platform_defconfig name then a full
# path must be used, e.g.: -DINIT_CONFIG=src/arch/myarch/collision_defconfig
set(init_config_search_list ".")
foreach(arch "xtensa" "host")
list(APPEND init_config_search_list "src/arch/${arch}/configs")
endforeach()
find_file(INIT_CONFIG_found
NAMES ${INIT_CONFIG}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH
PATHS ${init_config_search_list}
)
else() # old build directory
if (INIT_CONFIG)
message(WARNING
"IGNORING '-DINIT_CONFIG=${INIT_CONFIG}!!' "
"Using up-to-date ${INIT_CONFIG_found} instead."
)
endif()
endif() # new/old build directory
它会在 src/arch/xtensa/configs 和 src/arch/host/configs 目录下查找配置文件,以获得配置文件的完整路径。
注意
在 cmake 步骤之后,你可以在 build_xxx 目录下使用
'make menuconfig'
自定义你的构建。FW 二进制构建可以使用 DEBUG 和 ROM 选项。通过
'make menuconfig'
启用它们。
mkdir build_cnl_custom && cd build_cnl_custom
cmake -DTOOLCHAIN=xtensa-cnl-elf -DROOT_DIR="$XTENSA_ROOT"/xtensa-cnl-elf -DINIT_CONFIG=cannonlake_defconfig ..
make menuconfig # select/deselect options and save
make bin -j4
注意
如果你已经安装了 Ninja,你可以使用它来替换 Make。在配置步骤中键入 cmake -GNinja … 即可。
固件构建结果
固件二进制文件位于 build_<platform>/src/arch/xtensa/。安装器把它们拷贝到你的目标机器的 /lib/firmware/intel/sof 目录下。
sof-apl.ri sof-bdw.ri sof-byt.ri sof-cht.ri sof-cnl.ri sof-hsw.ri
具体的目标目录,可以在 installer/config.mk 文件中配置。如:
# The default FW_DESTDIR is the local /lib/firmware/intel directory
# _remote := test-system.local
# FW_DESTDIR := root@${_remote}:/lib/firmware/intel
# USER_DESTDIR := ${_remote}:bin/
第 5 步. 构建拓扑文件和工具
如果你使用前一节介绍的固件安装器,你可能可以跳过这一节。
从头开始一步重新构建
不带任何参数的 https://github.com/thesofproject/sof/tree/master/scripts/build-tools.sh 构建 https://github.com/thesofproject/sof/tree/master/tools/ 的默认 CMake 目标 "ALL"。
/media/data/work_sof/sof$ cd "$SOF_WORKSPACE"/sof/
/media/data/work_sof/sof$ ./scripts/build-tools.sh
+ cmake --build /media/data/work_sof/sof/tools/build_tools -- -j 4
[0/1] Re-running CMake...
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/hanpfei/data/work_sof/sof/tools/build_tools
[0/298] Generating abi.h
[1/298] Generating sof-hda-efx-generic-4ch.tplg
saving nhlt as binary in nhlt-sof-hda-efx-generic-4ch.bin
[6/298] Generating production/sof-imx8mp-wm8960-mixer.conf
[7/298] Generating production/sof-imx8-wm8960-cs42888.conf
[8/298] Generating production/sof-imx8mp-wm8960-mixer.tplg
[9/298] Generating production/sof-imx8-wm8960-cs42888.tplg
要查看选项列表,以 -h
选项运行 https://github.com/thesofproject/sof/tree/master/scripts/build-tools.sh。
/media/data/work_sof/sof$ ./scripts/build-tools.sh -h
Configures and builds selected CMake projects in the tools/ directory.
Attention: the list of selected shortcuts below is _not_ exhaustive. To
build _everything_ don't select any particular target; this will build
CMake's default target "ALL".
usage: ./scripts/build-tools.sh [-c|-f|-h|-l|-p|-t|-T]
-h Display help
-c Rebuild ctl/
-l Rebuild logger/
-p Rebuild probes/
-T Rebuild topology/ (not topology/development/! Use ALL)
-t Rebuild test/topology/ (or tools/test/topology/tplg-build.sh directly)
-C No build, only CMake re-configuration. Shows CMake targets.
WARNING: building tools/ is now incremental by default!
To build from scratch delete: /media/data/work_sof/sof/tools/build_tools
or use the -C option.
增量构建
cd "$SOF_WORKSPACE"/sof/tools/
mkdir build_tools && cd build_tools
cmake ..
make -j4
如果你的 cmake --version
是 3.13 或更高,你可能想要使用 -B 选项:
cmake -B build_tools/
make -C build_tools/ -j4 VERBOSE=1
rm -rf build_tools/ # no need to change directory ever
拓扑文件和工具构建结果
拓扑文件位于 tools/build_tools/topology 目录下。安装器 Makefile 把它们拷贝到目标机器的 /lib/firmware/intel/sof-tplg/ 目录下。
sof-logger 工具位于 tools/build_tools/logger 目录下。安装器 Makefile 把它们拷贝到你选择的目标目录。
第 6 步. 构建 Linux 内核
Sound Open Firmware 使用 Linux 内核 dev 分支,它必须与其它开发分支 firmware 和 topology 一起工作。这个简短的小节展示了如何在 Ubuntu 上使用少量命令构建经过测试的 Debian 内核包。请注意,这些命令每次都是从头开始重新构建所有内容,这使得对于开发,速度慢得不合适。如果你需要修改内核代码,忽略这里的介绍,看一下 搭建一个基于 Ktest 的环境,kconfig repo 的 README 文件,和 SOF Linux 驱动程序架构。
- 构建内核的这个分支
sudo apt-get install bison flex libelf-dev
cd "$SOF_WORKSPACE"
git clone https://github.com/thesofproject/linux
cd linux
git checkout topic/sof-dev
make defconfig
git clone https://github.com/thesofproject/kconfig
scripts/kconfig/merge_config.sh .config ./kconfig/base-defconfig ./kconfig/sof-defconfig ./kconfig/mach-driver-defconfig ./kconfig/hdaudio-codecs-defconfig
或者,你也可以运行 make menuconfig
,导航到 Device Drivers > Sound card support > Advanced Linux Sound Architecture,然后选择 Prefer SOF driver over SST on BY/CHT platforms 选项。
- 构建内核 deb 包以安装到目标机器上。
make deb-pkg -j 4
- 将三个输出 .deb 文件从 $SOF_WORKSPACE 拷贝到目标机器并安装它们。
sudo dpkg -i /absolute/path/to/deb/file
sudo apt-get install -f
参考文档:
Build toolchains and SOF from sources
Done.