Skip to content

Conversation

@tejlmand
Copy link
Contributor

@tejlmand tejlmand commented Feb 24, 2020

This PR introduces Zephyr Config package for CMake.

Today, working with Zephyr / CMake requires users to always set ZEPHYR_BASE.
This can be done in a couple of different ways, depending on OS and shell being used (manually sourcing zephyr-env.sh, sourced in bashrc, running zephyr-env.cmd, etc.)

Or when using west build then ZEPHYR_BASE is set automatically.

Unfortunately, using an environment variable in the build system has a couple of flaws.

A couple of examples, see further down for details:

  • west build is incompatible with command line ninja if user does not set ZEPHYR_BASE after running west
  • cmake -G'Eclipse CDT4 - Ninja' and Eclipse, requires re-launching of Eclipse if switching to another project that uses a different Zephyr base.
  • Having multiple Zephyr directories bears the risk of forgetting to set another (correct) Zephyr base.
  • Zephyr base is changed between CMake and ninja invocation
  • Probably more.

west build Example (zephyr-env.sh not sourced as that is not required for west):

$ cd <projects>/zephyr/samples/hello_world $ west build -bnrf52840_pca10056 $ cd build $ touch ../CMakeLists.txt $ ninja [0/1] Re-running CMake... CMake Error at CMakeLists.txt:5 (include): include could not find load file: /cmake/app/boilerplate.cmake CMake Error at CMakeLists.txt:8 (target_sources): Cannot specify sources for target "app" which is not built by this project. 

Terminal 1)
$ cmake -G'Eclipse CDT4 - Ninja' -DBOARD=nrf52840_pca10056

