objeto plano de salida de la estructura de directorios de archivos con GNU Hacer

StackOverflow https://stackoverflow.com/questions/1365305

  •  21-09-2019
  •  | 
  •  

Pregunta

Tengo un pequeño proyecto C ++ usando GNU Make. Me gustaría ser capaz de convertir los archivos de código siguiente:

src/
  a.cpp
  b/
    b.cpp
  c/
    c.cpp

en la siguiente estructura de salida (no estoy preocupado por duplicados en este punto):

build/
  a.o
  b.o
  c.o

Hasta ahora tengo el siguiente, que por desgracia pone el .oy .D uno al lado del .cpp:

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

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

Soy consciente de la (notdir ...) la función $, pero en este momento mis esfuerzos para utilizar para filtrar los objetos ha fallado. ¿Alguien puede arrojar algo de luz sobre esto? Parece algo bastante razonable para hacerlo.

¿Fue útil?

Solución

Hay al menos dos maneras de hacer esto. En primer lugar (y lo que yo recomiendo) es que se puede añadir el directorio de construcción a los nombres de destino (incluso cuando se utiliza una regla de patrón). Por ejemplo:

$(OBJS) : build/%.o : %.cpp

En segundo lugar, puede utilizar la variable VPATH para decirle hacer para buscar un directorio diferente para requisitos previos. Esta es probablemente la más común (sobre) la metodología utilizados. Tiene al menos un serio inconveniente, y es que si vas con él, y más tarde a tener problemas con "duplicados", no hay manera de resolver el problema. Con el primer enfoque, siempre se puede reflejar la estructura de directorio de origen debajo del directorio de construcción para evitar duplicados choque.

Editar Mi respuesta anterior era un poco corto en detalle, por lo que se expandirá en ella para demostrar que esto realmente funciona como se anuncia. Aquí está un ejemplo de trabajo completa Makefile que utiliza la primera técnica descrita anteriormente para resolver el problema. Basta con pegar esto en un Makefile y ejecute make -. Lo hará el resto y demostrar que este hecho funciona

Editar No puedo encontrar la manera de conseguir así que para permitir que los caracteres de tabulación en mi texto de la respuesta (se los reemplazó con espacios). Después de copiar y pegar este ejemplo, tendrá que convertir los espacios iniciales en los scripts de comandos en pestañas.

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}

En particular, tenga en cuenta que existen archivos de origen con nombres duplicados (A.C. y / A.C., b.c y B / b.c, etc) y que esto no causa ningún problema. También tenga en cuenta que no hay uso de VPATH, que recomiendo evitar el uso debido a sus limitaciones inherentes.

Otros consejos

vpath %.cpp src src/b src/c

A continuación, consulte los archivos de origen sin su nombre de directorio; Hacer buscará la vpath .

La creación de la estructura de directorios plana según lo solicitado inicialmente.

¿El uso vpath de localizar los archivos de origen, pero todo el bookeeping se hace automágicamente de la lista SRC.

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

Lo siento por el echo fea de, pero yo sólo tenía mi caja victoria para probarlo en.

Esto es para Win32 mingw32-make. funciona. La parte más importante es

-mkdir $(patsubst %/,%,$(dir $@))

para Win32. Tenemos que pelar el trailling / para Win32.

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

Es posible que no gusta especialmente este enfoque, pero:

AUTOMAKE_OPTIONS =

apaño bastante bien en un Makefile.am. Simplemente diciendo que no es necesario escribir todo a mano.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top