Comment puis-je créer un Makefile pour les projets C avec la SRC, OBJ, et les sous-répertoires BIN?
Il y A quelques mois, je suis venu avec les génériques suivantes Makefile
pour des travaux scolaires:
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
@$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
@$(CC) $(CFLAGS) $(SOURCES)
@echo "Compilation complete!"
clean:
@$(rm) $(TARGET) $(OBJECTS)
@echo "Cleanup complete!"
Ce sera essentiellement de compiler tous les .c
et .h
fichier à générer .o
fichiers et le fichier exécutable projectname
tous dans le même dossier.
Maintenant, j'aimerais pousser un peu. Comment puis-je écrire un Makefile pour compiler un projet C avec la structure de répertoire suivante?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
En d'autres termes, j'aimerais avoir un Makefile qui compile les sources C de ./src/
en ./obj/
et de les lier tous les éléments pour créer l'exécutable dans ./bin/
.
J'ai essayé de lire les différents fichiers Makefile, mais je ne peux tout simplement pas faire le travail pour le projet de la structure ci-dessus; au lieu de cela, le projet ne parvient pas à compiler avec toutes sortes d'erreurs. Bien sûr, je pourrais utiliser la pleine soufflé IDE (Monodevelop, Anjuta, etc.), mais honnêtement, je préfère rester avec gEdit et le bon vieux terminal.
Est-il un gourou qui peut me donner une solution ou une information claire sur la façon dont cela peut être fait? Merci!!!!
** Mise à JOUR (v4) **
La solution finale :
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
@echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
@$(rm) $(OBJECTS)
@echo "Cleanup complete!"
.PHONY: remove
remove: clean
@$(rm) $(BINDIR)/$(TARGET)
@echo "Executable removed!"
- Quelle est la question?
- Je ne suis pas sûr de comprendre ce que vous voulez faire.
- Mis à jour le
Makefile
. Je suis de près, mais j'ai du mal avec les variables automatiques, de sorte qu'il semble de toute façon - Je viens de trouver une solution. Si quelqu'un le soin de trouver quelque chose de mieux, le Makefile peut encore être améliorée.
- n'est-ce pas .BIDON au lieu de .FAUX?
- il peut être "BANANE" autant que je sache.. d'ailleurs, je ne suis pas un locuteur natif anglais 🙂
- Je ne veux pas critiquer vos compétences en anglais. Mais pour le FAUX cibles pour donner un sens vous avez très certainement ne peut pas écrire de la BANANE 😉 gnu.org/software/make/manual/html_node/Phony-Targets.html
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, votre
$(OBJECTS)
règle est problématique, parce que:file1.o
etfile2.o
)foo.o
) n'est pas ce que la règle en fait de produire (obj/foo.o
).Je suggère ce qui suit:
La
$(TARGET)
règle a le même problème que le nom de la cible n'est pas réellement décrire ce que la règle s'appuie. Pour cette raison, si vous tapezmake
plusieurs fois, Faire de recréer la cible à chaque fois, même si il n'y a pas de raison de le faire. Un petit changement de correctifs:Une fois que tout est en ordre, vous pourriez envisager de plus sophistiqué de traitement des dépendances; si vous modifiez l'un des fichiers d'en-tête, ce makefile ne savez pas quelles sont les objets/exécutables doivent être reconstruits. Mais que peut attendre un autre jour.
EDIT:
Désolé, j'ai omis une partie de la
$(OBJECTS)
la règle ci-dessus; j'ai corrigé. (Je souhaite que je pourrais utiliser "grève" à l'intérieur d'un exemple de code.)obj/file1.o: In function 'main': \n main.c:(.text+0x0): multiple definition of 'main' \n obj/main.o:main.c:(.text+0x0): first defined here
main
fonctions? Peut-être un dansfile1.c
et un enmain.c
? Si oui, alors vous ne serez pas en mesure d'établir un lien entre ces objets; il peut être un seulmain
dans un fichier exécutable.file1.c
mais ça donne le même message à tous les fichiers du projet. Etmain.c
est le uniquement l'un avec une fonction principale... etmain.c
importationsfile1.h
etfile2.h
(il n'y a aucun rapport entrefile1.c
etfile2.c
), mais je doute que le problème vient de là.$(OBJECTS)
règle; j'ai édité. Avec la ligne de mauvaise qualité j'ai eu une erreur, mais pas celui que vous avez obtenu...Vous pouvez ajouter la
-I
le drapeau drapeaux du compilateur (CFLAGS) pour indiquer où le compilateur doit rechercher des fichiers source , et l'-o drapeau pour indiquer où le binaire doit être à gauche:Afin de déposer des fichiers de l'objet dans le
obj
répertoire, utilisez la-o
option lors de la compilation. Aussi, regardez la$@
et$<
variables automatiques.Par exemple, considérons ce simple Makefile
Mise à jour>
En regardant votre makefile, je me rends compte que vous utilisez le
-o
drapeau. Bon. Continuer à l'utiliser, mais ajouter un répertoire cible de la variable pour indiquer l'emplacement où le fichier de sortie doit être écrit.-l ...
à laCFLAGS
et ... il y a déjà le-o
argument de l'éditeur de liens (LINKER
)make
, d'où le Makefile se trouve%.o: %.c
la règle est mal. Il ne produit pas de la cible à laquelle il promet de produire. Devrait être${OBJDIR}/%.o: %.c
et-o $@
.J'ai arrêté d'écrire des makefiles ces jours, si votre intention est d'apprendre à aller de l'avant, sinon vous avez un bon générateur de makefile qui vient avec eclipse CDT. Si vous voulez un peu de la facilité de maintenance /multiple projet de soutien dans votre arbre de construction, ont un oeil à ce qui suit -
https://github.com/dmoulding/boilermake J'ai trouvé cette très bonne..!