1// -*- mode:doc -*- ; 2// vim: set syntax=asciidoc: 3 4[[outside-br-custom]] 5=== Keeping customizations outside of Buildroot 6 7As already briefly mentioned in xref:customize-dir-structure[], you can 8place project-specific customizations in two locations: 9 10 * directly within the Buildroot tree, typically maintaining them using 11 branches in a version control system so that upgrading to a newer 12 Buildroot release is easy. 13 14 * outside of the Buildroot tree, using the _br2-external_ mechanism. 15 This mechanism allows to keep package recipes, board support and 16 configuration files outside of the Buildroot tree, while still 17 having them nicely integrated in the build logic. We call this 18 location a _br2-external tree_. This section explains how to use 19 the br2-external mechanism and what to provide in a br2-external 20 tree. 21 22One can tell Buildroot to use one or more br2-external trees by setting 23the +BR2_EXTERNAL+ make variable set to the path(s) of the br2-external 24tree(s) to use. It can be passed to any Buildroot +make+ invocation. It 25is automatically saved in the hidden +.br2-external.mk+ file in the output 26directory. Thanks to this, there is no need to pass +BR2_EXTERNAL+ at 27every +make+ invocation. It can however be changed at any time by 28passing a new value, and can be removed by passing an empty value. 29 30.Note 31The path to a br2-external tree can be either absolute or relative. 32If it is passed as a relative path, it is important to note that it is 33interpreted relative to the main Buildroot source directory, *not* to 34the Buildroot output directory. 35 36.Note: 37If using an br2-external tree from before Buildroot 2016.11, you need to 38convert it before you can use it with Buildroot 2016.11 onward. See 39xref:br2-external-converting[] for help on doing so. 40 41Some examples: 42 43----- 44buildroot/ $ make BR2_EXTERNAL=/path/to/foo menuconfig 45----- 46 47From now on, definitions from the +/path/to/foo+ br2-external tree 48will be used: 49 50----- 51buildroot/ $ make 52buildroot/ $ make legal-info 53----- 54 55We can switch to another br2-external tree at any time: 56 57----- 58buildroot/ $ make BR2_EXTERNAL=/where/we/have/bar xconfig 59----- 60 61We can also use multiple br2-external trees: 62 63---- 64buildroot/ $ make BR2_EXTERNAL=/path/to/foo:/where/we/have/bar menuconfig 65---- 66 67Or disable the usage of any br2-external tree: 68 69----- 70buildroot/ $ make BR2_EXTERNAL= xconfig 71----- 72 73==== Layout of a br2-external tree 74 75A br2-external tree must contain at least those three files, described 76in the following chapters: 77 78 * +external.desc+ 79 * +external.mk+ 80 * +Config.in+ 81 82Apart from those mandatory files, there may be additional and optional 83content that may be present in a br2-external tree, like the +configs/+ 84or +provides/+ directories. They are described in the following chapters 85as well. 86 87A complete example br2-external tree layout is also described later. 88 89===== The +external.desc+ file 90 91That file describes the br2-external tree: the _name_ and _description_ 92for that br2-external tree. 93 94The format for this file is line based, with each line starting by a 95keyword, followed by a colon and one or more spaces, followed by the 96value assigned to that keyword. There are two keywords currently 97recognised: 98 99 * +name+, mandatory, defines the name for that br2-external tree. That 100 name must only use ASCII characters in the set +[A-Za-z0-9_]+; any 101 other character is forbidden. Buildroot sets the variable 102 +BR2_EXTERNAL_$(NAME)_PATH+ to the absolute path of the br2-external 103 tree, so that you can use it to refer to your br2-external tree. This 104 variable is available both in Kconfig, so you can use it to source your 105 Kconfig files (see below) and in the Makefile, so that you can use it 106 to include other Makefiles (see below) or refer to other files (like 107 data files) from your br2-external tree. 108+ 109.Note: 110Since it is possible to use multiple br2-external trees at once, this 111 name is used by Buildroot to generate variables for each of those trees. 112 That name is used to identify your br2-external tree, so try to come up 113 with a name that really describes your br2-external tree, in order for 114 it to be relatively unique, so that it does not clash with another name 115 from another br2-external tree, especially if you are planning on 116 somehow sharing your br2-external tree with third parties or using 117 br2-external trees from third parties. 118 119 * +desc+, optional, provides a short description for that br2-external 120 tree. It shall fit on a single line, is mostly free-form (see below), 121 and is used when displaying information about a br2-external tree (e.g. 122 above the list of defconfig files, or as the prompt in the menuconfig); 123 as such, it should relatively brief (40 chars is probably a good upper 124 limit). The description is available in the +BR2_EXTERNAL_$(NAME)_DESC+ 125 variable. 126 127Examples of names and the corresponding +BR2_EXTERNAL_$(NAME)_PATH+ 128variables: 129 130 * +FOO+ -> +BR2_EXTERNAL_FOO_PATH+ 131 * +BAR_42+ -> +BR2_EXTERNAL_BAR_42_PATH+ 132 133In the following examples, it is assumed the name to be set to +BAR_42+. 134 135.Note: 136Both +BR2_EXTERNAL_$(NAME)_PATH+ and `BR2_EXTERNAL_$(NAME)_DESC` are 137 available in the Kconfig files and the Makefiles. They are also 138 exported in the environment so are available in post-build, post-image 139 and in-fakeroot scripts. 140 141===== The +Config.in+ and +external.mk+ files 142 143Those files (which may each be empty) can be used to define package 144recipes (i.e. +foo/Config.in+ and +foo/foo.mk+ like for packages bundled 145in Buildroot itself) or other custom configuration options or make logic. 146 147Buildroot automatically includes the +Config.in+ from each br2-external 148tree to make it appear in the top-level configuration menu, and includes 149the +external.mk+ from each br2-external tree with the rest of the 150makefile logic. 151 152The main usage of this is to store package recipes. The recommended way 153to do this is to write a +Config.in+ file that looks like: 154 155------ 156source "$BR2_EXTERNAL_BAR_42_PATH/package/package1/Config.in" 157source "$BR2_EXTERNAL_BAR_42_PATH/package/package2/Config.in" 158------ 159 160Then, have an +external.mk+ file that looks like: 161 162------ 163include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/package/*/*.mk)) 164------ 165 166And then in +$(BR2_EXTERNAL_BAR_42_PATH)/package/package1+ and 167+$(BR2_EXTERNAL_BAR_42_PATH)/package/package2+ create normal 168Buildroot package recipes, as explained in xref:adding-packages[]. 169If you prefer, you can also group the packages in subdirectories 170called <boardname> and adapt the above paths accordingly. 171 172You can also define custom configuration options in +Config.in+ and 173custom make logic in +external.mk+. 174 175===== The +configs/+ directory 176 177One can store Buildroot defconfigs in the +configs+ subdirectory of 178the br2-external tree. Buildroot will automatically show them in the 179output of +make list-defconfigs+ and allow them to be loaded with the 180normal +make <name>_defconfig+ command. They will be visible in the 181'make list-defconfigs' output, below an +External configs+ label that 182contains the name of the br2-external tree they are defined in. 183 184.Note: 185If a defconfig file is present in more than one br2-external tree, then 186the one from the last br2-external tree is used. It is thus possible 187to override a defconfig bundled in Buildroot or another br2-external 188tree. 189 190===== The +provides/+ directory 191 192For some packages, Buildroot provides a choice between two (or more) 193implementations of API-compatible such packages. For example, there is 194a choice to choose either libjpeg ot jpeg-turbo; there is one between 195openssl or libressl; there is one to select one of the known, 196pre-configured toolchains... 197 198It is possible for a br2-external to extend those choices, by providing 199a set of files that define those alternatives: 200 201* +provides/toolchains.in+ defines the pre-configured toolchains, which 202 will then be listed in the toolchain selection; 203* +provides/jpeg.in+ defines the alternative libjpeg implementations; 204* +provides/openssl.in+ defines the alternative openssl implementations; 205* +provides/skeleton.in+ defines the alternative skeleton implementations; 206* +provides/init.in+ defines the alternative init system implementations, this 207 can be used to select a default skeleton for your init. 208 209===== Free-form content 210 211One can store all the board-specific configuration files there, such 212as the kernel configuration, the root filesystem overlay, or any other 213configuration file for which Buildroot allows to set the location (by 214using the +BR2_EXTERNAL_$(NAME)_PATH+ variable). For example, you 215could set the paths to a global patch directory, to a rootfs overlay 216and to the kernel configuration file as follows (e.g. by running 217`make menuconfig` and filling in these options): 218 219---- 220BR2_GLOBAL_PATCH_DIR=$(BR2_EXTERNAL_BAR_42_PATH)/patches/ 221BR2_ROOTFS_OVERLAY=$(BR2_EXTERNAL_BAR_42_PATH)/board/<boardname>/overlay/ 222BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=$(BR2_EXTERNAL_BAR_42_PATH)/board/<boardname>/kernel.config 223---- 224 225===== Additional Linux kernel extensions 226 227Additional Linux kernel extensions (see xref:linux-kernel-ext[]) can 228be added by storing them in the `linux/` directory at the root of a 229br2-external tree. 230 231===== Example layout 232 233Here is an example layout using all features of br2-external (the sample 234content is shown for the file above it, when it is relevant to explain 235the br2-external tree; this is all entirely made up just for the sake of 236illustration, of course): 237 238---- 239/path/to/br2-ext-tree/ 240 |- external.desc 241 | |name: BAR_42 242 | |desc: Example br2-external tree 243 | `---- 244 | 245 |- Config.in 246 | |source "$BR2_EXTERNAL_BAR_42_PATH/toolchain/toolchain-external-mine/Config.in.options" 247 | |source "$BR2_EXTERNAL_BAR_42_PATH/package/pkg-1/Config.in" 248 | |source "$BR2_EXTERNAL_BAR_42_PATH/package/pkg-2/Config.in" 249 | |source "$BR2_EXTERNAL_BAR_42_PATH/package/my-jpeg/Config.in" 250 | | 251 | |config BAR_42_FLASH_ADDR 252 | | hex "my-board flash address" 253 | | default 0x10AD 254 | `---- 255 | 256 |- external.mk 257 | |include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/package/*/*.mk)) 258 | |include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/toolchain/*/*.mk)) 259 | | 260 | |flash-my-board: 261 | | $(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/flash-image \ 262 | | --image $(BINARIES_DIR)/image.bin \ 263 | | --address $(BAR_42_FLASH_ADDR) 264 | `---- 265 | 266 |- package/pkg-1/Config.in 267 | |config BR2_PACKAGE_PKG_1 268 | | bool "pkg-1" 269 | | help 270 | | Some help about pkg-1 271 | `---- 272 |- package/pkg-1/pkg-1.hash 273 |- package/pkg-1/pkg-1.mk 274 | |PKG_1_VERSION = 1.2.3 275 | |PKG_1_SITE = /some/where/to/get/pkg-1 276 | |PKG_1_LICENSE = blabla 277 | | 278 | |define PKG_1_INSTALL_INIT_SYSV 279 | | $(INSTALL) -D -m 0755 $(PKG_1_PKGDIR)/S99my-daemon \ 280 | | $(TARGET_DIR)/etc/init.d/S99my-daemon 281 | |endef 282 | | 283 | |$(eval $(autotools-package)) 284 | `---- 285 |- package/pkg-1/S99my-daemon 286 | 287 |- package/pkg-2/Config.in 288 |- package/pkg-2/pkg-2.hash 289 |- package/pkg-2/pkg-2.mk 290 | 291 |- provides/jpeg.in 292 | |config BR2_PACKAGE_MY_JPEG 293 | | bool "my-jpeg" 294 | `---- 295 |- package/my-jpeg/Config.in 296 | |config BR2_PACKAGE_PROVIDES_JPEG 297 | | default "my-jpeg" if BR2_PACKAGE_MY_JPEG 298 | `---- 299 |- package/my-jpeg/my-jpeg.mk 300 | |# This is a normal package .mk file 301 | |MY_JPEG_VERSION = 1.2.3 302 | |MY_JPEG_SITE = https://example.net/some/place 303 | |MY_JPEG_PROVIDES = jpeg 304 | |$(eval $(autotools-package)) 305 | `---- 306 | 307 |- provides/init.in 308 | |config BR2_INIT_MINE 309 | | bool "my custom init" 310 | | select BR2_PACKAGE_MY_INIT 311 | | select BR2_PACKAGE_SKELETON_INIT_MINE if BR2_ROOTFS_SKELETON_DEFAULT 312 | `---- 313 | 314 |- provides/skeleton.in 315 | |config BR2_ROOTFS_SKELETON_MINE 316 | | bool "my custom skeleton" 317 | | select BR2_PACKAGE_SKELETON_MINE 318 | `---- 319 |- package/skeleton-mine/Config.in 320 | |config BR2_PACKAGE_SKELETON_MINE 321 | | bool 322 | | select BR2_PACKAGE_HAS_SKELETON 323 | | 324 | |config BR2_PACKAGE_PROVIDES_SKELETON 325 | | default "skeleton-mine" if BR2_PACKAGE_SKELETON_MINE 326 | `---- 327 |- package/skeleton-mine/skeleton-mine.mk 328 | |SKELETON_MINE_ADD_TOOLCHAIN_DEPENDENCY = NO 329 | |SKELETON_MINE_ADD_SKELETON_DEPENDENCY = NO 330 | |SKELETON_MINE_PROVIDES = skeleton 331 | |SKELETON_MINE_INSTALL_STAGING = YES 332 | |$(eval $(generic-package)) 333 | `---- 334 | 335 |- provides/toolchains.in 336 | |config BR2_TOOLCHAIN_EXTERNAL_MINE 337 | | bool "my custom toolchain" 338 | | depends on BR2_some_arch 339 | | select BR2_INSTALL_LIBSTDCPP 340 | `---- 341 |- toolchain/toolchain-external-mine/Config.in.options 342 | |if BR2_TOOLCHAIN_EXTERNAL_MINE 343 | |config BR2_TOOLCHAIN_EXTERNAL_PREFIX 344 | | default "arch-mine-linux-gnu" 345 | |config BR2_PACKAGE_PROVIDES_TOOLCHAIN_EXTERNAL 346 | | default "toolchain-external-mine" 347 | |endif 348 | `---- 349 |- toolchain/toolchain-external-mine/toolchain-external-mine.mk 350 | |TOOLCHAIN_EXTERNAL_MINE_SITE = https://example.net/some/place 351 | |TOOLCHAIN_EXTERNAL_MINE_SOURCE = my-toolchain.tar.gz 352 | |$(eval $(toolchain-external-package)) 353 | `---- 354 | 355 |- linux/Config.ext.in 356 | |config BR2_LINUX_KERNEL_EXT_EXAMPLE_DRIVER 357 | | bool "example-external-driver" 358 | | help 359 | | Example external driver 360 | |--- 361 |- linux/linux-ext-example-driver.mk 362 | 363 |- configs/my-board_defconfig 364 | |BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_BAR_42_PATH)/patches/" 365 | |BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/overlay/" 366 | |BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/post-image.sh" 367 | |BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/kernel.config" 368 | `---- 369 | 370 |- patches/linux/0001-some-change.patch 371 |- patches/linux/0002-some-other-change.patch 372 |- patches/busybox/0001-fix-something.patch 373 | 374 |- board/my-board/kernel.config 375 |- board/my-board/overlay/var/www/index.html 376 |- board/my-board/overlay/var/www/my.css 377 |- board/my-board/flash-image 378 `- board/my-board/post-image.sh 379 |#!/bin/sh 380 |generate-my-binary-image \ 381 | --root ${BINARIES_DIR}/rootfs.tar \ 382 | --kernel ${BINARIES_DIR}/zImage \ 383 | --dtb ${BINARIES_DIR}/my-board.dtb \ 384 | --output ${BINARIES_DIR}/image.bin 385 `---- 386---- 387 388The br2-external tree will then be visible in the menuconfig (with 389the layout expanded): 390 391---- 392External options ---> 393 *** Example br2-external tree (in /path/to/br2-ext-tree/) 394 [ ] pkg-1 395 [ ] pkg-2 396 (0x10AD) my-board flash address 397---- 398 399If you are using more than one br2-external tree, it would look like 400(with the layout expanded and the second one with name +FOO_27+ but no 401+desc:+ field in +external.desc+): 402 403---- 404External options ---> 405 Example br2-external tree ---> 406 *** Example br2-external tree (in /path/to/br2-ext-tree) 407 [ ] pkg-1 408 [ ] pkg-2 409 (0x10AD) my-board flash address 410 FOO_27 ---> 411 *** FOO_27 (in /path/to/another-br2-ext) 412 [ ] foo 413 [ ] bar 414---- 415 416Additionally, the jpeg provider will be visible in the jpeg choice: 417 418---- 419Target packages ---> 420 Libraries ---> 421 Graphics ---> 422 [*] jpeg support 423 jpeg variant () ---> 424 ( ) jpeg 425 ( ) jpeg-turbo 426 *** jpeg from: Example br2-external tree *** 427 (X) my-jpeg 428 *** jpeg from: FOO_27 *** 429 ( ) another-jpeg 430---- 431 432And similarly for the toolchains: 433 434---- 435Toolchain ---> 436 Toolchain () ---> 437 ( ) Custom toolchain 438 *** Toolchains from: Example br2-external tree *** 439 (X) my custom toolchain 440---- 441 442.Note 443The toolchain options in +toolchain/toolchain-external-mine/Config.in.options+ 444will not appear in the `Toolchain` menu. They must be explicitly included 445from within the br2-external's top-level +Config.in+ and will thus appear 446in the `External options` menu. 447