Pergunta sobre makefile, c++ – makefile detecção automática de arquivos src e geração de dependência

2

Eu tenho a seguinte configuração para o meu projeto c ++:

na pasta src, existem arquivos * .cpp e correspondentes * .h e nas pastas obj eu quero ter meus arquivos .o.

até agora, compilar e vincular não é o problema. Mas agora eu tenho muitos arquivos .cpp e .h para colocá-los no Makefile manualmente. Então eu decidi escrever esta pequena instrução no makefile:

<code>collect_sources:
@echo "collecting source files";
@echo "SRCS = \\" > sources;
@for file in ./src/*.cpp; \
do \
    echo "$$file \\" >> sources; \
done
</code>

Eu também faço

<code>-include sources
</code>

no início do makefile

O arquivo resultantesources parece bem, embora haja uma barra invertida na última linha que eu não gosto. Mas afaik deve ser prejudicial também.

Agora também preciso criar dependências automaticamente. Na minha última versão em que eu defini os arquivos * .cpp comoSRCS diretamente no Makefile, o seguinte código era bom:

<code>$(SRCDIR)/%.cpp:
  @$(CXX) $(DEPFLAGS) -MT \
  "$(subst $(SRCDIR),$(OBJDIR),$(subst $(EXT_SRC),$(EXT_OBJ),$$file))" \
  $(addprefix ,$$file) >> $(DEP);
clear_dependencies:
    echo "" > $(DEP);

depend: clear_dependencies $(SRCS)
</code>

Mas com a inclusão dosources-file, nunca atinge o bloco de código superior.

Aqui estão as constantes definidas no topo do Makefile:

<code>CXX = g++
CXXFLAGS = -Wall \
       -Wextra \
       -Wuninitialized \
       -Wmissing-declarations \
       -pedantic \
       -O3 \
       -p -g -pg
LDFLAGS =  -p -g -pg
DEPFLAGS = -MM

SRCDIR  = ./src
OBJDIR  = ./obj

TARGET = ./bin/my_funky_function_which_is_not_the_real_name

-include sources

OBJSTMP =   $(SRCS:.cpp=.o)
OBJS        =   $(OBJSTMP:$(SRCDIR)=$(OBJDIR))
DEP = depend.main
EXT_SRC =   .cpp
EXT_OBJ =   .o
</code>

o que estou perdendo? Minha abordagem é válida / viável?

Há um erro simples e muita melhoria possível. Até onde você quer ir? Beta
em uma nota lateral: por favor, não sugira nenhuma ferramenta que faça isso. Eu realmente quero entender isso e ter controle total sobre o que está acontecendo. stefan
passo a passo para o ótimo absoluto ;-) stefan

Sua resposta

1   a resposta
7

Tudo bem, você pediu por isso.

1: Seucollect_sources:... include sources é gloriosa hackery de Rube Goldberg. Apenas faça isso:

<code>SRCS = $(wildcard ./src/*.cpp)
</code>

E se você quiser confirmar isso de olho, você pode fazer isso:

<code>$(info $(SRCS))
</code>

2:

<code>clear_dependencies:
    echo "" > $(DEP);
</code>

Apenas por uma questão de estética, vamos consertar isso.

<code>clear_dependencies:
    $(RM) $(DEP);
</code>

3:

<code>$(SRCDIR)/%.cpp:
    @$(CXX) $(DEPFLAGS) -MT \
  "$(subst $(SRCDIR),$(OBJDIR),$(subst $(EXT_SRC),$(EXT_OBJ),$$file))" \
  $(addprefix ,$$file) >> $(DEP);
</code>

Isso levará algum trabalho. Primeiro, o problema imediato: o alvo é um arquivo real que existe e a regra não tem pré-requisitos. Portanto, a regra não será executada (não faço ideia do motivo pelo qual funcionou para você em uma versão anterior, talvez outra coisa fosse diferente). Como uma correção temporária, sugiro que mudemos para uma regra de padrão estático e para os destinos PHONY:

<code>.PHONY:$(SRCS)
$(SRCS) : $(SRCDIR)/%.cpp:
    @$(CXX) $(DEPFLAGS) -MT \
   ...
</code>

Veja se tudo isso funciona, então podemos lidar com as grandes coisas.

Não, é um efeito colateral de fazer as origens PHONY das origens. Beta
@ Stefan, provavelmente[email protected]. Na prática, Make usará esta regra quando considerar reconstruir algo como./src/foo.cpp. Isso quase certamente será um arquivo que já existe (a menos que haja mais problemas do que você nos disse). Então, o Make concluirá que o arquivo está atualizado e não precisa ser reconstruído. Mesmo se / quando o Make executar a regra, eu não acho que o$$file coisas vão funcionar. Beta
você está absolutamente correto. e com a sua sugestão "PHONY" e "$ @" funciona bem :) stefan
Legal. Em poucas horas, terei tempo para adicionar mais. Beta

Perguntas relacionadas