2010-10-27 16 views
37

Tengo una biblioteca C++ creada con un Makefile. Hasta hace poco, todas las fuentes estaban en un solo directorio, y el Makefile hicieron algo como estoFuentes de subdirectorios en Makefile

SOURCES = $(wildcard *.cpp)

que funcionaba bien.

Ahora he agregado algunas fuentes que están en un subdirectorio, digamos subdir. Sé que puedo hacer esto

SOURCES = $(wildcard *.cpp) $(wildcard subdir/*.cpp)

pero estoy buscando una manera de evitar especificar subdir manualmente, es decir, hacer que wildcard mirada en subdirectorios, o la generación de una lista de subdirectorios de alguna manera y expandiéndolo con varios wildcard funciones. En este punto, tener una solución no recursiva (es decir, expandir solo el primer nivel) estaría bien.

No he encontrado nada, mi mejor opción es usar find -type d para enumerar los subdirectorios, pero se siente como un truco. ¿Hay alguna forma incorporada de hacer esto?

+0

posible duplicado de [comodines recursivos en GNU make?] (Http://stackoverflow.com/questions/2483182/recursive-wildcards-in-gnu-make) –

+0

@Jeroen debe ser al revés ya que esta pregunta una respuesta superior (usando '**'). – rightfold

Respuesta

53

Esto debe hacerlo:

SOURCES = $(wildcard *.cpp) $(wildcard */*.cpp) 

Si cambia de opinión y desea que una solución recursiva (es decir, a cualquier profundidad), se puede hacer pero implica algunas de las funciones Make más poderosas. Ya sabes, los que te permiten hacer cosas que realmente no deberías hacer.

EDIT:
Jack Kelly señala que $(wildcard **/*.cpp) obras a cualquier profundidad, al menos en algunas plataformas, utilizando gnumake 3,81. (Cómo se dio cuenta de eso, no tengo ni idea).

+19

Para buscar en cualquier profundidad, creo que '$ (comodín **/*. Cpp)' funcionaría. –

+1

@Jack Kelly: Lo intenté y no funcionó (GNU Make 3.81). ¿Funciona con tu versión? – Beta

+0

Sí. También estoy en GNU Make 3.81, así que tal vez se deba a algo más (glob?) Que se comporte de manera diferente en nuestras plataformas. Estoy en Ubuntu 10.10 amd64. –

9

Common practice es poner un Makefile en cada subdirectorio con las fuentes, a continuación,

all: recursive 
    $(MAKE) -C componentX 
    # stuff for current dir 

o

all: recursive 
    cd componentX && $(MAKE) 
    # stuff for current dir 

recursive: true 

Puede ser conveniente poner configuraciones para cada Makefile en un Makefile.inc en el directorio raíz de origen . El objetivo recursive fuerza make para ir a los subdirectorios. Asegúrese de que no recompile nada en un destino que requiera recursive.

+0

Claro, pero igual tendría que escribir "componentX" a mano, lo cual estoy tratando de evitar. – ggambett

+2

Por favor hágalo de esta manera. Simplemente compilar y vincular cada archivo de fuente/objeto en cada subdirector se romperá una vez que quiera construir una biblioteca, compilar un archivo con configuraciones especiales de compilador, escribir programas de prueba, etc. Siempre listé cada archivo de objeto en mis archivos Makefiles y algunas veces cada archivo fuente individual. Listar algunos directorios para repetir no es muy doloroso. –

+4

No llame 'make -C' directamente. Necesitas llamar '' $ (MAKE) -C' en su lugar. La versión de 'make' que se está ejecutando podría ser diferente del sistema' make'. Además, ¿no vas a activar un ciclo infinito ejecutando '$ (MAKE) $ @'? Por último, la marca recursiva se considera perjudicial para algunos. Consulte http://miller.emu.id.au/pmiller/books/rmch/ –

7

Esta es una nota al margen y no responde a su pregunta, pero hay un documento "Recursive Make Considered Harmful". Vale la pena leer.

Aquí está el enlace. http://aegis.sourceforge.net/auug97.pdf

+3

+1. Desprecio la marca recursiva y no creo que nadie deba publicitarla nunca más. Dar los subdires make.includes no es más difícil que darles sus propios makefiles. De hecho, es un poco más fácil porque no necesitan incluir un archivo "god" con todas las definiciones del proyecto. ¡Y oye, no obtienes un montón de gráficos de dependencia incompletos! Ese documento también da otros buenos consejos. –

+2

Aunque la creación recursiva puede ser perjudicial, la técnica que se busca en la pregunta original es en realidad una forma de * evitar * la creación recursiva, haciendo que el archivo de nivel superior conozca las fuentes en todos los subdirectorios. –

13

Si no desea utilizar los archivos make recursivas, esto podría darle algunas ideas:

subdirs := $(wildcard */) 
sources := $(wildcard $(addsuffix *.cpp,$(subdirs))) 
objects := $(patsubst %.cpp,%.o,$(sources)) 

$(objects) : %.o : %.cpp 
+0

Esa es una lista útil de comandos. 'subdirectorios: = $ (comodín * /)' ¡es lo que estaba buscando! – Mike

2

Si puede usar el comando de shell find, puede definir una función para usarlo.

recurfind = $(shell find $(1) -name '$(2)') 
SRCS := $(call recurfind,subdir1,*.c) $(call recurfind,subdir2,*.cc) $(call recurfind,subdir2,*.cu) \ 
     ... 
16

comodines recursivas se puede hacer puramente adentro hace, sin llamar a la concha o el comando find.Hacer la búsqueda usando solo Hacer significa que esta solución también funciona en Windows, no solo en * nix.

# Make does not offer a recursive wildcard function, so here's one: 
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) 

# How to recursively find all files with the same name in a given folder 
ALL_INDEX_HTMLS := $(call rwildcard,foo/,index.html) 

# How to recursively find all files that match a pattern 
ALL_HTMLS := $(call rwildcard,foo/,*.html) 

Se requiere una barra diagonal en el nombre de la carpeta. Esta función de rwildcard no es compatible con varios comodines de la forma en que lo hace la función comodín incorporada de Make, pero agregar esa compatibilidad sería sencillo con un par de usos adicionales de foreach.

+0

Esto no funciona para mí. Devuelve todos los subdirectorios y archivos independientemente del patrón proporcionado. – Antimony

+0

@Antimonio: (en caso de que lo haya hecho ...) No agregue espacios adicionales dentro del $ recursivo (llamada ...) alrededor de las comas que separan los argumentos. Agregar tales espacios altera el resultado. –