Skip to content

First, What Is It

  • External project: the project directory is not inside the SDK; the SDK is embedded via a git submodule (e.g., my_app/sdk/). The project commits only its own code; the SDK version is pinned by the submodule.
  • BL_SDK_BASE: the environment variable pointing to the SDK root — the single clue for "where the SDK is"; both Makefile and CMake use it.
  • Difference from the in-SDK project: nearly the same files; the key difference is BL_SDK_BASE pointing to ./sdk in the Makefile, and the project can be committed independently of the SDK repo.

Operation Steps

1
Create the project directory and init git

Keep the project separate from the SDK: the project is its own git repo, and the SDK becomes a submodule inside it:

mkdir my_app
cd my_app
git init
2
Add the SDK as a submodule

A submodule is a “repo inside a repo”; the SDK is embedded at a fixed version for collaboration and version pinning:

git submodule add https://github.com/bouffalolab/bouffalo_sdk.git sdk
3
Create CMakeLists.txt

Almost identical to the in-SDK project, except BL_SDK_BASE points to the sdk directory (set before building):

cmake_minimum_required(VERSION 3.15)

find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})

sdk_set_main_file(main.c)

project(my_app)
4
Create Makefile

BL_SDK_BASE points to the sdk subdirectory inside the project (note ./sdk, not ../..):

SDK_DEMO_PATH ?= $(abspath .)
BL_SDK_BASE ?= $(abspath ./sdk)

export BL_SDK_BASE

include $(BL_SDK_BASE)/project.build
5
Create Kconfig / defconfig / main.c

These three files are identical to the in-SDK project: Kconfig references the SDK menu, defconfig toggles components, main.c is the entry.

6
Build and flash

The Makefile exports BL_SDK_BASE automatically, so just build and flash:

make CHIP=bl616 BOARD=bl616dk
make flash CHIP=bl616 COMX=/dev/ttyUSB0

What Each File Is For (File-by-File)

Git submodule: the SDK "version lock"

bash
git submodule add https://github.com/bouffalolab/bouffalo_sdk.git sdk   # add once
git submodule update --init --recursive                                 # fetch after cloning
  • The project records only the SDK commit hash, not the SDK source.
  • After cloning, run git submodule update --init to fetch the SDK.
  • To upgrade the SDK: cd sdk && git pull, then commit the submodule update.

CMakeLists.txt

cmake
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})  # BL_SDK_BASE points to ./sdk
sdk_set_main_file(main.c)
project(my_app)

The only difference from the in-SDK project: BL_SDK_BASE is explicitly set to ./sdk by the Makefile instead of derived from ../...

Makefile

make
SDK_DEMO_PATH ?= $(abspath .)
BL_SDK_BASE ?= $(abspath ./sdk)     # key difference: points to the sdk subdirectory
export BL_SDK_BASE
include $(BL_SDK_BASE)/project.build

export BL_SDK_BASE passes the path to CMake's $ENV{BL_SDK_BASE}, which find_package needs.

Kconfig / defconfig / main.c

Identical to the in-SDK project:

  • Kconfig: source "$BL_SDK_BASE/Kconfig" (here $BL_SDK_BASE is ./sdk).
  • defconfig: CONFIG_FREERTOS =y etc.
  • main.c: entry starting with board_init().

flash_prog_cfg.ini (optional)

ini
[FW]
filedir = ./build/build_out/my_app_$(CHIPNAME)*.bin
address = 0x000000

Same as before, used by make flash.

FAQ

Why BL_SDK_BASE instead of copying the SDK into the project?

The submodule records only the SDK version: smaller repo, controlled upgrades, consistent team builds; copying the source makes the repo huge and hard to sync.

Build says SDK not found after cloning?

Submodules are not fetched automatically: run git submodule update --init --recursive and confirm sdk/ is not empty.

Can external and examples projects migrate to each other?

Yes. The files are nearly identical; migration only changes BL_SDK_BASE in the Makefile (../.../sdk).

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23