9
votes

Structure de la structure de la structure de fichiers d'objet plat avec GNU Gake

J'ai un petit projet C ++ à l'aide de GNU Gake. J'aimerais pouvoir activer les fichiers source suivants: xxx pré>

dans la structure de sortie suivante (je ne suis pas préoccupé par des doublons à ce stade): p>

OBJS            :=      $(foreach file,$(SRCS),$(file).o)
DEPS            :=      $(patsubst %.o,%.d,$(OBJS))
sinclude $(DEPS)

$(OBJS) : %.o : %.cpp
        @echo Compiling $<
        $(CC) $(CC_FLAGS) $(INCS) -MMD -o $@ $<  


0 commentaires

5 Réponses :


2
votes
vpath %.cpp src src/b src/c
Then refer to source files without their directory name; Make will search the vpath.

0 commentaires

9
votes

Il y a au moins deux façons de le faire. Premier (et ce que je recommanderais) est que vous pouvez ajouter le répertoire de construction aux noms cibles (même lors de l'utilisation d'une règle de modèle). Par exemple:

BUILD_DIR := build

SRCS := \
    a.c \
    b.c \
    c.c \
    a/a.c \
    b/b.c \
    c/c.c

OBJS := ${SRCS:%.c=${BUILD_DIR}/%.o}

foo: ${OBJS}
    @echo Linking $@ using $?
    @touch $@

${BUILD_DIR}/%.o: %.c
    @mkdir -p $(dir $@)
    @echo Compiling $< ...
    @touch $@

${SRCS}:
    @echo Creating $@
    @mkdir -p $(dir $@)
    @touch $@

.PHONY: clean
clean:
    rm -f foo
    rm -f ${OBJS}


12 commentaires

OK, en utilisant cette approche, j'avais probablement besoin d'une règle supplémentaire pour créer des sous-dossiers dans le dossier de sortie?


J'ai fini par descendre cet itinéraire - comme je devais faire de la cible et la configuration des dossiers de construction spécifiques de toute façon, il était facile d'ajouter un autre couple de dossiers à l'étape "Buildfolders". Merci!


Une règle distincte pour les dossiers de construction devrait fonctionner très bien. Ce que je fais généralement, cependant, ajoutez simplement une ligne "@mkdir -p $ (dir $ @)" à la ligne du script de commande pour créer le répertoire de sortie (si cela n'existe pas déjà) dans le cadre de la création du fichier d'objet ( s).


La première solution échoue soit sans vpath ni échec lorsque vous essayez de relier les objets dans un exécutable, en fonction de l'endroit où vous l'exécutez. L'objection "DUPLICATES" s'applique à la solution "Build /" autant que la solution VPATH.


@Beta: Ce n'est pas une solution hypothétique. Il s'agit d'une solution réelle qui a été essayée, testée et surplagée dans de nombreux maquillages que j'ai personnellement écrits. Il ne nécessite pas de VPATH et il ne subit pas de problèmes lorsqu'il existe des noms de fichier en double. Notez que toute la solution n'est pas affichée dans cette réponse - juste assez pour répondre à la question.


@Dan Moulding: Veuillez afficher votre solution complète (ou email à beta@mailinator.com), et si cela fonctionne comme vous dites que je vais manger mes mots et inverser mon vote.


@Beta: Fait. Je suppose que ma première réponse laissait un peu pour le lecteur d'imaginer. Cet exemple devrait illustrer le tout.


Cela ne satisfait pas la structure de sortie dans la question initiale. J'avoue que je n'ai pas remarqué que les commentaires de justicle acceptent ce changement, mais il n'est pas juste de modifier le problème et de critiquer une autre approche qui ne le fait pas.


@Beta: assez juste. J'ai inclus VPATH dans ma réponse, car il peut faire exactement la structure de sortie qu'il a spécifiée. Cependant, il me semblait clair que son vrai désir était de pas obtenir les fichiers générés mélangés avec les sources. Donc, j'ai proposé une solution alternative qui n'a pas les limitations de VPATH. Pensez-y comme allant le mile supplémentaire;)


Assez juste. P.s.: Objs: = $ {srcs:%. C = $ {build_dir} /%. O}


Ah. Joli. Je n'ai jamais pensé utiliser plus que le modèle "générique" dans une référence de substitution. Je l'aime bien.


J'ai essayé la solution sur Windows8 (64bits). Rendre une erreur: faire: *** Aucune règle pour faire la cible Build \ A \ a.obj ', nécessaire par tout'. Arrêter. De plus, cette réponse est fausse. La question était de savoir comment créer un arborescence de répertoires de fichiers C dans le répertoire plat sur .obj. La réponse que vous avez donnée crée un arborescence de répertoire dans le répertoire de construction



1
votes

Création de la structure de répertoire à plat comme initialement demandé.

utilise VPATH code> pour suivre les fichiers source, mais tous les broyées sont effectuées automatiquement à partir de la liste src code> . P>

SRC = a/a.c a/aa.c b/b.c
TARGET = done

FILES = $(notdir $(SRC) )
#make list of source paths, sort also removes duplicates
PATHS = $(sort $(dir $(SRC) ) )

BUILD_DIR = build
OBJ = $(addprefix $(BUILD_DIR)/, $(FILES:.c=.o))
DEP = $(OBJ:.o=.d)

# default target before includes
all: $(TARGET)

include $(DEP)

vpath %.c $(PATHS)

# create dummy dependency files to bootstrap the process
%.d:
    echo a=1 >$@

$(BUILD_DIR)/%.o:%.c
    echo $@: $< > $(patsubst %.o,%.d,$@)
    echo $< >$@

$(TARGET): $(OBJ)
    echo $^ > $@

.PHONY: clean
clean:
    del $(BUILD_DIR)/*.o
    del $(BUILD_DIR)/*.d


0 commentaires

0
votes

Vous pourriez ne pas particulièrement aimer cette approche, mais:

AUTOMAKE_OPTIONS =


0 commentaires

1
votes

Ceci est pour Win32 Mingw32-FAIT. ça marche. La partie la plus importante est

-mkdir $ (Patsubst% /,%, $ (dir $ @)) code> p>

pour Win32. Nous devons éliminer le train et pour Win32. P>

GENERATED_DIRS = a b

# Dependency generator function
mkdir_deps =$(foreach dir,$(GENERATED_DIRS),$(dir)/.mkdir.done)

# Target rule to create the generated dependency.
# And create the .mkdir.done file for stop continuous recreate the dir
%/.mkdir.done: # target rule
    -mkdir $(patsubst %/,%,$(dir $@))
    echo $(patsubst %/,%,$(dir $@)) >$@

all: $(mkdir_deps)
    @echo Begin

clean:
    @echo Cleaning


0 commentaires