Message ID | 20241119-pks-meson-v8-3-809bf7f042f3@pks.im (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Modernize the build system | expand |
Patrick Steinhardt <ps@pks.im> writes: > While at it, change the format of the version file by removing the > spaces around the equals sign. This may cause third-parties that act on the contents of the output for their own purpose (read: may break distro scripts), but that is part of packaging third-party software for a distro, so it may not be considered a regression by them ;-) > +if test "$#" -ne 3 > +then > + echo "USAGE: $0 <SOURCE_DIR> <INPUT> <OUTPUT>" >&2 > + exit 1 > +fi > + > +SOURCE_DIR="$1" > +INPUT="$2" > +OUTPUT="$3" > + > +if ! test -f "$INPUT" > +then > + echo "Input is not a file: $INPUT" >&2 > + exit 1 > +fi Just a taste thing, which does not warrant a reroll on its own, but when redirecting to the standard error stream, writing >&2 early on the command line is easier to signal that we are reading an error message, e.g. echo >&2 "This is an error message." > +GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." > +export GIT_CEILING_DIRECTORIES Interesting. Presumably this is to prevent a foreign project having a tarball extract of us in its subdirectory, which would be a good protection. > # First see if there is a version file (included in release tarballs), > # then try git-describe, then default. > -if test -f version > +if test -f "$SOURCE_DIR"/version > then > - VN=$(cat version) || VN="$DEF_VER" > -elif { test -d "${GIT_DIR:-.git}" || test -f .git; } && > - VN=$(git describe --match "v[0-9]*" HEAD 2>/dev/null) && > + VN=$(cat "$SOURCE_DIR"/version) || VN="$DEF_VER" > +elif { test -d "$SOURCE_DIR/.git" || test -d "${GIT_DIR:-.git}" || test -f "$SOURCE_DIR"/.git; } && The line has grown a bit too long... > + VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) && > case "$VN" in > *$LF*) (exit 1) ;; > v[0-9]*) > - git update-index -q --refresh > - test -z "$(git diff-index --name-only HEAD --)" || > + git -C "$SOURCE_DIR" update-index -q --refresh > + test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" || > VN="$VN-dirty" ;; VN matching this case arm is a good sign that we have "git" available, so not squelching "Command git not found" here is acceptable, with or without this patch. > esac > then > @@ -26,15 +44,31 @@ else > VN="$DEF_VER" > fi > > -VN=$(expr "$VN" : v*'\(.*\)') > +GIT_BUILT_FROM_COMMIT=$(git -C "$SOURCE_DIR" rev-parse -q --verify HEAD 2>/dev/null) The 2>/dev/null here is required and is good. Even if the source-dir is git controlled, if we do not have an installed Git available, we set GIT_BUILT_FROM_COMMIT to an empty string, as we cannot tell which commit we are building from (yet). > +GIT_DATE=$(git -C "$SOURCE_DIR" show --quiet --format='%as') This needs 2>/dev/null to squelch the case where we have no installed git. I suspect "%cs" is more in line with the spirit of GIT_DATE if I understand its purpose, i.e. "this is the time this version was recorded in the Git history, with the intention to give it the public" and better than "%as". > +GIT_VERSION=$(expr "$VN" : v*'\(.*\)') I think VN is now set by the if/else cascade above to a string that begins with 'v', as lnog as the maintainer makes sure that their tags begin with 'v' (or a distro person prepares the 'version' file to honor the convention), so this should be a safething to do. > +if test -z "$GIT_USER_AGENT" > +then > + GIT_USER_AGENT=git/$GIT_VERSION Not required by the language, but Documentation/CodingGuidelines encourages you to dq the RHS of this assignment. > +fi > + > +read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trailing <<EOF > +$(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ') > +EOF And because GIT_VERSION generation is safe above, this probably is safe, too. In the ancient days, we had tags like "v0.99.9g" which may not match the above convention, but with the understanding that we establish an official convention going forward (i.e. we allow up to four numbers, the rest is discarded so do not use more than four), it is OK. Who wants these broken-out versions and are they fine with up-to-four limitation? Just being curious. > diff --git a/contrib/buildsystems/git-version.in b/contrib/buildsystems/git-version.in > new file mode 100644 > index 0000000000000000000000000000000000000000..9750505ae77685ebb31a38468caaf13501b6739d > --- /dev/null > +++ b/contrib/buildsystems/git-version.in > @@ -0,0 +1 @@ > +@GIT_MAJOR_VERSION@.@GIT_MINOR_VERSION@.@GIT_MICRO_VERSION@ And this one seems to discard the fourth number, so those who prepares VN to contain the fourth digit to differenciate a new version with previous ones would be disappointed. Similarly, because this requires the third number, we cannot change the versioning scheme at 3.0 boundary to say "3.1 is the next version after 3.0". As this is merely setting the rule for our future, perhaps we want to be consistently allow and require N dot-separated numbers everywhere (e.g., we allow and require 3 numbers, not 2, not 4, but exactly 3 numbers)? Thanks.
diff --git a/GIT-VERSION-FILE.in b/GIT-VERSION-FILE.in new file mode 100644 index 0000000000000000000000000000000000000000..3789a48a34a3f9e37531fc24b577ffe3c657a3e9 --- /dev/null +++ b/GIT-VERSION-FILE.in @@ -0,0 +1 @@ +GIT_VERSION=@GIT_VERSION@ diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 78e8631f677bbebe8f18d83191f0fd014465563e..16f23d44873462aeb0fdb6a928f89fa32786bbbf 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,23 +1,41 @@ #!/bin/sh -GVF=GIT-VERSION-FILE DEF_VER=v2.47.GIT LF=' ' +if test "$#" -ne 3 +then + echo "USAGE: $0 <SOURCE_DIR> <INPUT> <OUTPUT>" >&2 + exit 1 +fi + +SOURCE_DIR="$1" +INPUT="$2" +OUTPUT="$3" + +if ! test -f "$INPUT" +then + echo "Input is not a file: $INPUT" >&2 + exit 1 +fi + +GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." +export GIT_CEILING_DIRECTORIES + # First see if there is a version file (included in release tarballs), # then try git-describe, then default. -if test -f version +if test -f "$SOURCE_DIR"/version then - VN=$(cat version) || VN="$DEF_VER" -elif { test -d "${GIT_DIR:-.git}" || test -f .git; } && - VN=$(git describe --match "v[0-9]*" HEAD 2>/dev/null) && + VN=$(cat "$SOURCE_DIR"/version) || VN="$DEF_VER" +elif { test -d "$SOURCE_DIR/.git" || test -d "${GIT_DIR:-.git}" || test -f "$SOURCE_DIR"/.git; } && + VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) && case "$VN" in *$LF*) (exit 1) ;; v[0-9]*) - git update-index -q --refresh - test -z "$(git diff-index --name-only HEAD --)" || + git -C "$SOURCE_DIR" update-index -q --refresh + test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" || VN="$VN-dirty" ;; esac then @@ -26,15 +44,31 @@ else VN="$DEF_VER" fi -VN=$(expr "$VN" : v*'\(.*\)') +GIT_BUILT_FROM_COMMIT=$(git -C "$SOURCE_DIR" rev-parse -q --verify HEAD 2>/dev/null) +GIT_DATE=$(git -C "$SOURCE_DIR" show --quiet --format='%as') +GIT_VERSION=$(expr "$VN" : v*'\(.*\)') +if test -z "$GIT_USER_AGENT" +then + GIT_USER_AGENT=git/$GIT_VERSION +fi + +read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trailing <<EOF +$(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ') +EOF + +sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ + -e "s|@GIT_DATE@|$GIT_DATE|" \ + -e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \ + -e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \ + -e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \ + -e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \ + -e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \ + -e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \ + "$INPUT" >"$OUTPUT"+ -if test -r $GVF +if ! test -f "$OUTPUT" || ! cmp "$OUTPUT"+ "$OUTPUT" >/dev/null then - VC=$(sed -e 's/^GIT_VERSION = //' <$GVF) + mv "$OUTPUT"+ "$OUTPUT" else - VC=unset + rm "$OUTPUT"+ fi -test "$VN" = "$VC" || { - echo >&2 "GIT_VERSION = $VN" - echo "GIT_VERSION = $VN" >$GVF -} diff --git a/Makefile b/Makefile index c3b546235a177cb090f8f6adcb13e07a1ccdcef1..456dfa0311b53627e6f5550c36a503808a4e5e3e 100644 --- a/Makefile +++ b/Makefile @@ -592,7 +592,10 @@ include shared.mak # Disable -pedantic compilation. GIT-VERSION-FILE: FORCE - @$(SHELL_PATH) ./GIT-VERSION-GEN + @OLD=$$(cat $@ 2>/dev/null || :) && \ + $(SHELL_PATH) ./GIT-VERSION-GEN "$(shell pwd)" GIT-VERSION-FILE.in $@ && \ + NEW=$$(cat $@ 2>/dev/null || :) && \ + if test "$$OLD" != "$$NEW"; then echo "$$NEW" >&2; fi -include GIT-VERSION-FILE # Set our default configuration. diff --git a/ci/test-documentation.sh b/ci/test-documentation.sh index 02b3af394117f840e078479ca60030141e47f998..6c018b673e0563fa5589195a77804c91deb93515 100755 --- a/ci/test-documentation.sh +++ b/ci/test-documentation.sh @@ -6,7 +6,7 @@ . ${0%/*}/lib.sh filter_log () { - sed -e '/^GIT_VERSION = /d' \ + sed -e '/^GIT_VERSION=/d' \ -e "/constant Gem::ConfigMap is deprecated/d" \ -e '/^ \* new asciidoc flags$/d' \ -e '/stripped namespace before processing/d' \ diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 8b0020edeba289e5eaa15a5452013fa2e4c3ed33..752479cac59d3833e7fff9239ebea75179692bf4 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -83,23 +83,12 @@ if(NOT SH_EXE) "On Windows, you can get it as part of 'Git for Windows' install at https://gitforwindows.org/") endif() -#Create GIT-VERSION-FILE using GIT-VERSION-GEN -if(NOT EXISTS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE) - message("Generating GIT-VERSION-FILE") - execute_process(COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/GIT-VERSION-GEN - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -endif() - -#Parse GIT-VERSION-FILE to get the version -file(STRINGS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE git_version REGEX "GIT_VERSION = (.*)") -string(REPLACE "GIT_VERSION = " "" git_version ${git_version}) -string(FIND ${git_version} "GIT" location) -if(location EQUAL -1) - string(REGEX MATCH "[0-9]*\\.[0-9]*\\.[0-9]*" git_version ${git_version}) -else() - string(REGEX MATCH "[0-9]*\\.[0-9]*" git_version ${git_version}) - string(APPEND git_version ".0") #for building from a snapshot -endif() +message("Generating Git version") +execute_process(COMMAND ${SH_EXE} "${CMAKE_SOURCE_DIR}/GIT-VERSION-GEN" + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/contrib/buildsystems/git-version.in" + "${CMAKE_BINARY_DIR}/git-version") +file(STRINGS "${CMAKE_BINARY_DIR}/git-version" git_version) project(git VERSION ${git_version} diff --git a/contrib/buildsystems/git-version.in b/contrib/buildsystems/git-version.in new file mode 100644 index 0000000000000000000000000000000000000000..9750505ae77685ebb31a38468caaf13501b6739d --- /dev/null +++ b/contrib/buildsystems/git-version.in @@ -0,0 +1 @@ +@GIT_MAJOR_VERSION@.@GIT_MINOR_VERSION@.@GIT_MICRO_VERSION@
Our "GIT-VERSION-GEN" script always writes the "GIT-VERSION-FILE" into the current directory, where the expectation is that it should exist in the source directory. But other build systems that support out-of-tree builds may not want to do that to keep the source directory pristine, even though CMake currently doesn't care. Refactor the script such that it won't write the "GIT-VERSION-FILE" directly anymore, but instead knows to replace @PLACEHOLDERS@ in an arbitrary input file. This allows us to simplify the logic in CMake to determine the project version, but can also be reused later on in order to generate other files that need to contain version information like our "git.rc" file. While at it, change the format of the version file by removing the spaces around the equals sign. Like this we can continue to include the file in our Makefiles, but can also start to source it in shell scripts in subsequent steps. Furthermore, we already start to replace some placeholders that are not yet of relevance in this commit. These are going to become relevant in subsequent steps, as well. Signed-off-by: Patrick Steinhardt <ps@pks.im> --- GIT-VERSION-FILE.in | 1 + GIT-VERSION-GEN | 64 ++++++++++++++++++++++++++++--------- Makefile | 5 ++- ci/test-documentation.sh | 2 +- contrib/buildsystems/CMakeLists.txt | 23 ++++--------- contrib/buildsystems/git-version.in | 1 + 6 files changed, 62 insertions(+), 34 deletions(-)