Pergunta

Eu estou usando GCC para gerar um arquivo de dependência, mas as minhas regras de compilação colocar a saída em um subdiretório. Existe uma maneira de dizer GCC para colocar o meu prefixo subdiretório no arquivo de dependência que gera para mim?

gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
Foi útil?

Solução

A resposta está na GCC Manual :. utilizar a bandeira -MT

-MT target

Alterar o alvo da regra emitida pela geração de dependência. Por padrão CPP leva o nome do arquivo de entrada principal, elimina quaisquer componentes do diretório e qualquer arquivo sufixo como .c, e acrescenta sufixo objeto habitual da plataforma. O resultado é o alvo.

Uma opção -MT irá definir o alvo a ser exatamente a string que você especificar. Se você quiser alvos múltiplos, você pode especificá-los como um único argumento para -MT, ou usar várias opções -MT.

Por exemplo, -MT '$(objpfx)foo.o' poderia dar

$(objpfx)foo.o: foo.c

Outras dicas

Eu estou supondo que você está usando o GNU make e GCC. Primeiro adicione uma variável para armazenar sua lista de arquivos de dependência. Supondo que você já tem um que lista todas as nossas fontes:

SRCS = \
        main.c \
        foo.c \
        stuff/bar.c

DEPS = $(SRCS:.c=.d)

Em seguida, incluem as dependências geradas no makefile:

include $(DEPS)

Em seguida, adicione esta regra padrão:

# automatically generate dependency rules

%.d : %.c
        $(CC) $(CCFLAGS) -MF"$@" -MG -MM -MP -MT"$@" -MT"$(<:.c=.o)" "$<"

# -MF  write the generated dependency rule to a file
# -MG  assume missing headers will be generated and don't stop with an error
# -MM  generate dependency rule for prerequisite, skipping system headers
# -MP  add phony target for each header to prevent errors when header is missing
# -MT  add a target to the generated dependency

"$ @" é o alvo (a coisa no lado esquerdo do:), "$ <" é o pré-requisito (a coisa no lado direito do:). A expressão "$ (<:. c = .o)" substitui a extensão .c com .o.

O truque aqui é para gerar a regra com dois alvos, adicionando -MT duas vezes; isso faz com que tanto o arquivo .o eo arquivo .d dependem do arquivo de origem e seus cabeçalhos; Dessa forma, o arquivo de dependência fica regenerado automaticamente sempre que qualquer um dos .c correspondente ou .h são alterados.

O -MG e -MP opções manter make de surtar, se um arquivo de cabeçalho está faltando.

Você pode gostar esta versão mais breve do Don McCaughey de resposta :

SRCS = \
    main.c \
    foo.c \
    stuff/bar.c

DEPS = $(SRCS:.c=.d)

Observação Adicione -include $(DEPS) o prefixo -, que erros silêncios, se ainda não existem os arquivos .d.

Não há nenhuma necessidade para uma regra padrão separado para gerar os arquivos de dependência. Basta adicionar -MD ou -MMD para sua linha de compilação normal, e os arquivos .d são geradas ao mesmo tempo seus arquivos de origem são compilados. Por exemplo:

%.o: %.c
     gcc $(INCLUDE) -MMD -c $< -o $@

# -MD can be used to generate a dependency output file as a side-effect of the compilation process.

de DGentry resposta , esta tem funcionado bem para mim:

.depend: $(SOURCES)
    $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend

Isso também funciona no caso em que há apenas um arquivo de dependência que contém as regras de dependência para todos os arquivos de origem.

Ok, só para ter certeza que eu tenho o direito pergunta: Eu estou supondo que você tem test.c que inclui test.h, e você quer gerar subdir/test.d (enquanto não subdir/test.o geração), onde subdir/test.d contém

subdir/test.o: test.c test.h

em vez de

test.o: test.c test.h

que é o que você começa agora. Está certo?

Eu não era capaz de chegar a uma maneira fácil de fazer exatamente o que você está pedindo. No entanto, olhando para Dependência Geração Melhorias , se você quiser criar o arquivo .d enquanto você gerar o arquivo .o, você pode usar:

gcc $(INCLUDES) -MMD $(CFLAGS) $(SRC) -o $(SUBDIR)/$(OBJ)

(Dada SRC=test.c, SUBDIR=subdir, e OBJ=test.o.) Isto irá criar tanto subdir / test.o e subdir / test.d, onde subdir/test.d contém a saída desejada como acima.

Se houver um argumento para GCC para fazer isso, eu não sei o que é. Nós acabam canalizando a saída dependência através sed para reescrever todas as ocorrências de <blah>.o como ${OBJDIR}/<blah>.o.

  1. [GNU] make fica irritado se você não colocar a saída no diretório atual. Você realmente deve executar make do diretório de compilação, e usar a variável VPATH make para localizar o código-fonte. Se você mentir para um compilador, mais cedo ou mais tarde ele vai tomar seu vingança.

  2. Se você insistir em geração de seus objetos e dependências em algum outro diretório, você precisa usar o argumento -o, como respondida por Emile .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top