0
votes

Lire un ensemble de variables dans un Makefile à partir d'un fichier source C?

J'ai une application AVR8 GCC qui peut être construite avec un makefile standard. Parce que certaines personnes qui souhaitent créer l'application ne veulent pas configurer make et autres (ou ont du mal à le faire), j'ai également trouvé comment configurer le projet afin qu'il puisse également être compilé à partir de l'IDE Arduino.

Tout fonctionne.

Mais, je règle normalement certains éléments dans le makefile , comme le numéro de version et autres, mais en créant la chaîne VERSION dans le makefile et en la passant comme définition dans chaque compilation de fichier source. Mais, lorsqu'elle est exécutée à partir de l'IDE Arduino, cette étape ne se produit évidemment pas. Donc, je dois créer un deuxième #define dans le talon d'esquisse Arduino pour recréer la définition.

Cela signifie que lorsque je mets à jour la version, je dois le faire à 2 endroits, dans le makefile et dans le fichier source.

L'option la plus simple consiste à déplacer simplement la création de VERSION vers le fichier source, où les deux peuvent l'utiliser. Et je vais bien faire ça, mais

Le makefile réellement besoin des informations de version, à la fois pour créer le bon nom de fichier (pensez app_v1.2.3.4.bin ) et pour incorporer le numéro de version dans le fichier bin puisqu'il est utilisé par le chargeur de démarrage (si demandé) pour garantir la version le boot-loader clignote est plus récent que celui déjà en FLASH. Donc, si je déplace les définitions de VERSION , RELEASE , MODIFICATION , etc. dans le code C, je dois trouver un moyen de les ramener dans le makefile .

J'ai essayé d'utiliser les opérations de lecture de fichier dans le makefile , mais elles semblent ignorer:

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

avec le caractère '#' préfacé.

Je vois qu'il y a quelques options pour exécuter sed / awk / etc, dans bash, mais je ne veux pas faire trop d'hypothèses sur l'environnement, et le makefile fonctionne actuellement sous Windows ainsi que Unix / Linux sans aucune différence.

J'ai essayé quelques exemples de débordement de pile, mais rien ne semble donner ces 4 nombres à partir d'un fichier, .h ou autre.

Je suis d'accord avec la création de version.h avec juste:

#define VERSION 0

Si je peux le lire dans le makefile et créer les variables dont j'ai besoin.

Jim


2 commentaires

Utilisez-vous GNU make ou une autre marque?


J'utilise gnu make


3 Réponses :


0
votes

Je pense que dans ce cas, vous pouvez utiliser la fonction 'file' de makefiles. Il vous permet d'écrire (avec> spécificateur) ou de lire (avec <spécificateur) vers / depuis des fichiers. Ensuite, vous pouvez couper (avec filtrage) vos variables dans votre makefile. Source: https://www.gnu.org/software/make/manual/html_node/File-Function.html#File-Function


3 commentaires

Relisez votre question, quelle version de marque utilisez-vous? la fonction de fichier ne fonctionne qu'avec 4.2 et au-dessus


Comme je l'ai noté ci-dessus dans ma question, j'ai déjà essayé la fonction de fichier $(file < version.h) , mais si je n'ai pas le '#' dans le #define, make 4.3 crache une erreur 'make: define: No such file or directory ', et si je préfère le # devant define, les lignes semblent être ignorées en tant que commentaires. Je pense que la fonction de fichier lit les données comme s'il s'agissait de commandes Makefile, et donc tout ce qui a un '#' devant peut être simplement ignoré en tant que commentaire.


la seule solution de contournement à laquelle je peux penser est d'utiliser cat ou type en fonction de l'os cat := $(if $(filter $(OS),Windows_NT),type,cat) variable := $(shell $(cat) filename)



0
votes

Vous pouvez utiliser la fonction $(shell ...) GNU make pour extraire les extensions de macro. En supposant que VERSION est définie dans src.c et que les jetons sont délimités par des espaces (pas des tabulations):

VERSION := $(shell sed -n -e "s/^\#define VERSION  *\(.*\)/\1/p" src.c)

.PHONY: all
all:
    @echo VERSION=$(VERSION)


1 commentaires

Comme indiqué dans la demande originale, je préfère ne pas utiliser le shell, car il n'y a aucune garantie qu'un ensemble complet d'outils Unix sera disponible. Je préfère créer le moins de pré-demandes d'outils possible.



0
votes

Vous pouvez jeter un oeil à gmtt qui a été conçu exactement pour votre cas d'utilisation. Dans gmtt les éléments suivants devraient lire et analyser votre fichier d'en-tête:

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))

Je n'ai pas pu le tester mais je pense que vous avez compris l'idée.

PS: utiliser une bibliothèque GNUmake signifie simplement placer le fichier include d à côté du makefile .


1 commentaires

Merci beaucoup. Cela fonctionne très bien et ne recourt pas à un piratage de shell laid.