Soy muy nuevo en makefiles y quiero crear directorios usando makefile. Mi directorio de proyectos es así
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
Quiero poner todos los objetos y la salida en la carpeta de salida respectiva. Quiero crear una estructura de carpetas que sería así después de compilar.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
Intenté con varias opciones, pero no pude. Ayúdame a crear directorios usando make file. Estoy publicando mi Makefile para su consideración.
#---------------------------------------------------------------------
# Input dirs, names, files
#---------------------------------------------------------------------
OUTPUT_ROOT := output/
TITLE_NAME := TestProj
ifdef DEBUG
TITLE_NAME += _DEBUG
else
ifdef RELEASE
TITLE_NAME += _RELEASE
endif
endif
# Include all the source files here with the directory tree
SOURCES := \
source/TestFile.cpp \
#---------------------------------------------------------------------
# configs
#---------------------------------------------------------------------
ifdef DEBUG
OUT_DIR := $(OUTPUT_ROOT)debug
CC_FLAGS := -c -Wall
else
ifdef RELEASE
OUT_DIR := $(OUTPUT_ROOT)release
CC_FLAGS := -c -Wall
else
$(error no build type defined)
endif
endif
# Put objects in the output directory.
OUT_O_DIR := $(OUT_DIR)/objs
#---------------------------------------------------------------------
# settings
#---------------------------------------------------------------------
OBJS = $(SOURCES:.cpp=.o)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
DIR_TARGET = $(OUT_DIR)
OUTPUT_TARGET = $(OUT_DIR)/$(TITLE_NAME)
CC_FLAGS +=
LCF_FLAGS :=
LD_FLAGS :=
#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir
RM := rm
CC := g++
#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: all clean title
all: title
clean:
$(RM) -rf $(OUT_DIR)
$(DIR_TARGET):
$(MD) -p $(DIRS)
.cpp.o:
@$(CC) -c $< -o $@
$(OBJS): $(OUT_O_DIR)/%.o: %.cpp
@$(CC) -c $< -o $@
title: $(DIR_TARGET) $(OBJS)
Gracias por adelantado. Por favor, guíeme si también cometí algún error.
output/debug', needed by
directorios de destino ". Detener ". Pero no me voy a preocupar por eso ahora. se apegará a las reglas básicas. :). Gracias por guiarnos. Y estoy ejecutando "make" solo desde el directorio de nivel superior.directories
sin causar a reconstruir siempre ..En mi opinión, los directorios no deberían considerarse objetivos de su archivo MAKE, ni en sentido técnico ni de diseño. Debe crear archivos y si la creación de un archivo necesita un nuevo directorio, cree silenciosamente el directorio dentro de la regla para el archivo relevante.
Si está apuntando a un archivo normal o "con patrón", simplemente use
make
la variable interna$(@D)
, que significa "el directorio en el que reside el objetivo actual" (cmp. With$@
para el objetivo). Por ejemplo,Entonces, estás haciendo efectivamente lo mismo: crea directorios para todos
$(OBJS)
, pero lo harás de una manera menos complicada.La misma política (los archivos son destinos, los directorios nunca lo son) se usa en varias aplicaciones. Por ejemplo, el
git
sistema de control de revisiones no almacena directorios.Nota: Si lo va a utilizar, puede resultar útil introducir una variable de conveniencia y utilizar
make
las reglas de expansión.fuente
O, BESO.
Esto creará todos los directorios después de analizar el Makefile.
fuente
$(info $(shell mkdir -p $(DIRS)))
sin el$(info ...)
, la salida delmkdir
comando se pegará en el Makefile , lo que provocará errores de sintaxis en el mejor de los casos. La$(info ...)
llamada asegura que a) los errores (si los hay) sean visibles para el usuario, yb) que la llamada a la función se expanda a la nada.make
dentro y fuera de sí mismo, maneja los destinos de directorio de la misma manera que los destinos de archivo. Entonces, es fácil escribir reglas como esta:El único problema con eso es que la marca de tiempo de los directorios depende de lo que se haga con los archivos internos. Para las reglas anteriores, esto conduce al siguiente resultado:
Definitivamente, esto no es lo que quieres. Siempre que toca el archivo, también toca el directorio. Y dado que el archivo depende del directorio, el archivo parece estar desactualizado, lo que obliga a reconstruirlo.
Sin embargo, puede romper fácilmente este ciclo diciéndole a make que ignore la marca de tiempo del directorio . Esto se hace declarando el directorio como un prerrequisito de solo pedido:
Esto produce correctamente:
TL; DR:
Escribe una regla para crear el directorio:
Y hacer que los objetivos de las cosas internas dependan solo del orden del directorio:
fuente
touch
modificar algún dato estadístico en el directorio principal? Eso no tiene sentido para mí. El mtime de un directorio solo depende de los nombres de archivo que contiene. No pude reproducir tu problema.Todas las soluciones, incluida la aceptada, tienen algunos problemas, como se indica en sus respectivos comentarios. La respuesta aceptada por @ jonathan-leffler ya es bastante buena, pero no tiene en cuenta que los requisitos previos no necesariamente deben construirse en orden (durante,
make -j
por ejemplo). Sin embargo, simplemente mover eldirectories
requisito previo deall
aprogram
provoca reconstrucciones en cada ejecución AFAICT. La siguiente solución no tiene ese problema y AFAICS funciona según lo previsto.fuente
Acabo de encontrar una solución bastante razonable que le permite definir los archivos para compilar y crear directorios automáticamente. Primero, defina una variable
ALL_TARGET_FILES
que contenga el nombre de archivo de cada archivo que se construirá su archivo MAKE. Luego usa el siguiente código:Así es como funciona. Defino una función
depend_on_dir
que toma un nombre de archivo y genera una regla que hace que el archivo dependa del directorio que lo contiene y luego define una regla para crear ese directorio si es necesario. Luego usoforeach
decall
esta función en cada nombre de archivo yeval
el resultado.Tenga en cuenta que necesitará una versión de GNU make compatible
eval
, que creo que es la versión 3.81 y superior.fuente
dado que eres un novato, diría que no intentes hacer esto todavía. definitivamente es posible, pero complicará innecesariamente su Makefile. apégate a las formas simples hasta que te sientas más cómodo con make.
Dicho esto, una forma de construir en un directorio diferente del directorio de origen es VPATH ; prefiero reglas de patrones
fuente
La independencia del sistema operativo es fundamental para mí, así
mkdir -p
que no es una opción. Creé esta serie de funciones que se utilizaneval
para crear destinos de directorio con el requisito previo en el directorio principal. Esto tiene el beneficio de quemake -j 2
funcionará sin problemas ya que las dependencias están determinadas correctamente.Por ejemplo, ejecutar lo anterior creará:
fuente
Consulte https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html
Como uso Ubuntu, también necesitaba agregar esto en la parte superior de mi Makefile:
fuente