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_BASEpointing to./sdkin the Makefile, and the project can be committed independently of the SDK repo.
Operation Steps
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 initA 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 sdkAlmost 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)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.buildThese three files are identical to the in-SDK project: Kconfig references the SDK menu, defconfig toggles components, main.c is the entry.
The Makefile exports BL_SDK_BASE automatically, so just build and flash:
make CHIP=bl616 BOARD=bl616dk
make flash CHIP=bl616 COMX=/dev/ttyUSB0What Each File Is For (File-by-File)
Git submodule: the SDK "version lock"
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 --initto fetch the SDK. - To upgrade the SDK:
cd sdk && git pull, then commit the submodule update.
CMakeLists.txt
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
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.buildexport 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_BASEis./sdk).defconfig:CONFIG_FREERTOS =yetc.main.c: entry starting withboard_init().
flash_prog_cfg.ini (optional)
[FW]
filedir = ./build/build_out/my_app_$(CHIPNAME)*.bin
address = 0x000000Same 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

