Eu sou um novato em makefiles e quero criar diretórios usando makefile. Meu diretório de projeto é assim
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
Quero colocar todos os objetos e a saída na respectiva pasta de saída. Quero criar uma estrutura de pastas que seja assim após a compilação.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
Tentei com várias opções, mas não consegui. Por favor me ajude a fazer diretórios usando make file. Estou postando meu Makefile para sua consideração.
#---------------------------------------------------------------------
# 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)
Desde já, obrigado. Por favor, me guie se eu também cometi algum erro.
output/debug', needed by
diretórios de destino . Pare." Mas não vou me preocupar com isso agora. seguirá as regras básicas. :). Obrigado por orientar. E estou executando "make" apenas no diretório de nível superior.directories
, sem causar-lhes para sempre reconstruir ..Na minha opinião, os diretórios não devem ser considerados alvos de seu makefile, seja no sentido técnico ou de design. Você deve criar arquivos e, se a criação de um arquivo precisar de um novo diretório, crie silenciosamente o diretório dentro da regra para o arquivo relevante.
Se você está almejando um arquivo normal ou "padronizado", apenas use
make
a variável interna de$(@D)
, que significa "o diretório em que o destino atual reside" (cmp. Com$@
para o destino). Por exemplo,Então, você estará efetivamente fazendo o mesmo: criar diretórios para todos
$(OBJS)
, mas de uma maneira menos complicada.A mesma política (arquivos são destinos, diretórios nunca) é usada em vários aplicativos. Por exemplo, o
git
sistema de controle de revisão não armazena diretórios.Nota: Se você for usá-lo, pode ser útil introduzir uma variável de conveniência e utilizar
make
as regras de expansão de.fonte
Ou KISS.
Isso criará todos os diretórios depois que o Makefile for analisado.
fonte
$(info $(shell mkdir -p $(DIRS)))
sem o$(info ...)
, a saída domkdir
comando será colada no Makefile , levando a erros de sintaxe na melhor das hipóteses. A$(info ...)
chamada garante que a) os erros (se houver) sejam visíveis para o usuário eb) que a chamada de função se expanda a nada.make
dentro e fora dele, trata os destinos de diretório da mesma forma que os destinos de arquivo. Portanto, é fácil escrever regras como esta:O único problema com isso é que a data e hora dos diretórios depende do que é feito com os arquivos dentro deles. Para as regras acima, isso leva ao seguinte resultado:
Isso definitivamente não é o que você quer. Sempre que você toca no arquivo, também toca no diretório. E como o arquivo depende do diretório, o arquivo consequentemente parece estar desatualizado, forçando-o a ser reconstruído.
No entanto, você pode facilmente interromper esse loop dizendo ao make para ignorar o carimbo de data / hora do diretório . Isso é feito declarando o diretório como um pré-requisito somente para pedido:
Isso produz corretamente:
TL; DR:
Escreva uma regra para criar o diretório:
E fazer com que os alvos para o material interno dependam do diretório apenas por ordem:
fonte
touch
modificar algum dado estatístico no diretório pai? Isso não faz sentido para mim. O mtime de um dir depende apenas dos nomes de arquivo que ele contém. Não consegui reproduzir seu problema.Todas as soluções, incluindo a aceita, apresentam alguns problemas, conforme declarado em seus respectivos comentários. A resposta aceita por @ jonathan-leffler já é muito boa, mas não leva em consideração que os pré-requisitos não devem ser necessariamente criados em ordem (durante,
make -j
por exemplo). No entanto, simplesmente mover odirectories
pré-requisito deall
paraprogram
provoca reconstruções em cada AFAICT executado. A solução a seguir não tem esse problema e AFAICS funciona conforme o planejado.fonte
Acabei de apresentar uma solução bastante razoável que permite definir os arquivos a serem construídos e fazer com que os diretórios sejam criados automaticamente. Primeiro, defina uma variável
ALL_TARGET_FILES
que contém o nome do arquivo de cada arquivo que seu makefile será construído. Em seguida, use o seguinte código:É assim que funciona. Eu defino uma função
depend_on_dir
que pega um nome de arquivo e gera uma regra que faz o arquivo depender do diretório que o contém e, em seguida, defino uma regra para criar esse diretório, se necessário. Então eu usoforeach
paracall
esta função em cada nome de arquivo eeval
o resultado.Observe que você precisará de uma versão do GNU make que suporte
eval
, que eu acho que é a versão 3.81 e superior.fonte
já que você é um novato, diria que não tente fazer isso ainda. é definitivamente possível, mas complicará desnecessariamente o seu Makefile. siga as formas simples até ficar mais confortável com o make.
Dito isso, uma maneira de construir em um diretório diferente do diretório de origem é VPATH ; eu prefiro regras padrão
fonte
A independência do sistema operacional é crítica para mim, portanto,
mkdir -p
não é uma opção. Criei esta série de funções que usameval
para criar destinos de diretório com o pré-requisito no diretório pai. Isso tem a vantagem demake -j 2
funcionar sem problemas, pois as dependências são determinadas corretamente.Por exemplo, a execução do acima criará:
fonte
Consulte https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html
Como eu uso o Ubuntu, também precisei adicionar isso no topo do meu Makefile:
fonte