Pregunta

Necesito generar un directorio en mi archivo MAKE y me gustaría no recibir el error "el directorio ya existe" una y otra vez, aunque puedo ignorarlo fácilmente.

Utilizo principalmente mingw/msys pero me gustaría algo que funcione en otros shells/sistemas también.

Intenté esto pero no funcionó, ¿alguna idea?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
¿Fue útil?

Solución

En UNIX solo usa esto:

mkdir -p $(OBJDIR)

La opción -p para mkdir evita el mensaje de error si el directorio existe.

Otros consejos

Mirando a la documentación oficial de la marca, aquí tienes una buena forma de hacerlo:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

Deberías ver aquí el uso del | Operador de tubería, definiendo un requisito previo de orden solo.Lo que significa que el $(OBJDIR) El objetivo debe existir (en lugar de más reciente) para construir el objetivo actual.

Tenga en cuenta que utilicé mkdir -p.El -p Se agregó la bandera en comparación con el ejemplo de los documentos.Vea otras respuestas para otra alternativa.

Puedes usar el comando de prueba:

test -d $(OBJDIR) || mkdir $(OBJDIR)

Aquí hay un truco que uso con GNU make para crear directorios de salida del compilador.Primero defina esta regla:

  %/.d:
          mkdir -p $(@D)
          touch $@

Luego haga que todos los archivos que van al directorio dependan del archivo .d en ese directorio:

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

Tenga en cuenta el uso de $< en lugar de $^.

Finalmente evite que los archivos .d se eliminen automáticamente:

 .PRECIOUS: %/.d

Omitir el archivo .d y depender directamente del directorio no funcionará, ya que la hora de modificación del directorio se actualiza cada vez que se escribe un archivo en ese directorio, lo que forzaría la reconstrucción en cada invocación de make.

Si tener el directorio ya existente no es un problema para usted, puede simplemente redirigir stderr para ese comando, eliminando el mensaje de error:

-mkdir $(OBJDIR) 2>/dev/null

Dentro de tu archivo MAKE:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi

En Windows

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

En unix | Linux

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
ifeq "$(wildcard $(MY_DIRNAME) )" ""
  -mkdir $(MY_DIRNAME)
endif
$(OBJDIR):
    mkdir $@

Lo que también funciona para múltiples directorios, por ejemplo.

OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

Añadiendo $(OBJDIR) ya que el primer objetivo funciona bien.

Funciona bajo mingw32/msys/cygwin/linux

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

Si ignora explícitamente el código de retorno y descarta el flujo de error, su marca ignorará el error si ocurre:

mkdir 2>/dev/null || true

Esto no debería causar un peligro de carrera en una marca paralela, pero no lo he probado para estar seguro.

Un poco más simple que la respuesta de Lars:

something_needs_directory_xxx : xxx/..

y regla genérica:

%/.. : ;@mkdir -p $(@D)

No hay archivos táctiles para limpiar o hacer .PRECIOUS :-)

Si desea ver otro pequeño truco genérico de gmake, o si está interesado en un make no recursivo con un andamiaje mínimo, puede consultar Dos trucos más baratos de gmake y las otras publicaciones relacionadas con make en ese blog.

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