Search code examples
cmakefileavr

Reading a set of variables into a Makefile from a C source file?


I have an AVR8 GCC application that can be built with a standard makefile. Because some folks who want to build the application don't want to set up make and such (or have trouble doing so), I also have figured out how to set the project up so it can be compiled from the Arduino IDE as well.

All is working.

But, I normally set some items in the makefile, like the version number and such, but creating the VERSION string in the makefile and passing it as a define into each source file compilation. But, when run from the Arduino IDE, that step is obviously not occurring. So, I have to create a second #define in the Arduino sketch stub to recreate the define.

This means when I update the version, I need to do so in 2 places, in the makefile and in the source file.

The easy option is to simply move the VERSION creation to the source file, where both can use it. And, I'm OK doing that, but

The makefile actually needs the version information, both to create the right filename (think app_v1.2.3.4.bin) and embed the version number into the bin file since it is used by the boot-loader (if requested) to ensure the version the boot-loader flashes is newer than the one already in FLASH. So, if I move the VERSION, RELEASE, MODIFICATION, etc. defines into the C code, I need to find a way to pull them back into the makefile.

I tried using the file read operations in the makefile, but they seem to ignore:

#define VERSION 0

with the prefaced '#' char.

I see there's some options to run sed/awk/etc, in bash, but I don't want to make too many assumptions on the environment, and the makefile currently runs on Windows as well as Unix/Linux without any differences.

I tried a few stack overflow examples, but nothing seems to yield those 4 numbers from any file, .h or otherwise.

I'm OK with creating version.h with just:

#define VERSION      0
#define RELEASE      1
#define MODIFICATION 2
#define FIX          4

If I can read it into the makefile and create the variables I need.

Jim


Solution

  • You may take a look at gmtt which was designed exactly with you use case in mind. In gmtt the following should read and analyze your header file:

    include gmtt.mk
    
    # create a 3-column table from the header file. The first column is just the "#define"
    VNR_TABLE := 3 $(file < version.h)
    
    # Extract the values from the table: select column 3 from VNR_TABLE where column 2 equals a string constant. 
    # Be careful not to introduce spaces in the compare!
    VER := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,VERSION))
    REL := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,RELEASE))
    MODF := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,MODIFICATION))
    FIX := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,FIX))
    

    I couldn't test it but I think you get the idea.

    PS: using a GNUmake library just means placing the included file alongside the makefile.