Terminal 2 or Desktop shortcut (not sourcing `zephyr-env.sh), Eclipse error:

15:39:45 **** Incremental Build of project hello_world@build **** /usr/bin/ninja all [0/1] Re-running CMake... CMake Error at CMakeLists.txt:5 (include): include could not find load file: /cmake/app/boilerplate.cmake -- Eclipse version is set to 3.6 (Helios). Adjust CMAKE_ECLIPSE_VERSION if this is wrong. -- Configuring incomplete, errors occurred! 

Having multiple Zephyrs and sourcing wrong one

/projects/zephyr-alt/zephyr/samples/hello_world/build$ cmake -GNinja -DBOARD=nrf52840_pca10056 .. -- Zephyr version: 2.1.99 -- Found PythonInterp: /usr/bin/python3.6 (found suitable version "3.6.8", minimum required is "3.6") -- Selected BOARD nrf52840_pca10056 -- Found west: /home/tora/.local/bin/west (found suitable version "0.7.1", minimum required is "0.6.0") -- Loading /projects/ncs/zephyr/boards/arm/nrf52840_pca10056/nrf52840_pca10056.dts as base Devicetree configuration written to /projects/zephyr-alt/zephyr/samples/hello_world/build/zephyr/include/generated/devicetree.conf Parsing /projects/ncs/zephyr/Kconfig Loaded configuration '/projects/ncs/zephyr/boards/arm/nrf52840_pca10056/nrf52840_pca10056_defconfig' Merged configuration '/projects/zephyr-alt/zephyr/samples/hello_world/prj.conf' Configuration saved to '/projects/zephyr-alt/zephyr/samples/hello_world/build/zephyr/.config' 

as seen, the Zephyr base was wrong, but everything worked.
This might give unexpected results later.


Zephyr base changed between CMake and Ninja invocation.
This could happen to someone running CMake and ninja in a projectA.
Change into projectB to do some work, and sets ZEPHYR_BASE to projectB.
Switch back to projectA, forgetting to set ZEPHYR_BASE and execute ninja

$ echo $ZEPHYR_BASE /projects/ncs/zephyr $ cmake -GNinja -DBOARD=nrf52840_pca10056 .. -- Zephyr version: 2.1.99 ... $ cd <projectB> $ source zephyr-env.sh $ cd <projectA>/build $ ninja -v $ ninja [0/1] Re-running CMake... -- Zephyr version: 2.2.0-rc1 -- Selected BOARD nrf52840_pca10056 -- Found west: /home/tora/.local/bin/west (found suitable version "0.7.1", minimum required is "0.6.0") -- Loading /projects/ncs/zephyr/boards/arm/nrf52840_pca10056/nrf52840_pca10056.dts as base Devicetree header saved to '/projects/ncs/zephyr/samples/hello_world/build/zephyr/include/generated/devicetree_unfixed.h' Parsing /projects/zephyr-alt/zephyr/Kconfig /projects/zephyr-alt/zephyr/scripts/kconfig/kconfig.py: /projects/ncs/nrf/subsys/bootloader/Kconfig:25: '/projects/zephyr-alt/zephyr/../nrf/subsys/partition_manager/Kconfig.template.build_strategy' not found (in 'source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.build_strategy"'). Check that environment variables are set correctly (e.g. $srctree, which is set to '/projects/zephyr-alt/zephyr'). Also note that unset environment variables expand to the empty string. CMake Error at /projects/zephyr-alt/zephyr/cmake/kconfig.cmake:216 (message): command failed with return code: 1 Call Stack (most recent call first): /projects/zephyr-alt/zephyr/cmake/app/boilerplate.cmake:464 (include) CMakeLists.txt:5 (include) 

In this case, an error was printed to user, but in case the two Zephyr's are very close, it could happen that everything worked, and in that case harder to detect when things break.


Fixes in this PR:

  • Cache ZEPHYR_BASE, the ZEPHYR_BASE that was set for the first CMake invocation in current build folder should be sticky, that is if CMake is re-invoked due to changes in any file, then the same ZEPHYR_BASE should be used.
  • Allow west build and ninja to work better together.
  • Remove the requirement to set ZEPHYR_BASE for majority of users
  • Be backward compatible with current ZEPHYR_BASE and allow it to support advange use-cases

With this PR, Zephyr now has a CMake config package.
A one-time install must be done in a Zephyr. (multiple install are allowed but not required).
To do this install, run:

west zephyr-export 

Once installed, users can now do:

$ echo $ZEPHYR_BASE $ cmake -GNinja -DBOARD=nrf52840_pca10056 .. Including boilerplate (in-zephyr-tree): /projects/ncs/zephyr/cmake/app/boilerplate.cmake -- Zephyr version: 2.2.0-rc1 

as seen, no ZEPHYR_BASE was set.

and also out-of-tree builds are supported this way:

$ echo $ZEPHYR_BASE tora@ubuntu:/projects/oot/hello_world/build$ cmake -GNinja -DBOARD=nrf52840_pca10056 .. Including boilerplate (out-of-worktree): /projects/ncs/zephyr/cmake/app/boilerplate.cmake -- Zephyr version: 2.2.0-rc1 

Using ZEPHYR_BASE and enforcing another Zephyr is also possible:

$ ZEPHYR_BASE=/projects/zephyr-alt/zephyr cmake -GNinja -DBOARD=nrf52840_pca10056 .. Including boilerplate (zephyr base): /projects/zephyr-alt/zephyr/cmake/app/boilerplate.cmake -- Zephyr version: 2.2.0-rc1 -- Found PythonInterp: /usr/bin/python3.6 (found suitable version "3.6.8", minimum required is "3.6") -- Selected BOARD nrf52840_pca10056 -- Found west: /home/tora/.local/bin/west (found suitable version "0.7.1", minimum required is "0.6.0") -- Loading /projects/zephyr-alt/zephyr/boards/arm/nrf52840_pca10056/nrf52840_pca10056.dts as base 

Creating a project also becomes much cleaner, all a user has to do, is to use find_package.
To create an application, you'll write:

find_package(Zephyr 2.0.0 HINTS $ENV{ZEPHYR_BASE}) project(hello_world) target_sources(app PRIVATE src/main.c) 

This has some additional benefits, such as requesting only to compile against an exact match:

find_package(Zephyr 2.0.0 EXACT HINTS $ENV{ZEPHYR_BASE}) 

or simply accept any Zephyr:

find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) 

To install Zephyr as a package, do the following:

west zephyr-export 

Or manually:

$ cd <project>/zephyr/share/zephyr-package/cmake/ $ cmake . Zephyr and ZephyrUnitTest (/projects/github/ncs/zephyr/share/zephyr-package/cmake) has been added to the user package registry in: ~/.cmake/packages/Zephyr ~/.cmake/packages/ZephyrUnitTest -- Configuring done -- Generating done -- Build files have been written to: /<project>/zephyr/share/zephyr-package/cmake 

Example of west / ninja fix:

$ west build -bnrf52840_pca10056 $ cd build $ touch ../CMakeLists.txt $ echo $ZEPHYR_BASE $ ninja [0/1] Re-running CMake... Including boilerplate (in-zephyr-tree): /projects/ncs/zephyr/cmake/app/boilerplate.cmake -- Zephyr version: 2.2.0-rc1 -- Selected BOARD nrf52840_pca10056 ... 

Things still ToDo:
[X] - Update documentation to described workflow (depends on feedback to this PR)
[X] - Create west extension command to make easy Zephyr config package install (instead of cmake .)

tejlmand added 13 commits March 26, 2020 13:58
When ZephyrConfig package is being version checked, then ZephyrConfigVersion.cmake loads version.cmake. This causes a print message, such as the following to happen: -- Zephyr version: 2.2.0 Now, in case a user has multiple Zephyr installations, this could result in something similar to: -- Zephyr version: 2.2.0 -- Zephyr version: 2.x.0 -- Zephyr version: 3.x.0 being printed. This commit add the possibility to disable version printing. With new Zephyr base find_package, printing of ZEPHYR_BASE is added after the version, in order to make it easy for users to see which Zephyr is used. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no> Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no> suggested change: print ZEPHYR_BASE
This commit adds the possibility of using a Zephyr repository package base even when it has not been exported to CMake package registry. It also introduces the possibility of locating and using Zephyr CMake config package correctly when invoking CMake on an out-of-tree project. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit introduces ZEPHYR_BASE as a cached variable, ensures that once ZEPHYR_BASE has been set in a project, it is sticky. Using cached variable also allows users to reconfigure ZEPHYR_BASE if they so wish. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
Adding ZephyrUnittestConfig.cmake and ZephyrUnittestConfigVersion.cmake to allow unittest projects to use find_package to locate ZephyrUnittest. This means that it will be possible to allow users to run CMake without the need to source zephyr-env.sh or run zephyr-env.cmd. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
Using find_package to locate Zephyr. Old behavior was to use $ENV{ZEPHYR_BASE} for inclusion of boiler plate code. Whenever an automatic run of CMake happend by the build system / IDE then it was required that ZEPHYR_BASE was defined. Using ZEPHYR_BASE only to locate the Zephyr package allows CMake to cache the base variable and thus allowing subsequent invocation even if ZEPHYR_BASE is not set in the environment. It also removes the risk of strange build results if a user switchs between different Zephyr based project folders and forgetting to reset ZEPHYR_BASE before running ninja / make. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
Changing ZEPHYR_BASE throughout Zephyr tests and samples revealed that intel s1000 crb cache test case could not be run on CI. This has now been fixed by moving the tests file located in tests/board/intel_s1000_crb folder into tests/board/intel_s1000_crb/main instead so there is now main and cache folders with test projects. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
Fixed usage build target. Previously, `ninja usage` would print: Build flags: ninja VERBOSE=1 [targets] verbose build This is clearly wrong, as VERBOSE=1 is for make targets. To support both ninja based builds and make based build systems, the CMAKE_MAKE_PROGRAM is now exported from the calling CMake / build instance, and the verbose flag is set depending on whether ninja or make is used as build program. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
With the introduction of ZephyrConfig.cmake all parts of CMake code should rely on the CMake ZEPHYR_BASE variable instead of the environment setting. This ensures that after the first CMake invocation, then all subsequent invocation in same build folder will use same zephyr base. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
West utilizes Zephyr base when invoked out-of-tree in order to determine west topdir. This commit ensures that zephyr base when invoking west from CMake is set to current zephyr base. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This command make it possible to use west for first time registration of a Zephyr config package in CMake. To register Zephyr as a CMake config package, invoke: west zephyr-export Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit introduces ZEPHYR_PREFER which is a list that user can specify when compiling an application. This allows a user who has multiple Zephyr installations in the same work-tree to provide a list of which Zephyr to prefer. This is an extension to CMake VERSION field, as a user who is working with multiple Zephyr installations could face a situation where multiple Zephyr's is having same version, as example 2.2.99, in which case CMake version is not sufficient. Example, workspace looking as: /projects/workspace/zephyr /projects/workspace/zephyr-alternate /projects/workspace/zephyr-wip /projects/workspace/my_app To prefer zephyr-alternate, then zephyr-wip the my_app/CMakeLists.txt should look as: set(ZEPHYR_PREFER "zephyr-alternate" "zephyr-wip") find_package(Zephyr) Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit includes the following fixes in order to remove environment setting of ZEPHYR_BASE is west extension commands. - Build command west build --pristine will now use the ZEPHYR_BASE variable found in CMakeCache.txt in the build folder. This ensures that the pristine command is executed from the same Zephyr that was used for compilation. - Board command The west boards command no longer sets Zephyr base before invoking cmake -P cmake/boards.cmake Instead boards.cmake uses find_package(Zephyr) to ensure consistent behavior with Zephyr samples, so that the detection of Zephyr base is uniform across CMake commands. It also changes BOARD_ROOT_SPACE_SEPARATED to BOARD_ROOT in order to be consistent with existing user documentation. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no> Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit changes the current boilerplate include description and instead describes the use of find_package(Zephyr) It also add a section covering additional possibilities when using find_package(Zephyr). - Search order - Zephyr repository application description - Zephyr workspace application description - Zephyr freestanding application description - Environment ZEPHYR_BASE setting - Multiple Zephyr and preference setting Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
@tejlmand tejlmand force-pushed the zephyr_base_improvement branch from c18f564 to 29b5548 Compare March 26, 2020 13:01
@carlescufi
Copy link
Member

@nashif @tejlmand is this ready for merging now?

@tejlmand
Copy link
Contributor Author

@nashif @tejlmand is this ready for merging now?

I'm still running full CI with this /scripts/ci/run_ci.sh -b master -r origin -l -R <commit>, but no errors so far.
Not sure if @nashif has completed a full CI run locally.

Any comments to doc can be addressed separately, as they a just minor improvements in phrasing.

@nashif
Copy link
Member

nashif commented Mar 26, 2020

@nashif @tejlmand is this ready for merging now?

i had CI run the ~50k builds but then something went bad at the end with the run, so do not have the exact results... It looked good in general. I think we should merge, look at first daily build after merge and fix any potential issues raised by daily build.

@carlescufi
Copy link
Member

@nashif @tejlmand is this ready for merging now?

i had CI run the ~50k builds but then something went bad at the end with the run, so do not have the exact results... It looked good in general. I think we should merge, look at first daily build after merge and fix any potential issues raised by daily build.

I agree, let's merge and deal with the aftermath in subsequent PRs. I don't think we'll ever get closer to merging this.

@carlescufi carlescufi merged commit db0b4e1 into zephyrproject-rtos:master Mar 27, 2020
@tejlmand tejlmand mentioned this pull request Apr 7, 2020
@tejlmand tejlmand mentioned this pull request Jun 23, 2020
18 tasks
tejlmand added a commit to tejlmand/openthread that referenced this pull request Sep 10, 2020
Since zephyrproject-rtos/zephyr#23054 then ZEPHYR_BASE should be used as a CMake variable. See also: d7862cf77686e607fcce776df1da6a800315bac8 in Zephyr repo. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
rlubos pushed a commit to zephyrproject-rtos/openthread that referenced this pull request Sep 10, 2020
Since zephyrproject-rtos/zephyr#23054 then ZEPHYR_BASE should be used as a CMake variable. See also: d7862cf77686e607fcce776df1da6a800315bac8 in Zephyr repo. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
@tejlmand tejlmand deleted the zephyr_base_improvement branch December 9, 2020 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Bluetooth area: Build System area: Documentation area: Kconfig area: Kernel area: native port Host native arch port (native_sim) area: Networking area: Samples Samples area: Test Framework Issues related not to a particular test, but to the framework instead area: Tests Issues related to a particular existing or missing test