I have a shell script that will create a version information header file, version.h, which looks like
echo -e "\
#pragma once\n\
\n\
#include \"build_config.h\"\n\
\n\
\n\
#define COMMIT_REVISION \"${GIT_HEAD^^}\"\n\
#define COMMIT_FIRST_FOUR_BYTES 0x$(cut -c 1-8 <<< ${GIT_HEAD^^})\n\
#define CHECKOUT_SHA \"${CHECKOUT_SHA}\"\n\
#define CURRENT_SHA \"${CURRENT_SHA}\"\n\
#define DATE_OF_SHA \"${DATE_OF_SHA}\"\n\
#define BUILD_TYPE \"${BUILD_TYPE}\"\n\
\n\
#define BINARY_BASE_NAME BUILD_TYPE \"_\" DATE_OF_SHA \"_\" CURRENT_SHA\n\" > ${1}
The environment variables used in the script are set during the execution of the script file. For instance, GIT_HEAD="$(git rev-parse HEAD)"
The resulting header file the script creates looks like
#pragma once
#include "build_config.h"
#define COMMIT_REVISION "D70B1A73915F11BF5BF3A9D531BF57BA3D58CD73"
#define COMMIT_FIRST_FOUR_BYTES 0xD70B1A73
#define CHECKOUT_SHA "d70b1a73"
#define CURRENT_SHA "d70b1a7391"
#define DATE_OF_SHA "220621"
#define BUILD_TYPE "E"
#define BINARY_BASE_NAME BUILD_TYPE CONTROLLER_CHIP_ID_CHAR CONTROLLER_CHIP_VERSION_CHAR DATE_OF_SHA "_" CURRENT_SHA
Within a makefile is there a way to use the macro BINARY_BASE_NAME within a target recipe? Something like
bin/$(BINARY_BASE_NAME): bin/binary_object.o version.h
$(V)cp bin/object.o bin/$(BINARY_BASE_NAME)
Would I need to export BINARY_BASE_NAME as an environment variable? Can the makefile use the macro directly?
CodePudding user response:
Not really. Make is not a C compiler, and a header file is not a makefile: make can't parse C code.
You could try to play a trick like, write a C file that included the above file then simply assigned it, and only run that C file through the preprocessor and not the compiler. It would be kind of a hack. Something like this MIGHT work:
# trick to get a variable $S that contains a single space
E :=
S := $E $E
include version.mk
_basename := $(subst ",,$(subst $S,,$(_basename)))
version.mk : version.h
(echo '#include "$<"'; echo '_basename := BINARY_BASE_NAME') > [email protected]
$(CC) $(CFLAGS) -E [email protected] > $@
it might work.
ETA
Just to promote my comment below: the best way to do this is to either write another shell script that generates the makefile info like version.mk
, or else enhance the shell script that creates version.h
so that it also writes the same information to a file version.mk
. That would be a lot safer and more reliable.
CodePudding user response:
Pushing MadScientist's approach one step further you could generate a real piece of C code that prints this macro, compile it, execute it and redirect the output to the included Makefile. Simplified demo:
The simplified version.h
:
#define CURRENT_SHA "d70b1a7391"
#define DATE_OF_SHA "220621"
#define BUILD_TYPE "E"
#define BINARY_BASE_NAME BUILD_TYPE DATE_OF_SHA "_" CURRENT_SHA
The Makefile
file:
include version.mk
define C_code
#include <stdio.h>
#include "$<"
int main(void) {
printf("BINARY_BASE_NAME := %s\n", BINARY_BASE_NAME);
return 0;
}
endef
export C_code
version.mk : version.h
printf '%s\n' "$$C_code" > "[email protected]"
$(CC) $(CFLAGS) -o "[email protected]" "[email protected]"
"./[email protected]" > "$@"
.PHONY: all clean
all:
@printf '%s\n' "$(BINARY_BASE_NAME)"
clean:
rm -f version.mk.c version.mk.exe version.mk
And then:
$ make all
printf '%s\n' "$C_code" > "version.mk.c"
cc -o "version.mk.exe" "version.mk.c"
"./version.mk.exe" > "version.mk"
E220621_d70b1a7391
$ cat version.mk.c
#include <stdio.h>
#include "version.h"
int main(void) {
printf("BINARY_BASE_NAME := %s\n", BINARY_BASE_NAME);
return 0;
}
$ cat version.mk
BINARY_BASE_NAME := E220621_d70b1a7391
$ make clean
rm -f version.mk.c version.mk.exe version.mk
CodePudding user response:
If your shell script creates a header, why not make it also create a Makefile snippet that gets included by your main Makefile?
echo "BINARY_BASE_NAME := ${BUILD_TYPE}_${DATE_OF_SHA}_${CURRENT_SHA}" > makefile.inc
Then use a GNU make include makefile.inc
directive.