This file describes the overall project structure and requirements for
contribution. Before you start make sure that you have basic utilities installed
in your system globally. The current list is defined in the
./ci/scripts/common/check_deps.sh
file.
When the repository is freshly cloned, run the ./ci/scripts/prepare.sh
file. This script will do the following things:
- Check globally installed and required binaries.
- Create virtual environment for Python scripts inside
./ci/scripts/python/.venv
. - Download nRF SDKs to the
./ci/sdks
directory. - Download third party libraries to the extracted SDK (e.g.
uECC
). - Download GCC ARM toolchain to the
./ci/toolchains/gcc
directory. - Download nRF Tools (
mergehex
andnrfjprog
) to the./ci/tools
directory. - Patch any files that lead to compilation errors or other issues using files
located inside
./ci/patches
directory.
Some folders located inside ./ci
, contain additional README.md
files
with more details. Make sure to check them out before contributing. As of now,
the project structure looks as follows:
./cmake/
arm-none-eabi.cmake
- ARM GCC Toolchain file.nrf5.cmake
- core CMake file which checks configuration options provided by a user and defines core libraries and functions (e.g.nrf5_mdk
).nrf5_validation.cmake
- validation of user provided configurations according to the information gathered from Nordic's website.nrf5_utils.cmake
- utility functions used in above files.nrf5_XXX.cmake
- autogenerated or manually written files with additional nRF libraries. These files are optional but recommended for use.
./ci/
examples/
- folder containing currently handwrittenCMakeLists.txt
files for examples from SDKs. They are built by the CI.generated/
- folder created for autogenerated files. For example you can find here scrapped examples from the SDKs, autogenerated libraries etc.libraries/
- JSON definitions of nRF libraries. They are used to generate CMake files inside the./cmake
folder and library tests inside./ci/libraries_tests
.libraries_tests/
- autogeneratedCMakeLists.txt
files for each object target. They are built by the CI.patches/
- patches for SDKs that fix compilation errors and other issues.sdks/
- place where nRF SDKs are downloaded.templates/
- place where are templates for autogenerated files.toolchains/
- place where ARM toolchains are downloaded.tools/
- place where nRF tools are downloaded.scripts/
- this directory contains all scripts used to autogenerate files or build artifacts. They are described in more details here.
Sections below describes recommended steps for adding new or modifying existing
library. You can find more details about innerworkings of scripts by reading
nested README.md
files or reading source code.
Instead of looking at example's Makefile in the nRF SDK, it's recommended to
scrape them to the JSON format, which is then located in the
./ci/generated/examples.json
file. You can do it
by running ./ci/scripts/scrape_makefiles.sh
script. Result in form of
examples.json
file is used by other scripts as well.
Execute the ./ci/scripts/generate_libraries.sh
script to gather information
about all existing libraries as well as ones not covered. The algorithm is
scanning all examples contained in the downloaded SDKs and, based on the usage
pattern, guesses the structure of all known libraries. Newly discovered libraries
have a name in form of libXXX
and can be found in the autogenerated
./ci/generated/libraries.json
file.
Here is an example:
"lib12": {
"variant": "object",
"sources": [
"external/utf_converter/utf.c"
],
"dependencies": {
"public": [
"lib0",
"lib2",
...
"nrf5_ringbuf",
"nrf5_strerror"
]
},
"includes": {
"public": [
"components/libraries/usbd",
"external/utf_converter"
]
}
},
The JSON pattern matches expected one, which is found in the files located
inside ./ci/libraries/
directory. Therefore you can use above
definition as a template, which can be modified according to the needs. As one
may expect, deduced libraries may contain wrong definitions which need to be
fixed.
All definitions are located inside ./ci/libraries/
directory.
You can add the library to one of the files matching your category or create a
new one if necessary. JSON schema is described in detail inside
./ci/libraries/README.md
file. Example definition
looks as follows:
"nrf5_boards": {
"documentation": "Boards",
"variant": "object",
"sources": [
"components/boards/boards.c"
],
"dependencies": {
"public": [
"nrf5_mdk",
"nrf5_nrfx_hal",
"nrf5_soc"
]
},
"includes": {
"public": [
"components/boards",
"components/libraries/util"
]
}
}
Once all library definitions are ready to go, run the
./ci/scripts/generate_cmake.sh
script. This will update all CMake files
located inside ./ci/cmake
folder. Check all the changes manually
to verify them and if there are any issues consider fixing the scripts.
Call the ./ci/scripts/generate_cmake_tests.sh
script to create a test for a
new library. Your CMakeLists.txt
file should be located inside
./ci/libraries_tests/XXX
directory where XXX
is a library name. Initially,
there is only CMakeLists.txt
file and you should add at least main.c
and
sdk_config.h
files. The main.c
file should call at least one library defined
function or macro to properly test if it builds as a standalone library. If
there is a need, you can also include a custom linker file in the directory.
Make sure that CI can properly build your library. To do that, call
./ci/scripts/build_library.sh
with proper parameters. For example, in the case
of nrf5_boards
library you may test it with the following call:
./ci/scripts/build_library.sh \
--library=nrf5_boards \
--sdk_version=16.0.0 \
--board=pca10056 \
--sd_variant=s140
As in the above section, you may use the result of the
./ci/generated/examples.json
and ./ci/scripts/generate_libraries.sh
to
iterate faster. Currently, adding an example is a manual process, but there is
a plan to do it automatically.
In the ./ci/examples
directory add CMakeLists.txt
file with
proper content and in the path which matches one from the SDK. For example,
blinky
is defined in the peripheral/blinky
folder and you should put it in
the same relative path to the ./ci/examples
directory. You can
use ./ci/scripts/generate_example.sh
to
automate this process. All examples are using sdk_config.h
and linker files
located inside the SDKs. Filling CMakeLists.txt
file is the only thing
required.
Make sure that CI can properly build your example. To do that, call
./ci/scripts/build_example.sh
with proper parameters. For example, in the case
of peripheral/blinky
you may test it with the following call:
./ci/scripts/build_example.sh \
--example=peripheral/blinky \
--sdk_version=16.0.0 \
--board=pca10056 \
--sd_variant=blank
Before submitting your example you must build it for all SDK versions we
currently support and also, for all boards and SoftDevice variants available
for this example. You can easily achieve this by using the
ci/scripts/build_all_examples.sh
script like this:
./ci/script/build_all_examples --example=ble_central/ble_app_blinky_c
The build_all_examples.sh
allows you to select which examples and
configurations shall be built. Use --help
option for details.