一、移植背景与环境说明

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 加速编译,但系统未安装。
  • 解决
    1. 安装 ccache(适合多次编译):sudo apt install ccache;
    1. 或临时禁用 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 路径解析错误,指向系统根目录(/),无权限写入。
  • 解决
    1. 确认 Makefile 中 OUTPUT_ROOT 为绝对路径或正确相对路径(如本文 ./output);
    1. 在 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)不存在。
  • 解决
    1. 执行 echo $(NIMBLE_ROOT)/nimble/include,查看路径是否存在;
    1. 若不存在,修正 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 "静态库生成完成: $@"

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