Author Topic: Makefile change output hex file name from header file #define  (Read 1480 times)

0 Members and 1 Guest are viewing this topic.

Offline hal9001Topic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: 00
I use a #define inside a header file for firmware version. Can the makefile append the version number from the #define to the name of the hex file? Im using Atmel Studio.
 

Offline mfro

  • Regular Contributor
  • *
  • Posts: 212
  • Country: de
Re: Makefile change output hex file name from header file #define
« Reply #1 on: May 15, 2024, 09:39:05 am »
I use a #define inside a header file for firmware version. Can the makefile append the version number from the #define to the name of the hex file? Im using Atmel Studio.

The Makefile itself can't - but with a little help from the C preprocessor cpp, it's possible. Let's assume you have your version number in a file called version.h like so:
Code: [Select]
#define VERSION "1.0.0-beta"

you can assign that to a Makefile variable using the C preprocessor:

Code: [Select]
VERSION = $(shell echo "#include \"version.h\"\nVERSION" | $(CPP) - -P -o -)

The version string can than be appended to any name in the Makefile.


(assuming you are using Linux or another *X-based OS like Mac OS. If you are using Windows, I'm afraid you need to ask somebody else)
Beethoven wrote his first symphony in C.
 
The following users thanked this post: PlainName, Karel, hal9001

Offline hal9001Topic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: 00
Re: Makefile change output hex file name from header file #define
« Reply #2 on: May 15, 2024, 09:53:48 am »
I use a #define inside a header file for firmware version. Can the makefile append the version number from the #define to the name of the hex file? Im using Atmel Studio.

The Makefile itself can't - but with a little help from the C preprocessor cpp, it's possible. Let's assume you have your version number in a file called version.h like so:
Code: [Select]
#define VERSION "1.0.0-beta"

you can assign that to a Makefile variable using the C preprocessor:

Code: [Select]
VERSION = $(shell echo "#include \"version.h\"\nVERSION" | $(CPP) - -P -o -)

The version string can than be appended to any name in the Makefile.


(assuming you are using Linux or another *X-based OS like Mac OS. If you are using Windows, I'm afraid you need to ask somebody else)
Cheers! Im using Windows. Maybe power shell in windows can work the same way?
 

Offline mfro

  • Regular Contributor
  • *
  • Posts: 212
  • Country: de
Re: Makefile change output hex file name from header file #define
« Reply #3 on: May 15, 2024, 10:01:38 am »
Cheers! Im using Windows. Maybe power shell in windows can work the same way?

That's entirely possible (maybe even CMD might do it), but I can't assist with that as I didn't touch any Windows for years.
Beethoven wrote his first symphony in C.
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 267
  • Country: ua
Re: Makefile change output hex file name from header file #define
« Reply #4 on: May 15, 2024, 01:13:17 pm »
You might try this

version.h:
Code: [Select]
#define VERSION "1.2.3"

Code: [Select]
VERSION = $(shell echo VERSION | gcc -P -E -imacros version.h -)

However the generated variable will be double-quoted , which is probably not what you want. But hey, there are at least two solutions for that:
1. Find how to dequote a string - a quick google search suggests it is doable, or
2. Stop using Windows, and start using something more developer-friendly
« Last Edit: May 15, 2024, 01:17:07 pm by tellurium »
Open source embedded network library https://github.com/cesanta/mongoose
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 

Offline retiredfeline

  • Frequent Contributor
  • **
  • Posts: 546
  • Country: au
Re: Makefile change output hex file name from header file #define
« Reply #5 on: May 15, 2024, 02:14:36 pm »
Can you do it the other way, assign the version in the Makefile and then pass it down to the #define? That's relatively easy.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8203
  • Country: fi
Re: Makefile change output hex file name from header file #define
« Reply #6 on: May 15, 2024, 04:43:51 pm »
Can you do it the other way, assign the version in the Makefile and then pass it down to the #define? That's relatively easy.

Taking this further:
Code: [Select]
GIT_VERSION := $(shell git describe --abbrev=16 --always --exclude '*')
CFLAGS += -DGIT_VERSION=0x$(GIT_VERSION)ULL

Basically a uint64_t automagically derived from the 64 first bits of the git commit hash, has served me well. And when printed in hex, it's human readable enough.
« Last Edit: May 15, 2024, 04:45:25 pm by Siwastaja »
 
The following users thanked this post: Karel, tellurium

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1217
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #7 on: May 17, 2024, 05:11:07 am »
We routinely pass defines to from our makefile to our compiler for just such purposes.

That said, if you want to grab the hash, you should use the "plumbing" command rev-parse as opposed to describe, which is a porcelain command and can change at any time.

git rev-parse HEAD|your_tag|or_whatever_else_you_want

or if you want to limit the length

git rev-parse --short=TheLengthYouWant HEAD|your_tag|or_whatever_else_you_want

so to get a 10 character hash of branch "Whatever"

git rev-parse --short=10 Whatever

 

Offline hal9001Topic starter

  • Regular Contributor
  • *
  • Posts: 121
  • Country: 00
Re: Makefile change output hex file name from header file #define
« Reply #8 on: May 17, 2024, 06:21:01 am »
We routinely pass defines to from our makefile to our compiler for just such purposes.

That said, if you want to grab the hash, you should use the "plumbing" command rev-parse as opposed to describe, which is a porcelain command and can change at any time.

git rev-parse HEAD|your_tag|or_whatever_else_you_want

or if you want to limit the length

git rev-parse --short=TheLengthYouWant HEAD|your_tag|or_whatever_else_you_want

so to get a 10 character hash of branch "Whatever"

git rev-parse --short=10 Whatever
Cheers. Passing the #define is preferred to git hash. Regretfully harder than I thought
 

Offline bson

  • Supporter
  • ****
  • Posts: 2284
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #9 on: May 18, 2024, 07:43:18 pm »
I'd suggest learning to use git.  Then use tags to identify versions, and have the Makefile extract either the tag and fill in version.h for you, or if the current head is not on a tag (named commit) use the commit ID.
 

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1217
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #10 on: May 19, 2024, 12:35:11 am »
We routinely pass defines to from our makefile to our compiler for just such purposes.

That said, if you want to grab the hash, you should use the "plumbing" command rev-parse as opposed to describe, which is a porcelain command and can change at any time.

git rev-parse HEAD|your_tag|or_whatever_else_you_want

or if you want to limit the length

git rev-parse --short=TheLengthYouWant HEAD|your_tag|or_whatever_else_you_want

so to get a 10 character hash of branch "Whatever"

git rev-parse --short=10 Whatever
Cheers. Passing the #define is preferred to git hash. Regretfully harder than I thought

I was explaining how to get a hash to pass it as a #define. I don't think I've ever run into a compiler that can't define on the command line. Is the syntax for defining a symbol on the command line the stumbling block?

The make file can't do anything to your code, at least not easily, but if your compiler supports it you can pass something in that you can then use. Absolute worst case, it can emit a file you can include. What's your stumbling block?
« Last Edit: May 19, 2024, 12:38:48 am by John Coloccia »
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 267
  • Country: ua
Re: Makefile change output hex file name from header file #define
« Reply #11 on: May 19, 2024, 09:41:10 am »
I am not an OP, but I had, and still have use cases when a header file is the source of truth, not git or whatever.
Long story short - you have a project which holds a library, and it's header defines a version.

Thus tricks with git, or taking versions from the Makefile, won't work. The version is set in the header, full stop.
Open source embedded network library https://github.com/cesanta/mongoose
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3260
  • Country: gb
Re: Makefile change output hex file name from header file #define
« Reply #12 on: May 19, 2024, 10:04:35 am »
Not exactly what you asked for, but it's possible to extract defines from a header using a batch file which can then be appended to the hex file.  This would be called as a post-build process, and on a Windows machine doesn't require any other dependencies.  The example below shows how this could be done.

Code: [Select]
REM Path and file name of the header file holding the firmware revision data.
set VERFILE=..\version.h

REM Set the defines holding version details.
set MAJOR_NAME=FIRMWARE_REV_MAJOR
set MINOR_NAME=FIRMWARE_REV_MINOR
set PATCH_NAME=FIRMWARE_REV_PATCH

REM Extract major version number from header file.
for /F "usebackq tokens=3" %%i in (`findstr /L /C:"#define %MAJOR_NAME% " %VERFILE%`) do set MAJOR_VER=%%~i

REM Extract minor version number from header file.
for /F "usebackq tokens=3" %%i in (`findstr /L /C:"#define %MINOR_NAME% " %VERFILE%`) do set MINOR_VER=%%~i

REM Extract patch version number from header file.
for /F "usebackq tokens=3" %%i in (`findstr /L /C:"#define %PATCH_NAME% " %VERFILE%`) do set PATCH_VER=%%~i

REM Combine major, minor , patch levels AND model to form the revision string.
set STRREV=%MAJOR_VER%_%MINOR_VER%_%PATCH_VER%_%1

REM Display revision string.
@echo Firmware revision is %STRREV%
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 3750
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #13 on: May 19, 2024, 04:53:58 pm »
I am not an OP, but I had, and still have use cases when a header file is the source of truth, not git or whatever.
Long story short - you have a project which holds a library, and it's header defines a version.

Thus tricks with git, or taking versions from the Makefile, won't work. The version is set in the header, full stop.

The use of git is incidental.  It's just a convenient way to generate a unique and traceable tag.  It's not even a proper version in the sense that it doesn't have ordering without referring to the source repo.

However, I am deeply suspicious of any claim that "the source of truth must be the header file."  If that is by administrative fiat with no technical reason, that's fine, although not very interesting.  But if it's for a technical reason, that reason matters.  In particular, if the header file is not actually part of the source code but generated by a step in the build process, then all of the make tricks using $(shell ...) may fail.  That's because $(shell) expansion is done while parsing rules before building the dependency graph or building any targets.  If version.h doesn't exist when you run make those rules will fail.  In this case, the "real" source of truth is something else that is used to generate the headers, and you should get the version from that.  If you have a pre-build step that runs before make (like gnu autoconf) that generates the header files, that's solves this problem, but then why couldn't autoconf generate the correct makefile in the first place?

I'm also skeptical of the wisdom of extracting the define from a header file.  You can do it with grep / awk and that works fine especially if you have a version.h with nothing but the version.  Really the only thing that is is in a position to parse an arbitrary header file is the compiler / pre-compiler.  You can use the compiler to extract the #define, which is more correct, but also more complicated.  Storing the verison in the source code is fine in simple cases where it isn't needed anywhere else, but as soon as you need it for another part of your build process I think it's better to remove it to more neutral territory, which could just be a text file called version.txt, and inject it into the compiler with -D (or /D).

A huge advantage of using the build process to inject the version is that you can have an automated way to distinguish developer builds from release builds by having your makefile choose what to inject. Builds produced by developers running "make" are automatically tagged as a development version (which may contain local changes), and only by the CI system running "make RELEASE=1" or something will it be targeted as a release candidate and guaranteed to be a clean, traceable build.  Whenever possible, I tend to just have the version #ifndef / #defined to "unknown" in the source, and developer builds use that, only release builds get a real version tag at all.
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 3750
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #14 on: May 19, 2024, 05:01:17 pm »
However, with all that said, the following should work:

Code: [Select]
BASENAME = myprog
VERSION = $(shell grep VERSION foo.h | cut -f3 -d " " )

$(BASENAME)_$(VERSION).hex: $(BASENAME).elf:
        objcopy -O ihex $< $@
 

Online cv007

  • Frequent Contributor
  • **
  • Posts: 829
Re: Makefile change output hex file name from header file #define
« Reply #15 on: May 19, 2024, 06:10:55 pm »
Quote
Can the makefile append the version number from the #define to the name of the hex file? Im using Atmel Studio
I doubt you will be touching any makefile if using Studio. The IDE deals with the makefiles(s) and generally they do not take kindly to a user making their own edits to them (edits could simply disappear as the IDE overwrites it, or may get the IDE confused, and so on).

The IDE will most likely have the ability to specify/run a post build command/script (MPLABX does), and this could be something simple like grep'ing a header to get your version, renaming/cp/mv the hex file using its new name (can do as a single line command, or make a script and simply execute the script). Although running Windows, you may still have the ability to run things like grep/sed/mv/cp/etc, as they may have included these things (they will have 'make', so sometimes include a set of unix-y utilities also so the various flavors of OS all have access to the same tools, so for example they can all run the same post build scripts).

I don't have Studio, but if you look around the build options there may be an option to do a post build step. If you simply enter something like 'ls' (no quote), and you get a file listing in the build output when compiling, you then know you have access to some unix tools.
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 267
  • Country: ua
Re: Makefile change output hex file name from header file #define
« Reply #16 on: May 19, 2024, 07:24:33 pm »
Code: [Select]
VERSION = $(shell grep VERSION foo.h | cut -f3 -d " " )

If you read the thread carefully, you'll notice that OP uses Windows, hence all those quirks with the preprocessor (cross-platform way to do things), since grep/sed are not available on Windows.
Open source embedded network library https://github.com/cesanta/mongoose
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1217
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #17 on: May 19, 2024, 07:34:14 pm »
As ejeffrey said, git was just an example.

Our common pattern for handling this is to create a file called "version" or similar. In our case, it's release_hash.txt, and sometimes a version.txt as well, and is usually autogenerated from a script that does a bunch of other stuff too (changelogs, etc). But create the file(s) however you want. In the file, stick something like:

Code: [Select]
HASH=123ABC

or

VERSION=v1.2.3

or whatever other information you want.

In the makefile:

Code: [Select]
include version.txt

or whatever you called it.

You will end up with a variable called VERSION just as if you'd defined it in the makefile.

You can then tell the compiler to define a symbol and set it to whatever you want, just like a #define. Or generate a header file if you really want to.

The point of this is that it's EASY to get arbitrary information into the makefile, and to somehow pass that along to the compiler. It's way clunkier to get information from your source code and pass it to the makefile.

One more thing I'll warn you about. You can just append the version name to the hex file, BUT it will eventually cause problems in the long run. When your version changes, make will have no idea that there USED to be a FILE_VERSION1.hex, and it will just get leftover. You should create a rule that does something like (using ejeffrey's example for reference):

Code: [Select]
$(BASENAME)_$(VERSION):
    make clean
    touch $(BASENAME)_$(VERSION):

This is just using an empty file to track the idea that the thing you're building now is different than the thing you build last time. There are other ways to handle this, but if you're project's not big and/or you're not changing versions all the time, this sledgehammer approach is really simple.

Depending on what else your doing, there may be other cleanup to do as well. Just giving you a heads up if you want your makefile to be squeaky clean.

One last thing I'll recommend. If you're going to work in Windows, and I generally work in Windows, use MSYS2. We've standardized on doing all of our builds/scripts/etc, as much as humanly possible, with tools like bash and all the other included tools. It's hard to imagine going back to using things like cmd and powershell.
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 267
  • Country: ua
Re: Makefile change output hex file name from header file #define
« Reply #18 on: May 19, 2024, 07:59:49 pm »
Gents, I fully get what you're talking about, and it makes a perfect sense.

The use case that I mentioned, is the other way around.
Imagine you're creating a single-header library.
You're going to ship it to other users. Everything is one single header file, including version definition. That line, "#define VERSION ...", is inside the header file. Not in the makefile. Not in the version.txt or in some other place.

Now a Makefile may have some actions / rules which may use that version - for example, upload a CI artefact, or build a test binary that includes version in the file name.
Open source embedded network library https://github.com/cesanta/mongoose
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1217
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #19 on: May 19, 2024, 08:15:47 pm »
Gents, I fully get what you're talking about, and it makes a perfect sense.

The use case that I mentioned, is the other way around.
Imagine you're creating a single-header library.
You're going to ship it to other users. Everything is one single header file, including version definition. That line, "#define VERSION ...", is inside the header file. Not in the makefile. Not in the version.txt or in some other place.

Now a Makefile may have some actions / rules which may use that version - for example, upload a CI artefact, or build a test binary that includes version in the file name.

How do you like this for abuse....

version.h
Code: [Select]
#define VERSION=v1.2.3
#ifndef VERSION
VERSION=v1.2.3
#endif

Include in your .c and your makefile...

I'll admit, it makes me throwup a bit in my mouth, but I'd do it if it kept me from parsing the header.  ;D
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4219
  • Country: us
Re: Makefile change output hex file name from header file #define
« Reply #20 on: May 19, 2024, 09:28:09 pm »
I've used (for Optiboot) CPP to output a shell-script based on command-line options, and then execute the shell script during the makefile.

Code: [Select]
baudcheck: FORCE
    - @$(CC) --version
    - @$(CC) $(CFLAGS) -E baudcheck.c -o baudcheck.tmp.sh
    - @$(SH) baudcheck.tmp.sh

You could use a similar technique to create a build-system-native executable that includes your headers and outputs your desired name, for later use in the Makefile.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf