已有 C 库可能只带 Makefile,而 Zephyr 应用由 CMake 驱动。把两者接起来,并不是把任意生成的 .a 文件放进链接命令:外部库必须使用与固件一致的目标编译器、归档器、架构和 ABI 选项,构建系统也必须知道归档何时生成、应用何时可以链接。
本文依据 Zephyr 4.4.0 的 External Library 示例完整页面及该版本伴随源码译编。发布维护方为 Zephyr Project,页面未见个人作者署名;C 源文件归属 Intel Corporation,Makefile 还包含 Nordic Semiconductor ASA 的版权声明。核对日期为 2026 年 10 月 5 日。本文采用的演练环境是 Linux、Zephyr 4.4.0、SDK 1.0.1 和 qemu_x86;这是固定的演练范围,本文未安装 SDK、构建或运行 QEMU。

示例目录里的每个文件做什么
官方示例路径是 samples/application_development/external_lib。库源码已经随 Zephyr 仓库提交,本例不需要在构建时从网络下载业务代码或第三方包。
external_lib/
├── CMakeLists.txt
├── prj.conf
├── sample.yaml
├── src/main.c
└── mylib/
├── Makefile
├── include/mylib.h
└── src/mylib.c
main.c 属于 Zephyr 应用,调用库公开的 mylib_hello_world()。库自己的 Makefile 负责把 mylib.c 编译成对象,再归档为 libmylib.a。顶层 CMake 使用 ExternalProject 驱动这个过程,并把结果包装为可链接的 imported library。
先把目标编译信息交给外部构建系统
以下是官方 CMakeLists.txt 的完整功能内容,英文说明注释整理为正文,其余命令与版本源文件保持一致。代码标记为 Apache-2.0。
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(external_lib)
target_sources(app PRIVATE src/main.c)
zephyr_get_include_directories_for_lang_as_string( C includes)
zephyr_get_system_include_directories_for_lang_as_string(C system_includes)
zephyr_get_compile_definitions_for_lang_as_string( C definitions)
zephyr_get_compile_options_for_lang_as_string( C options)
if(DEFINED CMAKE_C_COMPILER_TARGET)
set(target_flag "--target=${CMAKE_C_COMPILER_TARGET}")
endif()
set(external_project_cflags
"${target_flag} ${includes} ${definitions} ${options} ${system_includes}"
)
include(ExternalProject)
set(mylib_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/mylib)
set(mylib_build_dir ${CMAKE_CURRENT_BINARY_DIR}/mylib)
set(MYLIB_LIB_DIR ${mylib_build_dir}/lib)
set(MYLIB_INCLUDE_DIR ${mylib_src_dir}/include)
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
set(submake "$(MAKE)")
else()
set(submake "make")
endif()
ExternalProject_Add(
mylib_project
PREFIX ${mylib_build_dir}
SOURCE_DIR ${mylib_src_dir}
BINARY_DIR ${mylib_src_dir}
CONFIGURE_COMMAND ""
BUILD_COMMAND
${submake}
PREFIX=${mylib_build_dir}
CC=${CMAKE_C_COMPILER}
AR=${CMAKE_AR}
CFLAGS=${external_project_cflags}
INSTALL_COMMAND ""
BUILD_BYPRODUCTS ${MYLIB_LIB_DIR}/libmylib.a
)
add_library(mylib_lib STATIC IMPORTED GLOBAL)
add_dependencies(mylib_lib mylib_project)
set_target_properties(mylib_lib PROPERTIES
IMPORTED_LOCATION ${MYLIB_LIB_DIR}/libmylib.a)
set_target_properties(mylib_lib PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MYLIB_INCLUDE_DIR})
target_link_libraries(app PUBLIC mylib_lib)
四个 zephyr_get_…_for_lang_as_string 调用收集 C 编译所需的普通包含目录、系统包含目录、宏定义和编译选项;若设置了 CMAKE_C_COMPILER_TARGET,还传入 --target=…。这些字符串共同成为外部 Make 的 CFLAGS。
仅仅传递 CC 还不够。同一编译器可生成不同指令集、调用约定、浮点 ABI 或布局的目标文件;库与应用必须一致。也不能认为任何第三方库都接受全部 Zephyr 参数:原例注释明确指出,有的外部构建系统能够独立配置目标,有的与某些选项不兼容,需要过滤。集成真实库时,应核对它自己的构建接口,不要机械复制参数串。
ExternalProject 的目录、产物和依赖
mylib_src_dir 指向仓库里的库源码;mylib_build_dir 指向当前应用构建目录下的 mylib。虽然 BINARY_DIR 被设为源码根目录,让 Make 从那里启动,但传给 Make 的 PREFIX 把对象与归档输出放到构建树里。默认使用名为 build 的构建目录时,对应路径为:
build/mylib/obj/mylib.o
build/mylib/lib/libmylib.a
build/zephyr/zephyr.elf
CONFIGURE_COMMAND "" 和 INSTALL_COMMAND "" 分别跳过独立配置、安装阶段,本例直接调用 Make。BUILD_BYPRODUCTS 告诉上层构建系统该步骤会生成 libmylib.a,这对 Ninja 等需要明确依赖图的生成器尤其关键。
归档不是由 CMake 的普通源码目标直接生成,因此建立 STATIC IMPORTED GLOBAL 目标 mylib_lib,用 IMPORTED_LOCATION 指明归档路径,再通过 add_dependencies 要求 mylib_project 先完成。INTERFACE_INCLUDE_DIRECTORIES 把公开头文件目录传递给使用者,最后把 mylib_lib 链接到 app。产物声明、构建依赖和链接关系缺一不可:只写链接路径,容易遇到并行构建时文件尚未产生;只写构建依赖,又不会自动把库符号带进固件。
当顶层生成器是 Unix Makefiles 时,示例使用 $(MAKE) 递归调用子 Make;其他生成器则查找 PATH 里的 make。因此即便顶层用 Ninja,GNU Make 仍然是依赖。不要因为缺少 make 就改为用宿主默认 gcc 手工生成库。
外部 Makefile 如何编译和归档
官方 Makefile 如下。这里保留原版权与清理目标供静态理解;其中 clean 含递归删除,本文没有执行。实际使用前必须确认对象和归档路径都局限在专用构建目录。
#
# Copyright (c) 2017 Intel Corporation
# Copyright (c) 2022 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#
PREFIX ?= .
OBJ_DIR ?= $(PREFIX)/obj
LIB_DIR ?= $(PREFIX)/lib
ifeq ($(findstring Windows, $(OS)),Windows)
DEL := rmdir /S /Q
MKDIR := mkdir
else
DEL := rm -rf
MKDIR := mkdir -p
endif
all:
-$(MKDIR) "$(OBJ_DIR)"
-$(MKDIR) "$(LIB_DIR)"
$(CC) -c $(CFLAGS) -MD -Iinclude src/mylib.c -o $(OBJ_DIR)/mylib.o
$(AR) -rcs $(LIB_DIR)/libmylib.a $(OBJ_DIR)/mylib.o
clean:
$(DEL) "$(OBJ_DIR)" "$(LIB_DIR)"
?= 提供可覆盖的默认路径;CMake 传入 PREFIX 后,对象与归档就在构建树中。Make recipe 行必须保留制表符缩进。$(CC) -c 仅编译,$(AR) -rcs 把对象放进静态归档;-Iinclude 提供库自身公开头文件目录,-MD 生成编译依赖文件。
这里有几个真实的工程边界。创建目录命令前面的减号会让 Make 忽略该命令的失败;它方便处理目录已存在的情形,也可能掩盖权限或路径问题。编译和归档行里的部分路径未加引号,带空格的工作目录或工具链路径可能解析错误。参数通过 Make 与 shell 解释,不能让不可信输入控制 CC、AR、CFLAGS 或目录变量。外部构建脚本必须作为能执行命令的代码审查,不能当成纯数据。
这个教学 Makefile 没有消费 -MD 生成的依赖文件,顶层 ExternalProject 也使用自己的步骤与时间戳管理。不要仅凭第一次构建成功,就推定每次修改都能正确触发增量构建。变更库头文件、源文件或编译参数后,应检查是否重建了库;可在新的专用构建目录做完整验证,避免复用陈旧归档。本文没有声称已复现某种增量构建失败。
应用和库的最小接口
以下三个源文件共同展示调用链,逻辑与官方版本一致:
/* mylib/include/mylib.h
* Copyright (c) 2017 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _MYLIB_H_
#define _MYLIB_H_
int mylib_hello_world(void);
#endif
/* mylib/src/mylib.c
* Copyright (c) 2017 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include "mylib.h"
#include <stdio.h>
int mylib_hello_world(void)
{
printf("mylib says: Hello World!\n");
return 0;
}
/* src/main.c
* Copyright (c) 2017 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <stdio.h>
#include <mylib.h>
int main(void)
{
printf("Hello World!\n");
mylib_hello_world();
return 0;
}
prj.conf 只有下面一项,启用标准输出到控制台:
CONFIG_STDOUT_CONSOLE=y
这些 C 代码只打印固定字符串,没有接收不可信格式字符串、解析外部数据或使用秘密。这个结论仅覆盖所读到的极小例子,不是对任意接入库或整个 Zephyr 依赖树的安全背书。
固定环境下如何安排一次验证
在已完成官方工具链准备的隔离 Linux 工作区,确认使用 Zephyr 4.4.0 和预先核对的 SDK,并且 GNU Make 可用。选择一个新建、无个人文件和凭据的构建目录。本文演练采用 qemu_x86,因此可参考如下构建与运行命令;这些命令由本文针对该约定环境给出,不是本文执行记录:
west build -b qemu_x86 -d build_external_lib \
samples/application_development/external_lib
west build -d build_external_lib -t run
这里显式指定了 build_external_lib,相应产物应是 build_external_lib/mylib/lib/libmylib.a 与 build_external_lib/zephyr/zephyr.elf。检查编译日志中的 CC、AR 和目标参数是否来自同一 Zephyr 配置,再检查最终固件是否调用了库。
官方 sample.yaml 把 native_sim 列为 integration platform,console harness 匹配以下两行。它支持理解示例预期验证什么,不能当作 qemu_x86 已实测通过的证据:
Hello World!
mylib says: Hello World!
如果没有库那一行,要区分“库没有构建”“没有链接”“主程序没有调用”“控制台输出配置不对”;如果链接报目标格式或 ABI 错误,先检查外部 Make 是否真正用了传入的目标编译器和选项,而不是先给链接器添加忽略错误的参数。替换真实库后还需检查许可证、依赖、内存分配模型、线程与中断上下文要求。
Windows 说明与版本边界
原文另有 Windows 提示:GNU Make 必须在 PATH 中,可以通过已有的 Chocolatey 安装方式 choco install make,或从 GnuWin32 的 Make 页面取得 Binaries 与 Dependencies 并解压到同一目录,也可以使用 Complete package 安装方式。本文保留这些信息作为来源说明,不把旧的预编译下载渠道自动视为今天的推荐环境;安装来源、版本与 PATH 中实际执行的文件须独立核对。本文主流程采用 Linux,未运行任何安装命令。
文档页面显示本页源码最后更新于 2024 年 8 月 23 日、生成于 2026 年 4 月 14 日;读取的是 4.4.0 固定页面。换用其他版本时,应重新核对 CMake 辅助函数、工具链与 board target 名称。SDK 1.0.1 是本文选定的组合,本文未独立完成其安装及兼容性实测。
来源、修改与许可
源页由 Zephyr Project members and individual contributors 维护,页面版权为 © 2015–2026。本文完整翻译源页说明,并基于 v4.4.0 示例源码扩展讲解 CMake、Makefile、头文件、实现、应用、配置与测试定义。代码保留 Intel / Nordic 归属并采用 Apache License 2.0;许可证全文见文末。Zephyr 许可说明列有其他组件例外,不能把本例许可推广到全部第三方库。
修改包括中文说明、格式整理、固定环境命令与安全边界,未声称改写后的示例经过执行测试;没有提供未经验证的“安全 Makefile 替代版”。原创配图不是软件运行截图。
原始示例测试定义与代码许可
这是v4.4.0原始 sample.yaml,其integration platform为native_sim;前文qemu_x86演练命令是编辑补充,仍未执行。来源:固定版本测试定义。
sample:
name: External Library
tests:
sample.app_dev.external_lib:
integration_platforms:
- native_sim
tags: external
harness: console
harness_config:
type: multi_line
regex:
- "Hello World!"
- "mylib says: Hello World!"
下列完整Apache License2.0适用于前述标有SPDX声明的示例代码。保留 Copyright (c)2017 Intel Corporation及Makefile的 Copyright (c)2022 Nordic Semiconductor ASA;文档来源版权为©2015–2026 Zephyr Project members and individual contributors。中文说明、格式整理和已注明的演练参数为未完纪于2026-10-05所作修改。其他组件的许可仍需分别判断。
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.












暂无评论内容