-
Notifications
You must be signed in to change notification settings - Fork 8.2k
RFC: include version.h in the build system
#60651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Include the MAKE generated version header file so that any Zephyr application that include the kernel header will know its version without including additional header. Signed-off-by: Yong Cong Sin <[email protected]>
Set compiler specific macro inclusion of the version.h just like the autoconf.h, so that the kernel version is accessible everywhere. Signed-off-by: Yong Cong Sin <[email protected]>
No need to include version.h manually in files. Signed-off-by: Yong Cong Sin <[email protected]>
|
I would support option 2, preferably. Definitely will become relevant when we have people looking at migrating from LTSv2 to LTSv3 (or any other recent release, for that matter), cc @kartben And as @ycsin mentions, people will want to run test suites, test harnesses with boards, etc, to ensure that tests are passing on old version and new version before making the leap. So we have C/C++ source conditional compilation. What about CMake conditional compilation? E.g. currently we can access Kconfig constants within Thoughts, @tejlmand? |
| # @Intent: Set compiler specific macro inclusion of VERSION_H | ||
| zephyr_compile_options("SHELL: $<TARGET_PROPERTY:compiler,imacros> ${VERSION_H}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK with change except for this, should remain an include file which users #include if they need it. Having it in kernel.h I am undecided upon as it seems likely that some codebase or library somewhere will have a conflicting define
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is the essence of the second way. Do you think name spacing the macros in the version.h (i.e. ZEPHYR_*) would help with mitigating the potential conflict?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this.
Code should include what it needs, so if the code requires version.h, then it should include version.h.
I don't see why version.h is more special than kernel.h, errno.h, or string.h which are includes you find almost everywhere.
You can access the version from cmake already: -> |
Just a sample. Signed-off-by: Yong Cong Sin <[email protected]>
0cc95a4 to
56e84ee
Compare
|
Please rebase and address the failed CI checks |
tejlmand
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| unset(${type}_VERSION_WITHOUT_TWEAK) | ||
| endforeach() | ||
|
|
||
| set(VERSION_H ${PROJECT_BINARY_DIR}/include/generated/version.h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not the right location for this piece of information.
This file is used for CMake and is used both for Zephyr's kernel version, Application version, but can also be used by downstream users.
The intention of this CMake code is to parse a VERSION file (Zephyr, app, downstream project, etc.) and define corresponding CMake variables.
The VERSION_H is a Zephyr code specific header and thus belongs more correctly where it is used today.
Notice also that this call:
Lines 558 to 563 in 657462d
| COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} | |
| -DOUT_FILE=${VERSION_H} | |
| -DVERSION_TYPE=KERNEL | |
| -DVERSION_FILE=${ZEPHYR_BASE}/VERSION | |
| ${build_version_argument} | |
| -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake |
with your proposal both feeds in VERSION_H as the
OUT_FILE argument, but that the script gen_version_h.cmake actually calls on to version.cmake where you just made that piece on info directly available.
zephyr/cmake/gen_version_h.cmake
Line 32 in 9e8d609
| include(${ZEPHYR_BASE}/cmake/modules/version.cmake) |
| set(VERSION_H ${PROJECT_BINARY_DIR}/include/generated/version.h) |
| # @Intent: Set compiler specific macro inclusion of VERSION_H | ||
| zephyr_compile_options("SHELL: $<TARGET_PROPERTY:compiler,imacros> ${VERSION_H}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this.
Code should include what it needs, so if the code requires version.h, then it should include version.h.
I don't see why version.h is more special than kernel.h, errno.h, or string.h which are includes you find almost everywhere.
include/zephyr/kernel.h
Outdated
| #define ZEPHYR_INCLUDE_KERNEL_H_ | ||
|
|
||
| #if !defined(_ASMLANGUAGE) | ||
| #include "version.h" /* generated by MAKE, at compile time */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not fond of this.
kernel.h itself doesn't require anything / provide anything related to version, so I fail to see why it should suddenly start to include a header so that other parts of code can save a single include line.
Doing this will have a severe impact on incremental builds.
On incremental builds, then only code that contains actual changes (or headers they include) will rebuild if there is a need.
But including version.h in kernel.h means that everyone will depend on version.h, and thus commiting a foo.txt, unrelated to other files will cause everything to rebuild.
Today:
$ cmake -GNinja -DBOARD=nrf52840dk_nrf52840 -Bbuild samples/hello_world
$ ninja -C build
$ ninja: Entering directory `build'
...
[134/134] Linking C executable zephyr/zephyr.elf
Memory region Used Size Region Size %age Used
FLASH: 18152 B 1 MB 1.73%
RAM: 5580 B 256 KB 2.13%
IDT_LIST: 0 GB 2 KB 0.00%
$ ninja -C build
ninja: Entering directory `build'
ninja: no work to do.
$ touch foo.txt; git add foo.txt; git commit -s -m"File added"
$ ninja -C build
ninja: Entering directory `build'
[1/9] Generating include/generated/version.h
-- Zephyr version: 3.5.0-rc1 (/projects/github/ncs/zephyr), build: v3.5.0-rc1-45-gb59168b4833f
[9/9] Linking C executable zephyr/zephyr.elf
Memory region Used Size Region Size %age Used
FLASH: 18152 B 1 MB 1.73%
RAM: 5580 B 256 KB 2.13%
IDT_LIST: 0 GB 2 KB 0.00%
Note, that the new file causes a new commit, which generates a new version.h, but only files actually using version.h needs to be recompiled, and thus linked.
Just 9 build step.
If kernel.h includes version.h, then almost everything will rebuild.
Result of doing the #include "version.h" change in my repo,
$ ninja -C build
ninja: Entering directory `build'
ninja: no work to do.
$ touch foo.txt; git add foo.txt; git commit -s -m"File added"
$ ninja -C build;
ninja: Entering directory `build'
[1/89] Generating include/generated/version.h
-- Zephyr version: 3.5.0-rc1 (/projects/github/ncs/zephyr), build: v3.5.0-rc1-45-gdf07a813c711
[89/89] Linking C executable zephyr/zephyr.elf
Memory region Used Size Region Size %age Used
FLASH: 18152 B 1 MB 1.73%
RAM: 5580 B 256 KB 2.13%
IDT_LIST: 0 GB 2 KB 0.00%
@tejlmand has a point Unneeded rebuilds are no good. I think the biggest concern was that I wonder if we could deprecate the old That might be the second best solution and only requires a bit of patience. But it would definitely be good to get in before LTSv3. |
that sounds like a good suggestion. |
|
@tejlmand Q: wouldn't it make sense for the software being compiled to know the version of the kernel? To me the software should be able to 'just know' the kernel version without including anything, just like the |
No, Kconfig symbols would stay set to the version that was used to configure it, that would mean if you configured a project with 3.5, they would show 3.5, if you then just switched your zephyr version without deleting the build to version 3.0 and built it again, it would still show 3.5, likewise if you changed to 4.1 and did the same, it would still show 3.5 |
After working on #59981 & quite a bit of adaptation work to support multiple Zephyr versions that involve breaking changes, i.e. #51217 & #45417, it becomes clear that having access to the Zephyr kernel version can be handy:
This PR demonstrates two ways to achieve this:
version.hin thezephyr/kernel.h- so any application that includes the kernel header will have access to its versionversion.has part of the compile command just like theautoconf.h- so any application built out of Zephyr build system will have access to the kernel version, just like the Kconfigs.The 2nd commit might be a better way, as it allows all Zephyr compiled application to access the kernel version & it reduces the chance of namespace conflict.
Would love to have some comments on this.