Mynewt-NimBLE 在 RV1103 嵌入式 Linux 平台的移植实战
摘要:本文详细介绍了在瑞芯微RV1106嵌入式Linux系统中移植Mynewt-NimBLE蓝牙协议栈的实现方案。通过交叉编译工具链适配、Makefile重写和源码目录重构,成功将NimBLE协议栈移植到ARMv7-A架构平台,生成静态库libnimble.a并统一输出头文件。文章重点解析了移植过程中的关键步骤,包括工具链配置、架构参数调整、静态库打包等,并针对常见错误提供了解决方案。最后展示了基
一、移植背景与环境说明
1.1 核心组件介绍
- RV1103:瑞芯微推出的低功耗嵌入式处理器,搭载 ARM Cortex-A7 架构(32 位),常用于物联网、边缘计算场景,支持蓝牙 4.2/5.0 控制器,是典型的嵌入式 Linux 硬件平台。
- Mynewt-NimBLE:轻量级开源 BLE 协议栈,支持主机 / 控制器分离架构,最多可同时连接 32 个从机,适配多种操作系统(含 Linux),适合资源受限的嵌入式设备。
- 目标需求:在 RV1103嵌入式 Linux 系统中移植 NimBLE,实现 BLE 客户端功能(接收从机 Notification 数据),并封装为静态库供其他程序调用。
1.2 环境准备
|
组件 |
版本 / 路径说明 |
|
交叉编译工具链 |
arm-rockchip830-linux-uclibcgnueabihf-gcc(RV1106 官方 SDK 自带,路径:/home/user/tools/linux/toolchain/...) |
|
Mynewt-NimBLE 源码 |
从 Apache 官网下载(链接),解压路径:/home/user/ble_gap/mynewt-nimble |
|
RV1106 系统镜像 |
基于 Linux 4.19 内核,已启用蓝牙子系统(CONFIG_BT、CONFIG_BT_HCI_UART 配置开启) |
|
依赖工具 |
ccache(可选,加速编译)、make、dos2unix(解决换行符问题)、file(验证编译产物) |
二、移植核心步骤
2.1 源码目录梳理
首先明确 NimBLE 源码关键目录作用,避免后续路径配置错误:
mynewt-nimble/
├── nimble/ # BLE 核心代码(主机/控制器/服务)
│ ├── include/ # 核心头文件(如 nimble_npl.h、ble_gap.h)
│ ├── host/ # 主机栈代码(GAP/GATT 逻辑)
│ └── transport/ # 传输层(HCI Socket 适配)
├── porting/ # 平台适配层
│ ├── npl/linux/ # Linux NPL 适配(线程/定时器/事件队列)
│ └── examples/linux/ # Linux 示例代码(本文基于此修改)
└── ext/tinycrypt/ # 加密库(NimBLE 依赖,用于蓝牙安全传输)
2.2 交叉编译工具链配置
RV1103 需使用 ARM 架构交叉编译工具链,在移植前先验证工具链可用性:
# 验证工具链版本(应输出 ARM 相关信息)
arm-rockchip830-linux-uclibcgnueabihf-gcc --version
# 若提示“command not found”,需添加工具链路径到环境变量
export PATH=$PATH:/home/usertools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin
2.3 编写移植适配 Makefile
NimBLE 官方示例 Makefile 需适配 RV1106 交叉编译环境,重点解决 “架构参数、静态库输出、头文件统一拷贝” 问题,最终 Makefile 如下(路径:mynewt-nimble/porting/examples/linux/Makefile):
# 1. 工具链配置(RV1106 官方交叉编译工具链)
CROSS_COMPILE ?=/home/user/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-
CC := $(CROSS_COMPILE)gcc
CXX := $(CROSS_COMPILE)g++
AR := $(CROSS_COMPILE)ar # 静态库打包工具
LD := $(CROSS_COMPILE)gcc
SIZE := $(CROSS_COMPILE)size
# 2. 统一输出目录(避免文件分散,便于后续调用)
NIMBLE_ROOT := ../../.. # NimBLE 源码根目录
OUTPUT_ROOT := ./output # 输出根目录
LIB_DIR := $(OUTPUT_ROOT)/lib # 静态库输出路径(最终:output/lib/libnimble.a)
INCLUDE_DIR := $(OUTPUT_ROOT)/include # 头文件输出路径(最终:output/include/)
# 3. NimBLE 核心配置(启用加密库,跳过不兼容文件)
NIMBLE_CFG_TINYCRYPT := 1
NIMBLE_IGNORE := $(NIMBLE_ROOT)/porting/nimble/src/hal_timer.c \
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime.c \
$(NULL)
# 4. 引入 NimBLE 基础编译规则(获取 NIMBLE_SRC 等核心变量)
include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
# 5. 源码配置(仅保留核心代码,移除示例 app 的 main.c/ble.c)
SRC := $(NIMBLE_SRC) # NimBLE 核心源码(主机/服务/传输层)
SRC += $(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.c) # Linux NPL 适配
SRC += $(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.cc)
SRC += $(wildcard $(NIMBLE_ROOT)/nimble/transport/socket/src/*.c) # HCI Socket
SRC += $(TINYCRYPT_SRC) # 加密库源码
# 6. 编译选项(适配 RV1106 ARMv7-A 架构,生成位置无关代码)
INC = ./include \
$(NIMBLE_ROOT)/porting/npl/linux/include \
$(NIMBLE_ROOT)/nimble/transport/socket/include \
$(NIMBLE_INCLUDE) \
$(TINYCRYPT_INCLUDE)
INCLUDES := $(addprefix -I, $(INC))
CFLAGS = $(NIMBLE_CFLAGS) \
$(INCLUDES) \
-g \
-D_GNU_SOURCE \
-march=armv7-a \ # RV1106 核心架构(Cortex-A7 属于 ARMv7-A)
-mthumb \ # 启用 Thumb 指令集(减少代码体积)
-mfpu=vfpv3-d16 \ # 适配 RV1106 浮点单元
-mfloat-abi=hard \# 硬件浮点调用约定
-fPIC \ # 位置无关代码(静态库必备)
$(NULL)
# 7. 静态库目标(核心:输出到 LIB_DIR/libnimble.a)
LIB_TARGET := $(LIB_DIR)/libnimble.a
OBJ := $(filter %.o, $(SRC:.c=.o) $(SRC:.cc=.o))
TINYCRYPT_OBJ := $(TINYCRYPT_SRC:.c=.o)
# 8. 伪目标(编译入口、清理、头文件拷贝)
.PHONY: all clean prepare install_headers
.DEFAULT: all
# 9. 编译流程:创建目录 → 编译静态库 → 拷贝头文件
all: prepare $(LIB_TARGET) install_headers
ho "=== 移植完成 ==="
echo "静态库路径: $(LIB_TARGET)"
echo "头文件路径: $(INCLUDE_DIR)"
# 准备输出目录(避免目录不存在报错)
prepare:
r -p $(LIB_DIR)
@mkdir -p $(INCLUDE_DIR)
@echo "已创建输出目录: $(OUTPUT_ROOT)"
# 打包静态库(ar rcs:创建+替换+生成索引)
$(LIB_TARGET): $(OBJ) $(TINYCRYPT_OBJ)
$(AR) rcs $@ $^
$(SIZE) $@ # 打印库大小(验证编译产物)
@echo "静态库生成完成: $@"
# 统一拷贝头文件(供其他程序调用)
install_headers:
@echo "=== 开始拷贝头文件 ==="
# 拷贝 NimBLE 核心头文件
@cp -r $(NIMBLE_ROOT)/nimble/include/* $(INCLUDE_DIR)/ || echo "NimBLE 头文件拷贝失败"
# 拷贝 NPL 适配头文件
@cp -r $(NIMBLE_ROOT)/porting/npl/linux/include/* $(INCLUDE_DIR)/ || echo "NPL 头文件拷贝失败"
# 拷贝加密库头文件
@cp -r $(NIMBLE_ROOT)/ext/tinycrypt/include/* $(INCLUDE_DIR)/ || echo "TinyCrypt 头文件拷贝失败"
# 验证拷贝结果
@ls -l $(INCLUDE_DIR) | grep -E "\.h$$" && echo "头文件拷贝完成" || echo "头文件为空,需检查路径"
# 清理产物(彻底删除输出目录和目标文件)
clean:
rm -rf $(OUTPUT_ROOT)
rm -f $(OBJ) $(TINYCRYPT_OBJ)
@echo "清理完成" @mkdi @ @ @ec
2.4 编译静态库与头文件
在 Makefile 所在目录执行编译命令,完成 NimBLE 静态库生成:
# 进入示例目录
cd /home/user/ble_gap/mynewt-nimble/porting/examples/linux
# 清理旧产物(首次编译可跳过,重新编译必执行)
make clean
# 编译静态库与头文件(若报错,按第三节问题解决处理)
make all
编译成功后,output 目录结构如下(核心产物已标注):
output/
├── include/ # 统一头文件(供其他程序引用)
│ ├── nimble_npl.h # NimBLE NPL 核心头文件
│ ├── ble_gap.h # GAP 服务头文件
│ ├── ble_gatt.h # GATT 服务头文件
│ └── tinycrypt/ # 加密库头文件
└── lib/
└── libnimble.a # RV1106 适配的 NimBLE 静态库(核心产物)
三、移植常见问题与解决方案
移植过程中易因 “工具链适配、路径配置、语法格式” 出现错误,以下是高频问题的解决方法:
3.1 错误 1:ccache: No such file or directory
- 原因:Makefile 调用 ccache 加速编译,但系统未安装。
- 解决:
-
- 安装 ccache(适合多次编译):sudo apt install ccache;
-
- 或临时禁用 ccache:修改 Makefile 中 CC := $(CROSS_COMPILE)gcc,删除前面的 ccache 前缀。
3.2 错误 2:arm-rockchip830-linux-uclibcgnueabihf-gcc: error: unrecognized command line option '-m32'
- 原因:NimBLE 官方 Makefile 默认添加 -m32(x86 32 位参数),RV1106(ARM 架构)不支持。
- 解决:删除 Makefile 中所有 -m32 选项,替换为 ARM 架构参数(如 -march=armv7-a,已在本文 Makefile 中配置)。
3.3 错误 3:cp: cannot create directory '/include': Permission denied
- 原因:INCLUDE_DIR 路径解析错误,指向系统根目录(/),无权限写入。
- 解决:
-
- 确认 Makefile 中 OUTPUT_ROOT 为绝对路径或正确相对路径(如本文 ./output);
-
- 在 install_headers 目标添加路径打印:@echo "INCLUDE_DIR: $(INCLUDE_DIR)",验证是否为 ./output/include。
3.4 错误 4:arm-rockchip830-linux-uclibcgnueabihf-ar: /home/.../output/lib: Is a directory
- 原因:LIB_TARGET 指向目录(如 output/lib),而非具体 .a 文件。
- 解决:修正 LIB_TARGET 为 $(LIB_DIR)/libnimble.a(确保包含文件名)。
3.5 错误 5:头文件未拷贝(output/include 为空)
- 原因:NIMBLE_ROOT 路径错误,导致源路径(如 ../../../nimble/include)不存在。
- 解决:
-
- 执行 echo $(NIMBLE_ROOT)/nimble/include,查看路径是否存在;
-
- 若不存在,修正 NIMBLE_ROOT(如实际路径是 ../../../../,则改为 NIMBLE_ROOT := ../../../../)。
四、功能验证:基于静态库开发 BLE 客户端
移植完成后,需验证 NimBLE 功能是否正常。以下是基于静态库的 BLE 客户端示例(接收从机 Notification 数据):
4.1 客户端代码(ble_client.c)
#include <stdio.h>
#include <string.h>
#include "nimble/nimble_npl.h"
#include "nimble/host/gap/ble_gap.h"
#define MAX_CONNECTIONS 5 // 最大连接数(RV1106 资源限制,建议不超过 10)
#define TARGET_DEV_NAME "Sensor-"// 目标从机名称前缀
#define NOTIFY_CHAR_UUID 0x2A50 // 从机 Notification 特征值 UUID
static struct ble_gap_conn s_conns[MAX_CONNECTIONS];
static int s_conn_count = 0;
static struct ble_uuid16 s_notify_uuid = BLE_UUID16_INIT(NOTIFY_CHAR_UUID);
// 打印 BLE 地址
void ble_addr_print(const ble_addr_t *addr) {
printf("%02x:%02x:%02x:%02x:%02x:%02x",
addr->val[5], addr->val[4], addr->val[3],
addr->val[2], addr->val[1], addr->val[0]);
}
// 处理 Notification 数据(从机推送的核心逻辑)
static int gap_event_cb(struct ble_gap_event *event, void *arg) {
switch (event->type) {
// 收到从机 Notification 数据
case BLE_GAP_EVENT_GATTC_NOTIFY: {
printf("从机(句柄%d)推送数据:", event->conn.handle);
for (int i = 0; i < event->gattc_notify.val_len; i++) {
printf("%02x ", event->gattc_notify.val[i]);
}
printf("\n");
return 0;
}
// 连接成功:启用 Notification
case BLE_GAP_EVENT_CONNECT:
printf("连接成功!从机地址:");
ble_addr_print(&event->connect.addr);
printf("(句柄%d)\n", event->conn.handle);
// 启用 Notification(需先发现特征值,此处简化为直接写入 CCCD)
uint8_t enable_notify[2] = {0x01, 0x00};
struct ble_gattc_write_params write = {
.conn_handle = event->conn.handle,
.handle = 0x000C, // 从机 CCCD 句柄(需实际调试确认)
.val = enable_notify, .len = 2
};
ble_gattc_write(&write, NULL, NULL);
return 0;
default:
return 0;
}
}
// 扫描目标从机
void scan_start() {
struct ble_gap_disc_params disc_params = {
.itvl = BLE_GAP_SCAN_FAST_INTERVAL,
.window = BLE_GAP_SCAN_FAST_WINDOW
};
ble_gap_event_register(gap_event_cb, NULL);
ble_gap_disc_start(&disc_params, NULL, NULL);
printf("开始扫描目标从机(名称前缀:%s)...\n", TARGET_DEV_NAME);
}
int main() {
// 初始化 NimBLE 协议栈
nimble_port_init();
ble_svc_gap_init();
ble_svc_gatt_init();
ble_store_ram_init();
// 启动扫描与事件循环
scan_start</doubaocanvas>
第二版makefile内容
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# 1. 工具链配置(保持不变)
CROSS_COMPILE ?=/home/user/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-
CC := $(CROSS_COMPILE)gcc
CXX := $(CROSS_COMPILE)g++
LD := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar # 静态库打包工具
AS := $(CROSS_COMPILE)as
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
# 2. 核心路径配置(新增:统一输出目录)
NIMBLE_ROOT := ../../..
OUTPUT_ROOT := ./output # 统一输出根目录
LIB_DIR := $(OUTPUT_ROOT)/lib # 静态库输出目录
INCLUDE_DIR := $(OUTPUT_ROOT)/include # 头文件输出目录
# 3. NimBLE 核心配置(保持不变)
NIMBLE_CFG_TINYCRYPT := 1
# 4. 跳过不兼容文件(保持不变)
NIMBLE_IGNORE := $(NIMBLE_ROOT)/porting/nimble/src/hal_timer.c \
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime.c \
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime_pwr2.c \
$(NULL)
# 5. 引入 NimBLE 基础编译规则(保持不变)
include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
# 6. 库源码配置(保持不变:移除应用层代码,仅保留核心源码)
SRC := $(NIMBLE_SRC)
SRC += \
$(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.c) \
$(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.cc) \
$(wildcard $(NIMBLE_ROOT)/nimble/transport/socket/src/*.c) \
$(TINYCRYPT_SRC) \
$(NULL)
# 7. 头文件路径(修改:新增输出目录的头文件路径,方便编译时引用)
INC = \
./include \
$(NIMBLE_ROOT)/porting/npl/linux/include \
$(NIMBLE_ROOT)/nimble/transport/socket/include \
$(NIMBLE_INCLUDE) \
$(TINYCRYPT_INCLUDE) \
$(INCLUDE_DIR) # 新增:输出目录的头文件路径(避免编译冲突)
INCLUDES := $(addprefix -I, $(INC))
# 8. 源码分类与目标文件(保持不变)
SRC_C = $(filter %.c, $(SRC))
SRC_CC = $(filter %.cc, $(SRC))
OBJ := $(SRC_C:.c=.o)
OBJ += $(SRC_CC:.cc=.o)
TINYCRYPT_OBJ := $(TINYCRYPT_SRC:.c=.o)
# 9. 编译选项(修复续行符,新增-fPIC)
CFLAGS = \
$(NIMBLE_CFLAGS) \
$(INCLUDES) \
-g \
-D_GNU_SOURCE \
-fPIC \ # 位置无关代码,确保库可复用
$(NULL)
# 10. 静态库目标(修改:指定库输出路径)
LIB_TARGET := $(LIB_DIR)/libnimble.a # 库路径+名称(如./output/lib/libnimble.a)
# 11. 伪目标定义(新增:install_headers目标,用于拷贝头文件)
.PHONY: all clean prepare install_headers
.DEFAULT: all
# 12. 编译入口(修改:先创建输出目录,再编译库,最后拷贝头文件)
all: prepare $(LIB_TARGET) install_headers
@echo "=== 所有构建完成 ==="
@echo "静态库路径: $(LIB_TARGET)"
@echo "头文件路径: $(INCLUDE_DIR)"
# 13. 准备目标(新增:创建输出目录,避免目录不存在报错)
prepare:
@mkdir -p $(LIB_DIR) # 创建库输出目录
@mkdir -p $(INCLUDE_DIR)# 创建头文件输出目录
@echo "已创建输出目录: $(OUTPUT_ROOT)"
# 14. 清理规则(修改:清理输出目录下的所有产物)
clean:
rm -rf $(OUTPUT_ROOT) # 删除整个output目录,彻底清理
rm -f $(OBJ) $(TINYCRYPT_OBJ) # 删除目标文件
@echo "=== 清理完成 ==="
# 15. TinyCrypt编译规则(保持不变)
$(TINYCRYPT_OBJ): CFLAGS+=$(TINYCRYPT_CFLAGS)
# 16. C文件编译规则(保持不变)
%.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) -o $@ $<
@echo "编译C文件: $< -> $@"
# 17. C++文件编译规则(保持不变)
%.o: %.cc
$(CXX) -c $(INCLUDES) $(CFLAGS) -o $@ $<
@echo "编译C++文件: $< -> $@"
# 18. 静态库打包规则(保持不变,输出到指定路径)
$(LIB_TARGET): $(OBJ) $(TINYCRYPT_OBJ)
$(AR) rcs $@ $^ # 打包静态库到LIB_TARGET路径
$(SIZE) $@ # 打印库大小
@echo "静态库生成完成: $@"
# 19. 头文件拷贝规则(新增:统一拷贝所有关键头文件到INCLUDE_DIR)
install_headers:
# 1. 拷贝NimBLE核心头文件(如nimble_npl.h、ble_gap.h)
@cp -r $(NIMBLE_ROOT)/nimble/include/* $(INCLUDE_DIR)/
# 2. 拷贝NPL适配层头文件(Linux系统抽象层)
@cp -r $(NIMBLE_ROOT)/porting/npl/linux/include/* $(INCLUDE_DIR)/
# 3. 拷贝HCI Socket传输层头文件
@cp -r $(NIMBLE_ROOT)/nimble/transport/socket/include/* $(INCLUDE_DIR)/
# 4. 拷贝TinyCrypt加密库头文件
@cp -r $(NIMBLE_ROOT)/ext/tinycrypt/include/* $(INCLUDE_DIR)/
# 5. 拷贝本地项目头文件(若./include有自定义头文件)
@cp -r ./include/* $(INCLUDE_DIR)/ 2>/dev/null || : # 忽略目录不存在的错误
@echo "头文件拷贝完成: $(INCLUDE_DIR)"
第一版makefile
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# 1. 工具链配置(保持不变)
CROSS_COMPILE ?=/home/usertools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-
CC := $(CROSS_COMPILE)gcc
CXX := $(CROSS_COMPILE)g++
LD := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar # 静态库打包工具(关键,原Makefile已包含)
AS := $(CROSS_COMPILE)as
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
# 2. NimBLE 核心配置(保持不变,确保库依赖正确)
NIMBLE_ROOT := ../../..
NIMBLE_CFG_TINYCRYPT := 1
# 3. 跳过不兼容文件(保持不变)
NIMBLE_IGNORE := $(NIMBLE_ROOT)/porting/nimble/src/hal_timer.c \
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime.c \
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime_pwr2.c \
$(NULL)
# 4. 引入 NimBLE 基础编译规则(保持不变,获取NIMBLE_SRC等关键变量)
include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
# 5. 库源码配置(关键修改:移除应用层的main.c,仅保留NimBLE核心+NPL层源码)
SRC := $(NIMBLE_SRC) # NimBLE核心源码(协议栈、服务等)
# 添加 NPL(OS适配层)和 Transport(HCI Socket)源码(库必需)
SRC += \
$(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.c) \
$(wildcard $(NIMBLE_ROOT)/porting/npl/linux/src/*.cc) \
$(wildcard $(NIMBLE_ROOT)/nimble/transport/socket/src/*.c) \
$(TINYCRYPT_SRC) \ # 加密库(NimBLE依赖)
$(NULL)
# 【关键删除】移除应用层的main.c和ble.c(这些是原demo的入口,库不需要)
# 原代码中的 "./ble.c ./main.c" 已删除,避免库包含应用层逻辑
# 6. 头文件路径(保持不变,确保其他程序引用库时能找到头文件)
INC = \
./include \
$(NIMBLE_ROOT)/porting/npl/linux/include \
$(NIMBLE_ROOT)/nimble/transport/socket/include \
$(NIMBLE_INCLUDE) \
$(TINYCRYPT_INCLUDE) \
$(NULL)
INCLUDES := $(addprefix -I, $(INC))
# 7. 源码分类(保持不变,区分C和C++文件)
SRC_C = $(filter %.c, $(SRC))
SRC_CC = $(filter %.cc, $(SRC))
# 8. 目标文件(保持不变,由源码生成.o文件)
OBJ := $(SRC_C:.c=.o)
OBJ += $(SRC_CC:.cc=.o)
TINYCRYPT_OBJ := $(TINYCRYPT_SRC:.c=.o)
# 9. 编译选项(保持不变,确保库编译兼容)
CFLAGS = \
$(NIMBLE_CFLAGS) \
$(INCLUDES) \
-g \
-D_GNU_SOURCE \
-fPIC # 【新增】生成位置无关代码,确保库可被不同程序链接
$(NULL)
# 10. 静态库目标(关键修改:原目标是可执行文件nimble-linux,改为静态库libnimble.a)
LIB_TARGET := libnimble.a # 静态库名称(约定以lib开头,.a结尾)
# 11. 伪目标定义(保持不变)
.PHONY: all clean
.DEFAULT: all
# 12. 编译入口(关键修改:生成静态库而非可执行文件)
all: $(LIB_TARGET)
# 13. 清理规则(修改:清理静态库和目标文件)
clean:
rm -f $(OBJ) $(TINYCRYPT_OBJ) $(LIB_TARGET) # 新增清理静态库
@echo "静态库及目标文件已清理"
# 14. TinyCrypt加密库编译规则(保持不变)
$(TINYCRYPT_OBJ): CFLAGS+=$(TINYCRYPT_CFLAGS)
# 15. C文件编译规则(保持不变)
%.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) -o $@ $<
@echo "编译C文件: $< -> $@"
# 16. C++文件编译规则(保持不变)
%.o: %.cc
$(CXX) -c $(INCLUDES) $(CFLAGS) -o $@ $<
@echo "编译C++文件: $< -> $@"
# 17. 静态库打包规则(关键新增:用ar工具将所有.o文件打包为静态库)
$(LIB_TARGET): $(OBJ) $(TINYCRYPT_OBJ)
$(AR) rcs $@ $^ # rcs:替换旧文件、创建库、生成索引(静态库打包标准参数)
$(SIZE) $@ # 打印库大小(可选,用于验证)
@echo "静态库生成完成: $@"
更多推荐



所有评论(0)