Usando variáveis de ambiente para receitas mais curtas no GNU Make

1

Eu gostaria que receitas no GNU Make usassem variáveis de ambiente em vez de argumentos de linha de comando, para torná-los mais curtos, para que eu pudesse me concentrar melhor em quais mudanças em cada comando. Por exemplo, em vez de ver:

g++ -g -I/path1 -I/path2 -DFLAG  -Wall -c hello.cpp -o hello.o

Gostaria de ver algo como:

g++ -c hello.cpp -o hello.o

onde g++ leria diretórios de inclusão e tudo mais de variáveis de ambiente. Portanto, em vez de usar isso:

compile.cxx = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c

%.o: %.cpp
    $(compile.cxx) $< -o $@

Estou usando isso:

compile.cxx = CPATH="$(CPATH)" LIBRARY_PATH="$(LIBRARY_PATH)" bash -c $(CXX) -c

%.o: %.cpp
    $(compile.cxx) $< -o $@

Mas recebo esta saída:

CPATH="irrelevant" LIBRARY_PATH="irrelevant" bash -c g++ -c hello.cpp -o hello.o
g++: fatal error: no input files

Portanto, parece que g++ não recebe seus argumentos.

Estou também aberto a alternativas que tenham um efeito semelhante (ou seja: receitas curtas).

    
por Elena 29.06.2015 / 15:05

4 respostas

2

Você pode querer usar o chamado arquivo de resposta do compilador, que é muito comum em MS toolchains . Aparentemente, versões recentes do GCC também o suportam (consulte manual ).

CXX = g++
CPPFLAGS = -I/path1 -I/path2 -DFLAG
CXXFLAGS = -g -Wall
CXXOPTS = $(CURDIR)/cxx.opts

%.o: %.cpp $(CXXOPTS)
        $(CXX) @$(CXXOPTS) -c -o $@ $<

$(CXXOPTS):
        echo "$(CPPFLAGS) $(CXXFLAGS)" >$@

clean:
        rm -f *.o
        rm -f $(CXXOPTS)

Sessão de amostra:

$ touch a.cpp b.cpp c.cpp
$ make a.o b.o c.o
echo "-I/path1 -I/path2 -DFLAG -g -Wall" >cxx.opts
g++ @cxx.opts -c -o a.o a.cpp
g++ @cxx.opts -c -o b.o b.cpp
g++ @cxx.opts -c -o c.o c.cpp
$ make clean
rm -f *.o
rm -f cxx.opts
    
por 29.06.2015 / 17:07
0

Esta não é uma resposta completa, mas uma primeira dica e parece bastante feia

v:=bash -x -c "
all:
    $vls -l"

mas funciona.

    
por 29.06.2015 / 15:38
0

Seu problema é simly que bash -c leva apenas 1 arg, e simplesmente você não precisa dele. Experimente:

compile.cxx = CPATH="$(CPATH)" LIBRARY_PATH="$(LIBRARY_PATH)" $(CXX) -c
    
por 29.06.2015 / 16:45
0

Alguns makefiles são configurados para imprimir um comando e executar um comando diferente, através do uso de macros que podem ser complexas. Aqui está uma maneira simples de fazer isso:

ifeq(debug,)
cc = $(CC) $(CFLAGS)
else
cc = @cc () { echo "\$$(CC) $<"; $(CC) $(CFLAGS) "$$@" }; cc
endif

foo.o: foo.c
        $(cc) $<

Se a variável debug tiver um valor não vazio, esse fragmento imprimirá o comando normalmente. Caso contrário, esse fragmento ocultará o comando (a linha de comando será iniciada com @ ) e imprimirá um comando simples e substituído antes de executar o comando real.

Eu apresentei um exemplo muito simples. Várias variantes mais complexas existem em diferentes projetos. Por exemplo, o kernel do Linux usa um esquema bastante avançado.

Eu não recomendo isso porque eles dificultam a depuração de makefiles. Algo falha devido a um caminho de inclusão ruim ou algo assim, e a saída do make não informa. Esquemas sofisticados que registram comandos inteiros em um arquivo e mostram um comando abreviado no terminal são aceitáveis.

Para tornar a saída mais legível, considere colormake em seu lugar.

    
por 30.06.2015 / 02:00

Tags