Skip to content
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

build system: add machine-readable RIOT_VERSION_CODE macro #16765

Merged
merged 2 commits into from
Sep 22, 2021

Conversation

benpicco
Copy link
Contributor

@benpicco benpicco commented Aug 21, 2021

Contribution description

For external modules it can be handy to determine the RIOT version using a define.
Linux provides a KERNEL_VERSION macro for that. It splits a 64 bit version number into 16 bit mayor version, 16 bit minor version 16 bit patch level and user defined 16 bit extraversion.

This also works for RIOT's versioning scheme, so let's adopt the same scheme.

Testing procedure

A new unit test is provided in tests/unittests/tests-kernel_defines.

Issues/PRs references

https://forum.riot-os.org/t/detect-riot-os-version/3329

@benpicco benpicco requested a review from aabadie August 21, 2021 12:09
@github-actions github-actions bot added Area: build system Area: Build system Area: core Area: RIOT kernel. Handle PRs marked with this with care! Area: tests Area: tests and testing framework labels Aug 21, 2021
@benpicco benpicco requested a review from maribu August 21, 2021 12:10
@benpicco benpicco force-pushed the RIOT_VERSION_CODE branch 3 times, most recently from 4347cc5 to 5fe93c9 Compare August 21, 2021 12:30
@maribu
Copy link
Member

maribu commented Aug 21, 2021

Note that for Linux stable versions the 8 bit counter had to few bits. I don't think that RIOT will have stable releases with so many bugfix releases any time soon. But since this is hardly something that is going into hot code paths, why not pack 32 bit, 16 bit, and 16 bit into a 64 bit number. Just to reduce the chance that a future version of us travels back in time to kick our asses.

@aabadie
Copy link
Contributor

aabadie commented Aug 21, 2021

