From 69bace22205b4bb01673f7c9873f57a43bd6a0f7 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 1 Jan 2025 01:16:48 +0100 Subject: [PATCH] build: Revamp git versioning. This rewrites GIT-VERSION-GEN and renames it to version-gen.sh. The main difference is that the script now generates version.c rather than version.h, speeding up the build because switching branches or transitioning from a clean to a dirty work-tree (or vice versa) changes the version string. Before the patch, all files which included version.h were recompiled. With the patch applied, only the short version.c needs to be recompiled. The generated version,c defines one function which returns the single-line version string and a second function which returns the multi-line version information (author, copyright, git URL etc). This information is now passed to version-gen.sh via environment variables. The CPP macros we had before are removed. --- .gitignore | 1 - GIT-VERSION-GEN | 42 ------------------------------- Makefile.real | 61 +++++++++++++++++++++++++++------------------ configure.ac | 2 +- m4/lls/copyright.m4 | 28 +++++++++++++++++---- string.c | 18 +++---------- string.h | 2 ++ version-gen.sh | 43 ++++++++++++++++++++++++++++++++ 8 files changed, 110 insertions(+), 87 deletions(-) delete mode 100755 GIT-VERSION-GEN create mode 100755 version-gen.sh diff --git a/.gitignore b/.gitignore index 8f8d0af7..318f5519 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,4 @@ web_sync confdefs.h conftest conftest.c -git-version.h *-local* diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN deleted file mode 100755 index b8abff35..00000000 --- a/GIT-VERSION-GEN +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -(($# > 1)) && { echo >&2 "usage: $0 []"; exit 1; } -GVF="$1" - -DEF_VER="unnamed_version" -LF=' -' - -# First see if there is a version file (included in release tarballs), -# then try git-describe, then gitweb, then default. -if [[ -f VERSION ]]; then - VN=$(cat VERSION) || VN="$DEF_VER" -elif [[ -d .git || -f .git ]] && - VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && - case "$VN" in - *$LF*) (exit 1) ;; - v[0-9]*) - git update-index -q --refresh &>/dev/null - test -z "$(git diff-index --name-only HEAD --)" || - VN="$VN-dirty" ;; - esac -then - VN=$(echo "$VN" | sed -e 's/-/./g'); -elif [[ "$PWD" =~ paraslash-[a-f0-9]{1,} ]]; then - VN="${PWD#*-}" -else - VN="$DEF_VER" -fi - -VN=$(expr "$VN" : v*'\(.*\)') -echo "$VN" - -[[ -z "$GVF" ]] && exit 0 -if [[ -r "$GVF" ]]; then - pattern='^#define GIT_VERSION "' - VC=$(grep "$pattern" < "$GVF" | sed -e "s/$pattern//; s/\"$//") - [[ "$VN" == "$VC" ]] && exit 0 -fi -echo >&2 "new git version: $VN" -echo "/** \\file ${GVF##*/} Auto-generated version file. Do not edit. */" >$GVF -echo "#define GIT_VERSION \"$VN\"" >> $GVF diff --git a/Makefile.real b/Makefile.real index 33b9ba46..3a6aea4c 100644 --- a/Makefile.real +++ b/Makefile.real @@ -9,24 +9,38 @@ endif .ONESHELL: .SHELLFLAGS := -ec +PACKAGE := paraslash +DEFINES = \ + $(call DEFINE,PACKAGE,$(PACKAGE)) \ + $(call DEFINE,SLOGAN,network audio streaming) \ + $(call DEFINE,AUTHOR,Andre Noll) \ + $(call DEFINE,EMAIL,maan@tuebingen.mpg.de) \ + $(call DEFINE,COPYRIGHT_YEAR,1997) \ + $(call DEFINE,PROJECT_WEBSITE,https://people.tuebingen.mpg.de/maan/$(PACKAGE)/) \ + $(call DEFINE,CLONE_URL,https://git.tuebingen.mpg.de/$(PACKAGE)) \ + $(call DEFINE,GITWEB_URL,https://git.tuebingen.mpg.de/$(PACKAGE).git) \ + $(call DEFINE,HOME_URL,https://people.tuebingen.mpg.de/maan/) \ + $(call DEFINE,LICENSE,GPL-2.0) \ + $(call DEFINE,LICENSE_URL,https://www.gnu.org/licenses/) +DEFINE = -D '$(1)=$(2)' +M4 += $(DEFINES) +DEFINE = $(1)='$(2)' +SHELL_DEFINES := $(DEFINES) + LOGLEVELS := LL_DEBUG,LL_INFO,LL_NOTICE,LL_WARNING,LL_ERROR,LL_CRIT,LL_EMERG SEVERITIES := \"debug\",\"info\",\"notice\",\"warning\",\"error\",\"crit\",\"emerg\" vardir := /var/paraslash mandir := $(datarootdir)/man/man1 MKDIR_P := mkdir -p -build_date := $(shell date) uname_s := $(shell uname -s 2>/dev/null || echo "UNKNOWN_OS") -uname_rs := $(shell uname -rs) -cc_version := $(shell $(CC) --version | head -n 1) -GIT_VERSION := $(shell ./GIT-VERSION-GEN git-version.h) -COPYRIGHT_YEAR := 2025 ifeq ("$(origin O)", "command line") build_dir := $(O) else build_dir := build endif +version_dir := $(build_dir)/version-gen object_dir := $(build_dir)/objects dep_dir := $(build_dir)/deps man_dir := $(build_dir)/man/man1 @@ -36,6 +50,7 @@ lls_m4_dir := m4/lls test_dir := t yy_src_dir := yy yy_build_dir := $(build_dir)/yy +GIT_VERSION := $(shell $(SHELL_DEFINES) ./version-gen.sh $(PACKAGE) $(version_dir)/version.c) executables := recv filter audioc write afh ifneq ($(CRYPTOLIB),) @@ -47,7 +62,7 @@ ifneq ($(CRYPTOLIB),) crypt_common base64 ipc dccp_send fd user_list \ chunk_queue afs aft mood mp score attribute blob \ playlist sched acl send_common udp_send color fec \ - wma_afh wma_common sideband lsu \ + wma_afh wma_common sideband lsu version \ ) ifeq ($(CRYPTOLIB),openssl) server_objs += openssl.o @@ -73,14 +88,14 @@ ifneq ($(CRYPTOLIB),) server_objs += aac_afh.o mp4.o endif upgrade_db_objs := $(addsuffix .o, crypt_common exec fd string \ - upgrade_db base64) + upgrade_db base64 version) endif endif ifneq ($(CRYPTOLIB),) executables += client audiod client_objs := $(addsuffix .o, \ client net string fd lsu sched stdin stdout time sideband client_common \ - buffer_tree crypt_common base64 $(CRYPTOLIB) \ + buffer_tree crypt_common base64 $(CRYPTOLIB) version \ ) ifeq ($(HAVE_READLINE),yes) client_objs += interactive.o @@ -91,7 +106,7 @@ ifneq ($(CRYPTOLIB),) http_recv dccp_recv recv_common fd sched write_common file_write \ audiod_command fecdec_filter client_common udp_recv color fec \ prebuffer_filter bitstream imdct wma_common wmadec_filter \ - buffer_tree sync_filter lsu $(CRYPTOLIB) \ + buffer_tree sync_filter lsu $(CRYPTOLIB) version \ ) audiod_audio_formats := "wma" ifeq ($(NEED_VORBIS_OBJECTS),yes) @@ -133,7 +148,7 @@ ifneq ($(CRYPTOLIB),) endif ifneq ($(HAVE_OSS)-$(HAVE_ALSA),no-no) executables += mixer - mixer_objs := $(addsuffix .o, mixer exec string fd time lsu) + mixer_objs := $(addsuffix .o, mixer exec string fd time lsu version) ifeq ($(HAVE_OSS),yes) mixer_objs += oss_mix.o endif @@ -144,13 +159,13 @@ endif ifeq ($(HAVE_CURSES),yes) executables += gui gui_objs := $(addsuffix .o, exec signal string stat ringbuffer fd \ - gui gui_theme lsu time sched) + gui gui_theme lsu time sched version) endif filter_objs := $(addsuffix .o, \ filter_common wav_filter compress_filter filter string stdin stdout \ sched fd amp_filter fecdec_filter fec lsu prebuffer_filter \ time bitstream imdct wma_common wmadec_filter buffer_tree net \ - sync_filter \ + sync_filter version \ ) ifeq ($(NEED_VORBIS_OBJECTS),yes) filter_objs += oggdec_filter.o @@ -177,6 +192,7 @@ endif recv_objs := $(addsuffix .o, \ http_recv recv_common recv time string net dccp_recv fd sched stdout \ udp_recv buffer_tree afh_recv afh_common wma_afh wma_common mp3_afh \ + version \ ) ifeq ($(NEED_OGG_OBJECTS),yes) recv_objs += ogg_afh_common.o @@ -199,7 +215,7 @@ endif audio_format_handlers := mp3 wma afh_objs := $(addsuffix .o, afh string fd mp3_afh afh_common time wma_afh \ - wma_common) + wma_common version) ifeq ($(NEED_OGG_OBJECTS),yes) afh_objs += ogg_afh_common.o endif @@ -231,7 +247,7 @@ ifeq ($(HAVE_READLINE),yes) wma_afh wma_common mp3_afh recv_common udp_recv http_recv dccp_recv \ filter_common fec bitstream imdct wav_filter compress_filter \ amp_filter prebuffer_filter fecdec_filter wmadec_filter write_common \ - file_write sync_filter lsu interactive \ + file_write sync_filter lsu interactive version \ ) ifeq ($(NEED_OGG_OBJECTS),yes) play_objs += ogg_afh_common.o @@ -269,7 +285,7 @@ ifeq ($(HAVE_READLINE),yes) endif write_objs := $(addsuffix .o, write write_common file_write time fd \ - string sched stdin buffer_tree check_wav) + string sched stdin buffer_tree check_wav version) ifeq ($(NEED_AO_OBJECTS),yes) write_objs += ao_write.o endif @@ -280,7 +296,7 @@ ifeq ($(HAVE_ALSA),yes) write_objs += alsa_write.o endif -audioc_objs := $(addsuffix .o, audioc string lsu net fd time) +audioc_objs := $(addsuffix .o, audioc string lsu net fd time version) ifeq ($(HAVE_READLINE),yes) audioc_objs += buffer_tree.o interactive.o sched.o endif @@ -356,12 +372,8 @@ $(object_dir) $(man_dir) $(dep_dir) $(m4depdir) $(lls_suite_dir) \ $(yy_build_dir): @$(MKDIR_P) $@ -CPPFLAGS += -DCOPYRIGHT_YEAR='"$(COPYRIGHT_YEAR)"' -CPPFLAGS += -DBUILD_DATE='"$(build_date)"' CPPFLAGS += -DLOGLEVELS='$(LOGLEVELS)' CPPFLAGS += -DSEVERITIES=$(SEVERITIES) -CPPFLAGS += -DUNAME_RS='"$(uname_rs)"' -CPPFLAGS += -DCC_VERSION='"$(cc_version)"' CPPFLAGS += -I$(lls_suite_dir) CPPFLAGS += -I$(yy_build_dir) CPPFLAGS += $(lopsub_cppflags) @@ -439,7 +451,7 @@ $(man_dir)/para_%.1: $(lls_suite_dir)/%.lsg.man \ $(lls_m4_dir)/copyright.m4 | $(man_dir) $(call SAY, LLSMAN $<) cat $< $(all_commands) > $@ - $(M4) -D COPYRIGHT_YEAR=$(COPYRIGHT_YEAR) $(lls_m4_dir)/copyright.m4 >> $@ + $(M4) $(lls_m4_dir)/copyright.m4 >> $@ $(object_dir)/%.o: %.c | $(object_dir) @@ -482,8 +494,9 @@ define CC_CMD $(CPPFLAGS) $(STRICT_CFLAGS) $(CFLAGS) $< endef CC_PREREQUISITES := %.c | $(object_dir) $(dep_dir) $(lsg_h) $(yy_h) -# These two have the same prerequisites and the same recipe. There should be a -# better way to write this. +# There should be a # better way to write these. +$(object_dir)/%.o: $(version_dir)/%.c | $(object_dir) + $(CC_CMD) $(object_dir)/%.o: $(CC_PREREQUISITES) $(CC_CMD) $(dep_dir)/%.d: $(CC_PREREQUISITES) @@ -590,7 +603,7 @@ $(tarball) dist tarball: git archive --format=tar --prefix=$(tarball_pfx)/ HEAD \ | tar --delete $(tarball_delete) > $(tarball_pfx).tar $(MKDIR_P) $(tarball_pfx) - ./GIT-VERSION-GEN > $(tarball_pfx)/VERSION + ./version-gen.sh $(PACKAGE_TARNAME) > $(tarball_pfx)/VERSION cp $(autocrap) $(tarball_pfx) tar rf $(tarball_pfx).tar $(tarball_pfx)/* xz -9 $(tarball_pfx).tar diff --git a/configure.ac b/configure.ac index efb96a3b..37d90554 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.61]) -AC_INIT([paraslash], [m4_esyscmd_s(./GIT-VERSION-GEN)], +AC_INIT([paraslash], [m4_esyscmd_s(./version-gen.sh paraslash)], [maan@tuebingen.mpg.de], [], [https://people.tuebingen.mpg.de/maan/paraslash/]) AC_CONFIG_HEADERS([config.h]) diff --git a/m4/lls/copyright.m4 b/m4/lls/copyright.m4 index 9e5c5413..875b649b 100644 --- a/m4/lls/copyright.m4 +++ b/m4/lls/copyright.m4 @@ -1,15 +1,33 @@ .SH COPYRIGHT -Written by Andre Noll +Written by AUTHOR() .br -Copyright (C) COPYRIGHT_YEAR() Andre Noll +Copyright (C) COPYRIGHT_YEAR() - present AUTHOR() .br -License: GNU GPL version 2 +License: LICENSE() +.UR LICENSE_URL() +.UE .br This is free software: you are free to change and redistribute it. .br There is NO WARRANTY, to the extent permitted by law. +.P +Project web page: +.UR PROJECT_WEBSITE() +.UE +.br +Git clone URL: +.UR CLONE_URL() +.UE +.br +Gitweb: +.UR GITWEB_URL() +.UE +.br +Author home page: +.UR HOME_URL() +.UE .br Report bugs to -.MT -Andre Noll +.MT EMAIL() +AUTHOR() .ME diff --git a/string.c b/string.c index 5e8d72bc..5d3be150 100644 --- a/string.c +++ b/string.c @@ -13,7 +13,6 @@ #include "string.h" #include "error.h" -#include "git-version.h" /** * Reallocate an array, abort on failure or bugs. @@ -1107,7 +1106,7 @@ const char *version_single_line(const char *pfx) { static char buf[100]; snprintf(buf, sizeof(buf) - 1, - "para_%s " GIT_VERSION, pfx); + "para_%s %s", pfx, paraslash_version()); return buf; } @@ -1125,18 +1124,9 @@ const char *version_single_line(const char *pfx) */ const char *version_text(const char *pfx) { - static char buf[512]; - - snprintf(buf, sizeof(buf) - 1, "%s\n" - "Copyright (C) " COPYRIGHT_YEAR " Andre Noll\n" - "This is free software with ABSOLUTELY NO WARRANTY." - " See COPYING for details.\n" - "Report bugs to .\n" - "build date: " BUILD_DATE ",\n" - "build system: " UNAME_RS ",\n" - "compiler: " CC_VERSION ".\n", - version_single_line(pfx) - ); + static char buf[1024]; + snprintf(buf, sizeof(buf) - 1, "%s\n%s\n", + version_single_line(pfx), paraslash_info()); return buf; } diff --git a/string.h b/string.h index fe1f49cb..99fa8324 100644 --- a/string.h +++ b/string.h @@ -98,6 +98,8 @@ int skip_cells(const char *s, size_t cells_to_skip, size_t *result); __must_check int strwidth(const char *s, size_t *result); __must_check int sanitize_str(const char *src, size_t max_width, char **result, size_t *width); +const char *paraslash_version(void); +const char *paraslash_info(void); const char *version_single_line(const char *pfx); const char *version_text(const char *pfx); void version_handle_flag(const char *pfx, bool flag); diff --git a/version-gen.sh b/version-gen.sh new file mode 100755 index 00000000..d1641c8f --- /dev/null +++ b/version-gen.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +package="$1" +version_file="$2" + +ver='unnamed_version' +# Try git, version file and gitweb, in this order +if [ -e '.git' -o -e '../.git' ]; then + git_ver=$(git describe --abbrev=4 --always HEAD 2>/dev/null) + [ -z "$git_ver" ] && git_ver="$ver" + # update stat information in index to match working tree + git update-index -q --refresh > /dev/null + # if there are differences (exit code 1), the working tree is dirty + git diff-index --quiet HEAD || git_ver=$git_ver-dirty + ver=$git_ver +elif [ -f VERSION ]; then + ver=$(cat VERSION) +elif [ "${PWD%%-*}" = $package- ]; then + ver=${PWD##*/$package-} +fi +ver=${ver#v} + +echo "$ver" +[ -z "${version_file}" ] && exit 0 +# update version file if necessary +content="const char *${package}_version(void) {return \"$ver\";};" +info=" + \"Copyright (C) $COPYRIGHT_YEAR - present $AUTHOR\\n\" + \"License: $LICENSE <$LICENSE_URL\\n\" + \"This is free software: you are free to change and redistribute it.\\n\" + \"There is NO WARRANTY, to the extent permitted by law.\\n\" + \"\\n\" + \"Project Website: $PROJECT_WEBSITE\\n\" + \"Clone URL: $CLONE_URL\\n\" + \"Gitweb: $GITWEB_URL\\n\" + \"Author Home Page: $HOME_URL\\n\" + \"Send feedback to: $AUTHOR <$EMAIL>\\n\" +" +content="$content +const char *${package}_info(void) {return $info;};" +[ -r "$version_file" ] && printf '%s\n' "$content" | cmp -s - $version_file && exit 0 +[ "$version_file" = "${version_file%/*}" ] || mkdir -p ${version_file%/*} +printf '%s\n' "$content" > $version_file -- 2.39.5