Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 22/11/2007, à 18:00

CasseTaTele

[Résolu] Makefile (sous répertoires,cibles multiples)

Bonjour,

je souhaiterai compiler plusieurs *.c disséminés dans plusieurs sous-répertoires (dont j'ai la liste) vers autant d'exécutables situés dans un répertoire unique (../bin), en mettant si possible les objets (*.o) dans un répertoire séparé (./objects)

j'ai lu quelque part que l'instruction VPATH permettait à  make de rechercher dans plusieurs sous-répertoires mais par la suite quand j'utilise wildcard ou %.c ça coince ...

une idée?

(je précise bien : je veux tout faire avec un seul Makefile)

Dans l'exemple ci après j'ai mis la liste des répertoire dans VPATH,
j'essaye ensuite d'affecter la variable EXE_SRC avec les nom de tous les *.c dans les sous rep mais quand je les affiche avec echo la variable reste vide ...

# List of src directories ###############################################
VPATH = ./pre-processing/background_segmentation: \
		./pre-processing/image_alignment: \
		./pre-processing/image_filtering_and_contrast_enhancement: \
		./pre-processing/quality_check: \
		./information_extraction/1D_ring_extraction: \
		./information_extraction/2D_ring_extraction: \
		./information_extraction/nucleus_detection: \
		./information_extraction/oriented_field: \
		./information_extraction/shape: \
		./estimation_of_individual_ages/classification_from_global_features: \
		./estimation_of_individual_ages/selection_of_ring_curves: \
		./estimation_of_length-based_age_distribution

##############################################################

# List of exe source files (automatic parsing inside VPATH directories
#EXE_SRC = %.c			<--- ça marche pas non plus
EXE_SRC = $(wildcard *.c) 
EXE = $(EXE_SRC:*.c=*.exe)

all : $(EXE)
	echo "======================================================="
	echo $(VPATH)
	echo "======================================================="
	echo $(EXE_SRC)
	echo "======================================================="
	echo $(EXE)	
	echo "======================================================="
$(EXE_SRC): 
	echo $(EXE_SRC)
	echo $(EXE)

Résultat d'un make:

scarbini@ntlimestra ~/prog/afisa/afisa_libs/src
$ make
echo "======================================================="
=======================================================
echo ./pre-processing/background_segmentation: ./pre-processing/image_alignment: ./pre-processing/image_filtering_and_cont
rast_enhancement: ./pre-processing/quality_check: ./information_extraction/1D_ring_extraction: ./information_extraction/2D
_ring_extraction: ./information_extraction/nucleus_detection: ./information_extraction/oriented_field: ./information_extra
ction/shape: ./estimation_of_individual_ages/classification_from_global_features: ./estimation_of_individual_ages/selectio
n_of_ring_curves: ./estimation_of_length-based_age_distribution
./pre-processing/background_segmentation: ./pre-processing/image_alignment: ./pre-processing/image_filtering_and_contrast_
enhancement: ./pre-processing/quality_check: ./information_extraction/1D_ring_extraction: ./information_extraction/2D_ring
_extraction: ./information_extraction/nucleus_detection: ./information_extraction/oriented_field: ./information_extraction
/shape: ./estimation_of_individual_ages/classification_from_global_features: ./estimation_of_individual_ages/selection_of_
ring_curves: ./estimation_of_length-based_age_distribution
echo "======================================================="
=======================================================
echo

echo "======================================================="
=======================================================
echo

echo "======================================================="
=======================================================

Dernière modification par CasseTaTele (Le 23/11/2007, à 15:50)

Hors ligne

#2 Le 22/11/2007, à 19:42

Gojita

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

Tu peux regarder la doc de make. Mais tu peux faire un truc du genre:

# extrait de la doc 'GNU Make'
find_files = $(wildcard $(dir)/*)
dirs := a b c d
files := $(foreach dir,$(dirs),$(find_files))

Voici un lien pour la section:
http://www.cs.utah.edu/dept/old/texinfo … html#SEC75

bien sur tu remplaces ta vaiables dirs avec la valeur de tes répertoires.

Pour info, VPATH te permets de recherches les fichiers que make ne trouve pas.
Donc, c'est bien normale que ca ne marche pas.

toto.c:   fichier1.h fichier2.h

voilà , si toto.c n'est pas trouvé ... alors, il va allez voir ta variable VPATH. Mais pas
pour un $(wildcard *.c)

Dernière modification par Gojita (Le 22/11/2007, à 19:43)


Il y a 10 sortes de personnes
Celles qui savent compter en binaires et les autres.

Hors ligne

#3 Le 22/11/2007, à 20:48

CasseTaTele

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

ok merci, je vais regarder ça demain,
autre question en plus :
comment lister automatiquement tous les sous-répertoires dans une variable (ex: dirs) ?

Hors ligne

#4 Le 23/11/2007, à 09:57

Gojita

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

Si c'est dans un makefile

dirs = $(shell find <root> -type d | grep -v '^.$')

ou tu remplaces <root> par le répertoire à  partir duquel tu veux rechercher.


Il y a 10 sortes de personnes
Celles qui savent compter en binaires et les autres.

Hors ligne

#5 Le 23/11/2007, à 11:10

CasseTaTele

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

merci !

par contre je ne comprend pas le sens du grep -v '^.$'
En regardant dans la doc je comprend le -v(Inverser la mise en correspondante, pour sélectionner les lignes ne correspondant pas au motif.) mais je vois pas pourquoi tu veux inverser la selection ni le sens de '^.$' ...

Donc je l'ai enlevé et ça donne ce que je cherchais:

dirs := $(shell find ./ -type d)

Maintenant, je dispose donc d'une chaà®ne comprenant toutes les sources (.c) avec leurs répertoires respectifs du type :

./dira/subdir1/a1.c
./dira/subdir2/a2.c
./dira/subdir3/a3.c
./dirb/b.c
./dirc/subdir1/c1.c
./dirc/subdir2/c2.c

En bidouillant j'ai réussis à  construire aussi des chaà®ne contenant les objets (tous dans un même répertoires) et les exécutables cibles (tous dans un même répertoire aussi), du type (pour les objets):

./obj/a1.o
./obj/a2.o
./obj/a3.o
./obj/b.o
./obj/c1.o
./obj/c2.o

et pour les exécutables :

./bin/a1.exe
./bin/a2.exe
./bin/a3.exe
./bin/b.exe
./bin/c1.exe
./bin/c2.exe

La réponse doit être simple mais je n'arrive pas à  compiler tout ça ...
j'ai essayé ça (avec $(obj_target) contenant la liste des objets ):

all : $(obj_target)
	
%_exe.o: %_exe.c
	@echo "========= Compile $< to build $@ ======="
	$(CC) -c $< -o $@

mais ça ne marche pas,

je pense qu'il doit y avoir moyen avec un foreach mais il faudrait pouvoir parcourir plusieurs chaà®nes en simultané du type comme ça:
$(foreach  src & obj, $(src) & (obj), gcc -c src -o obj )
mais je ne connais pas exactement la syntaxe et je ne trouve pas d'exemple sur le net...

Hors ligne

#6 Le 23/11/2007, à 12:26

Gojita

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

1) Pour le grep -v
c'est pour enlever le répertoire '.' qui apparaà®t dans le find si tu fais un find . -type d

2) normalement un

VPATH=<liste de tes répertoires>

obj/%.o: %.c
    $(CC) -c $< -o $@

devrait pouvoir le faire


Il y a 10 sortes de personnes
Celles qui savent compter en binaires et les autres.

Hors ligne

#7 Le 23/11/2007, à 14:12

CasseTaTele

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

1) ah ok! bah de toutes façons il n'y a pas de sources dans '.' donc c'est pas grave

2) j'ai pas essayé ta solution mais entre temps j'ai trouvé cette manière de faire :

# Binaries linking step
$(foreach)$(exe_target): $(foreach)$(obj_target)
	@echo "====== Build exe : $@ from $< ========="
	$(CC) $< -o $@ $(LIBS)
	@echo
	
# Binaries compilation step
$(foreach)$(obj_target): $(foreach)$(exe_src)
	@echo "====== Compile exe sources : $@ from $< ========="
	$(CC) -c $< -o $@ $(INCLUDES)
	@echo

ça marche !
l'astuce était d'utiliser $(foreach)$(cible): $(foreach)$(source)
EDIT: non en fait ça marche pas, (même problèmes que pour le 3) ) , tous les objets puis tous les exe étaient en fait fabriqués depuis la même source ... yikes/
j'essaye avec ta solution...

3) maintenant j'ai un souci différent, dans ces mêmes répertoires j'ai aussi des sources qui doivent se compiler dans une seule 'dll' (les sources concernant la dll se terminent par '_dll.c' et celles qui créent des exécutables se terminent par '_exe.c')
j'ai essayé de procéder de la même manière mais ça marche pas :

######################################################################################
# VARIABLES FOR DLL CONSTRUCTION

# function to find dll source file in sub-directories
find_dll_src = $(wildcard $(dir)/*_dll.c)

# Find all dll source files (files of type *_dll.c)
dll_src := $(foreach dir,$(dirs),$(find_dll_src))

# Extract only the filenames from dll source files
dll_src_filename := $(notdir $(dll_src))

# All dll sources are compile into the dynamic library 'otolith.dll'
dll_target := ../lib/otolith.dll

# Compute objects filenames from dll sources filenames
dll_obj_target := $(foreach file,$(dll_src_filename),./_obj_/$(subst _dll.c,_dll.o,$(file)))

# Main target
all : $(dll_target)

# Dll
$(dll_target): $(dll_obj_target)
	@echo "====== Build dll : $@ from $< ========="
	$(CC_DLL) -o $(dll_target) $(dll_obj_target) $(LIBS0)
	
# Dll compilation step
$(foreach)$(dll_obj_target): $(foreach)$(dll_src)
	@echo "====== Compile Dll sources :   $@ from $< ========="
	$(CC) -c $< -o $@ $(INCLUDES)
	@echo

quand je tape 'make' ça donne ça :

$ make
====== Compile Dll sources :   _obj_/amle_sigma_init_dll.o from pre-processing/image_filtering_and_contrast_enhancement/am
le_sigma_init_dll.c =========
gcc -c pre-processing/image_filtering_and_contrast_enhancement/amle_sigma_init_dll.c -o _obj_/amle_sigma_init_dll.o -I ./_
kernel_/megawave2_functions_dll/

====== Compile Dll sources :   _obj_/define_sigma_image3_dll.o from pre-processing/image_filtering_and_contrast_enhancemen
t/amle_sigma_init_dll.c =========
gcc -c pre-processing/image_filtering_and_contrast_enhancement/amle_sigma_init_dll.c -o _obj_/define_sigma_image3_dll.o -I
 ./_kernel_/megawave2_functions_dll/

====== Compile Dll sources :   _obj_/lic_smoothing6_dll.o from pre-processing/image_filtering_and_contrast_enhancement/aml
e_sigma_init_dll.c =========
gcc -c pre-processing/image_filtering_and_contrast_enhancement/amle_sigma_init_dll.c -o _obj_/lic_smoothing6_dll.o -I ./_k
ernel_/megawave2_functions_dll/

====== Compile Dll sources :   _obj_/main_shape_dll.o from pre-processing/image_filtering_and_contrast_enhancement/amle_si
gma_init_dll.c =========
gcc -c pre-processing/image_filtering_and_contrast_enhancement/amle_sigma_init_dll.c -o _obj_/main_shape_dll.o -I ./_kerne
l_/megawave2_functions_dll/

====== Compile Dll sources :   _obj_/segment_otolith_dll.o from pre-processing/image_filtering_and_contrast_enhancement/am
le_sigma_init_dll.c =========
gcc -c pre-processing/image_filtering_and_contrast_enhancement/amle_sigma_init_dll.c -o _obj_/segment_otolith_dll.o -I ./_
kernel_/megawave2_functions_dll/

====== Build dll : ../lib/otolith.dll from _obj_/amle_sigma_init_dll.o =========
gcc -shared -o ../lib/otolith.dll ./_obj_/amle_sigma_init_dll.o ./_obj_/define_sigma_image3_dll.o ./_obj_/lic_smoothing6_d
ll.o ./_obj_/main_shape_dll.o ./_obj_/segment_otolith_dll.o -L ../lib/ -lkernel -lfunctions
./_obj_/define_sigma_image3_dll.o:amle_sigma_init_dll.c:(.text+0x0): multiple definition of `_amle_sigma_init'
./_obj_/amle_sigma_init_dll.o:amle_sigma_init_dll.c:(.text+0x0): first defined here
./_obj_/lic_smoothing6_dll.o:amle_sigma_init_dll.c:(.text+0x0): multiple definition of `_amle_sigma_init'
./_obj_/amle_sigma_init_dll.o:amle_sigma_init_dll.c:(.text+0x0): first defined here
./_obj_/main_shape_dll.o:amle_sigma_init_dll.c:(.text+0x0): multiple definition of `_amle_sigma_init'
./_obj_/amle_sigma_init_dll.o:amle_sigma_init_dll.c:(.text+0x0): first defined here
./_obj_/segment_otolith_dll.o:amle_sigma_init_dll.c:(.text+0x0): multiple definition of `_amle_sigma_init'
./_obj_/amle_sigma_init_dll.o:amle_sigma_init_dll.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [../lib/otolith.dll] Error 1

en fait le problème, c'est que pour construire chaque objet '.o' il prend tout le temps le même fichier source 'amle_sigma_init_dll.c' ...

Dernière modification par CasseTaTele (Le 23/11/2007, à 14:51)

Hors ligne

#8 Le 23/11/2007, à 14:57

CasseTaTele

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

# List all source sub-directories
VPATH := $(shell find ./ -type d)

./_obj_/%.o: %.c
    $(CC) -c $< -o $@
	
# DO NOT DELETE

j'ai essayé avec ta solution mais j'obtiens l'erreur suivante :

$ make
Makefile:19: *** missing separator.  Stop.

Hors ligne

#9 Le 23/11/2007, à 15:49

CasseTaTele

Re : [Résolu] Makefile (sous répertoires,cibles multiples)

OK c'est bon !!! smile smile
voila le résultat, c'est assez impitable mais j'ai mis beaucoup de commentaires pour pouvoir m'y retrouver plus tard :

# Looks for sources files in each sub-directories 
# For each source which filename ending with '_exe.c' : create a binary in ../bin/
# The source files ending with '_dll.c' are all compiled into a dynamic library : ../lib/otolith.dll

######################################################################################
# GENERAL VARIABLES
CC = gcc

LIBDIR = ../lib/
OBJDIR = ../obj/
BINDIR = ../bin/
KERNELDIR = ./_kernel_/megawave2_functions_dll/

INCLUDES = -I $(KERNELDIR)

LIBS  = -L $(LIBDIR) -lkernel -lfunctions -lotolith
LIBS0  = -L $(LIBDIR) -lkernel -lfunctions

######################################################################################
# VARIABLES FOR BINARIES CONSTRUCTION

# List all source sub-directories
dirs := $(shell find ./ -type d)

# function to find binaries source files in sub-directories
find_exe_src = $(wildcard $(dir)/*_exe.c)

# Find all binaries source files (files of type *_exe.c)
exe_src := $(foreach dir,$(dirs),$(find_exe_src))

# Extract only the filenames from binaries source files
exe_src_filename := $(notdir $(exe_src))

# Compute binaries filenames from sources filenames
exe_target := $(foreach file,$(exe_src_filename),$(BINDIR)$(subst _exe.c,.exe,$(file)))

######################################################################################
# VARIABLES FOR DLL CONSTRUCTION

# function to find dll source file in sub-directories
find_dll_src = $(wildcard $(dir)/*_dll.c)

# Find all dll source files (files of type *_dll.c)
dll_src := $(foreach dir,$(dirs),$(find_dll_src))

# Extract only the filenames from dll source files
dll_src_filename := $(notdir $(dll_src))

# All dll sources are compile into the dynamic library 'otolith.dll'
dll_target := $(LIBDIR)otolith.dll

# Compute objects filenames from dll sources filenames
dll_obj_target := $(foreach file,$(dll_src_filename),$(OBJDIR)$(subst _dll.c,_dll.o,$(file)))

######################################################################################
# List all source sub-directories
VPATH := $(shell find ./ -type d)

all:  $(dll_target) $(exe_target)

$(dll_target): $(dll_obj_target)
	@echo "------------------------------------------------------------"
	@echo "--- Linking : ---"
	@echo ">obj: $(dll_obj_target)"
	@echo ">dll: $(dll_target)"
	$(CC) -shared $(dll_obj_target) -o $(dll_target) $(LIBS0)
	@echo "============================================================"
	@echo	

$(OBJDIR)%_dll.o: %_dll.c
	@echo "------------------------------------------------------------"
	@echo "--- Compilation : ---"
	@echo ">src: $(notdir $<)  ($<)"
	@echo ">obj: $(notdir $@)  ($@)"
	$(CC) -c $< -o $@ $(INCLUDES)
	@echo

$(BINDIR)%.exe: $(OBJDIR)%_exe.o
	@echo "------------------------------------------------------------"
	@echo "--- Linking : ---"
	@echo ">obj: $(notdir $<)  ($<)"
	@echo ">bin: $(notdir $@)  ($@)"
	$(CC) $< -o $@ $(LIBS)
	@echo "============================================================"
	@echo
	
$(OBJDIR)%_exe.o: %_exe.c
	@echo "------------------------------------------------------------"
	@echo "--- Compilation : ---"
	@echo ">src: $(notdir $<)  ($<)"
	@echo ">obj: $(notdir $@)  ($@)"
	$(CC) -c $< -o $@ $(INCLUDES)
	@echo
	
list:
	@echo "------------------------------------------------------------"
	@echo "bin targets: $(exe_target)"
	@echo 
	@
	@echo "------------------------------------------------------------"
	@echo "dll targets: $(dll_target)"
	@echo 
	@	

clean:
	rm $(OBJDIR)*

Merci à  toi Gojita,
finalement j'ai réussi à  faire marcher ta solution

(Pour le problème du 'missing separator'  il suffisait de rajouter une tabulation à  la ligne indiquée à  la place des espaces...)

Hors ligne