This PR expects that RIOT_VERSION is always containing something like 2021.10 or 2021.10.1 but on a development branch like master, RIOT_VERSION contains something like 2021.10-devel-130-g934c87 and on a different branch it also contains the branch name.
With the example above, 2021.10-devel-130-g934c87, the resulting RIOT_VERSION_CODE macro would contain KERNEL_VERSION\(2021,10,0\) which returns a wrong result since the master branch doesn't correspond to an exact RIOT release version but a development version.
We could keep the extra devel-130-g934c87 in the result (e.g KERNEL_VERSION\(2021,10,0devel-130-g934c87\)) but then the KERNEL_VERSION would have to be adapted (and I don't know how).

@benpicco
Copy link
Contributor Author

benpicco commented Aug 21, 2021

I don't think there is another way to do it - arbitrary branches can't be encoded in a numerical format.

I would expect external modules to only build against released branches anyway.

@fjmolinas
Copy link
Contributor

I don't think there is another way to do it - arbitrary branches can't be encoded in a numerical format.

I would expect external modules to only build against released branches anyway.

Lets just add a comment that this only applies for released branches, and include this.

@kaspar030
Copy link
Contributor

kaspar030 commented Aug 24, 2021

should we think of some meaning of "version"? like, make it somehow semantic? give it two numbers, one for "breaking changes", one for additions?

edit and make CI check that any PR marked "API change" increases the number? and add a document that explains any breaking changes and how to fix older code?

@benpicco
Copy link
Contributor Author

That's actually hard to track and the reason why most projects abandoned the idea.

Also this PR is not about changing the versioning scheme that RIOT uses, but rather just adding a macro to check the version at compile time.

@kaspar030
Copy link
Contributor

That's actually hard to track and the reason why most projects abandoned the idea.

semver you mean? not sure about "most projects abandoned the idea". Also, if it is hard to track when our public API changes, we have a problem.

I agree that this PR just allows checking the version in code. we can discuss the actual versioning scheme elsewhere.

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

2021.10-devel-130-g934c87

Alternatively, a workaround could be that a string like this resolves to KERNEL_VERSION(2021, 9, 130). Of course for different devel branches this could yield the same result.

@kaspar030
Copy link
Contributor

Of course for different devel branches this could yield the same result.

do we want to support finer grained versioning than our releases? dev branches could resolve to e.g., KERNEL_VERSION(2021,9,9999)?

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

do we want to support finer grained versioning than our releases? dev branches could resolve to e.g., KERNEL_VERSION(2021,9,9999)?

Alternatively the actual release could have an extra flag (1) and the devel describe towards it has it just unset.

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

And for testing it could be beneficial to also have comparability to dev branches at least.

@benpicco
Copy link
Contributor Author

do we want to support finer grained versioning than our releases?

Where are those numbers supposed to come from?

What I could imagine could be a RIOT_EXTRA_VERSION ?= 0 and then KERNEL_VERSION(mayor, minor, patch, extra) for downstream forks.

e.g. we have a 2021.07-mlpa-5 branch that is the 5th iteration of the base branch based on the 2021.07 branch.

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

Where are those numbers supposed to come from?

git describe counts the number of commits from the base tag. That's where the 130 in my original proposal came.

@aabadie
Copy link
Contributor

aabadie commented Aug 24, 2021

Should this PR also take into account the fact that on the CI (or when building with RIOT_CI_BUILD=1), RIOT_VERSION contains only buildtest ?

@benpicco
Copy link
Contributor Author

benpicco commented Aug 24, 2021

Since the unit test does some sanity checks on RIOT_VERSION_CODE, those would then fail on CI.
Is there no way to get the RIOT version on CI?

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

Is there no way to get the RIOT version on CI?

We could use the verbatim version, we use in devel branches, but then the build size would not be reliable anymore.

@benpicco
Copy link
Contributor Author

We could use the verbatim version, we use in devel branches, but then the build size would not be reliable anymore.

git describe | sed -E 's/([0-9]+).([0-9]+).*/\1.\2/'

always only returns the release branch

@miri64
Copy link
Member

miri64 commented Aug 24, 2021

git describe | sed -E 's/([0-9]+).([0-9]+).*/\1.\2/'

always only returns the release branch

  1. Why the excessive use of sed?
    git describe | grep -Eo '([0-9]{4}).([0-9]{2})'
    
  2. That would be imprecise. All RCs and all commits towards a release would then be versioned as THE release.

@benpicco
Copy link
Contributor Author

  1. That would be imprecise. All RCs and all commits towards a release would then be versioned as THE release.

It would still increase the precision over calling them all buildtest

Makefile.include Outdated Show resolved Hide resolved
core/include/kernel_defines.h Outdated Show resolved Hide resolved
Makefile.include Outdated Show resolved Hide resolved
Makefile.include Outdated
Comment on lines 521 to 523
# Generate machine readable RIOT VERSION macro
RIOT_VERSION_CODE ?= $(shell echo ${RIOT_VERSION} | \
sed -E 's/([0-9]+).([0-9]+).?([0-9]+)?.*/KERNEL_VERSION\\\(\1,\2,0\3,${RIOT_EXTRAVERSION}\\\)/')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check how often this is executed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--- a/Makefile.include
+++ b/Makefile.include
@@ -519,7 +519,7 @@ ifneq (,$(RIOT_VERSION_OVERRIDE))
 endif
 
 # Generate machine readable RIOT VERSION macro
-RIOT_VERSION_CODE ?= $(shell echo ${RIOT_VERSION} | \
+RIOT_VERSION_CODE ?= $(shell echo eval 1>&2 && echo ${RIOT_VERSION} | \
                       sed -E 's/([0-9]+).([0-9]+).?([0-9]+)?.*/KERNEL_VERSION\\\(\1,\2,0\3,${RIOT_EXTRAVERSION}\\\)/')
 
 # Set module by prepending APPLICATION name with 'application_'.

prints eval exactly once

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed with piping the to ${RIOTBASE}/test.eval instead of stderr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(ping @kaspar030)

core/include/kernel_defines.h Outdated Show resolved Hide resolved
core/include/kernel_defines.h Outdated Show resolved Hide resolved
@aabadie
Copy link
Contributor

aabadie commented Sep 21, 2021

I think the RIOT_VERSION_CODE should be added to the DOCKER_ENV_VARS:

export DOCKER_ENV_VARS += \

otherwise I think this won't work when BUILD_IN_DOCKER is set to 1.

@@ -476,6 +476,8 @@ endif
# set some settings useful for continuous integration builds
ifeq ($(RIOT_CI_BUILD),1)
RIOT_VERSION ?= buildtest
# set a dummy version number
RIOT_VERSION_CODE ?= RIOT_VERSION_NUM\(2042,5,23,0\)
Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if somone changes the release cycle may(5) in 2042 may be a regular Release ->

    RIOT_VERSION_CODE ?= RIOT_VERSION_NUM\(2042,99,23,0\)

Is that Feb 2050?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes, if we change for a semantic versioning scheme, but keep the year number for backwards compatibility. IMHO this is not really important. The main thing, is that the version in CI is static and since it is not planned to use this macro in-tree, it will never come to a versioning conflict within the CI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this macro might have some use inside packages that have a source that has the changes to make them work with riot upstream.
Some packages are tested in the CI ?afaik?

Copy link
Member

@miri64 miri64 Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a package requires a different RIOT version, a different version of that package should be used. If we allow RIOT_VERSION_CODE within things the CI is using, it has to be non-static and we would lose as such both caching advantages and size comparison capabilities offered by the CI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(i.e. we would loose deterministic build results within the CI)

core/include/kernel_defines.h Outdated Show resolved Hide resolved
core/include/kernel_defines.h Outdated Show resolved Hide resolved
core/include/kernel_defines.h Outdated Show resolved Hide resolved
@miri64
Copy link
Member

miri64 commented Sep 21, 2021

You may squash after addressing my last change request.

@benpicco benpicco added the Type: new feature The issue requests / The PR implemements a new feature for RIOT label Sep 21, 2021
@chrysn
Copy link
Member

chrysn commented Sep 21, 2021

Summarizing some chat exchange, I still think that rather than having anyone rely on particular versions we should rather expose features declared in, say, <apifeatures.h>, that indicate that a particular change was enacted. Unlike versions, this would naturally work with any number of branches, releases or merges, for as long as these names (eg. #define RIOT_APIFEATURE_CPUINIT_CALLED_FROM_STARTUP) are unique. They'd be kept indefinitely (but might after many releases be marked for deprecation in order to hint to users that unless they use really old versions they can just as well assume the feature to be present).

Sadly I don't have the time right now to follow this through completely, but I still suggest that it be held as an available option for cases in which version number checking reaches its limitations.

@miri64
Copy link
Member

miri64 commented Sep 21, 2021

Sadly I don't have the time right now to follow this through completely, but I still suggest that it be held as an available option for cases in which version number checking reaches its limitations.

I think having something like you propose can be done in addition to the proposal here. RIOT_VERSION_CODE would then be more coarse grained, while feature defines / API versions would be used for finer grained code checking.

@benpicco
Copy link
Contributor Author

The problem I see with that approach is that it depends on the contributors to always keep the apifeatures.h file up to date.

The version number on the other hand changes automatically and external boards/modules are not at the mercy of the attentiveness of contributors to flag possible API changes properly.

@fjmolinas
Copy link
Contributor

@kaspar030 are you happy with the current state?

@kaspar030
Copy link
Contributor

@kaspar030 are you happy with the current state?

Medium, but the CI issues are gone.

@miri64 miri64 merged commit ea8e632 into RIOT-OS:master Sep 22, 2021
@miri64
Copy link
Member

miri64 commented Sep 22, 2021

Might be a good idea to add a coccinelle rule, to prevent further merging of RIOT_VERSION_CODE to master.

@benpicco benpicco deleted the RIOT_VERSION_CODE branch September 22, 2021 10:56
@benpicco benpicco added this to the Release 2021.10 milestone Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: build system Area: Build system Area: core Area: RIOT kernel. Handle PRs marked with this with care! Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants