Um Makefile com vários executáveis

Eu estou tentando escrever um makefile que usa macros para criar vários executáveis ​​de vários arquivos ao mesmo tempo. Eu tentei pesquisar em perguntas respondidas anteriormente, mas, como sou relativamente novo em programar em C e também trabalhei com o gcc, não consegui encontrar uma resposta para minha pergunta.

Aqui está o que eu tenho até agora:

CC=gcc CFLAGS=-I. OBJ = ex1.c ex3.c EXECUTABLE = ex1 ex3 $(EXECUTABLE): $(OBJ) gcc -o $@ $^ $(CFLAGS) clean: rm -f $(EXECUTABLE) 

Eu gostaria da linha

 $(EXECUTABLE): $(OBJ) 

para criar executáveis ​​ex1 e ex3 a partir dos arquivos ex1.c ex3.c respectivamente.

Para este caso em particular, onde cada executável possui um único arquivo de origem com extensão .c , tudo o que você precisa é de um Makefile de uma linha:

 all: ex1 ex3 

As regras padrão internas para make então já funcionam:

 $ make cc -O2 -pipe ex1.c -o ex1 cc -O2 -pipe ex3.c -o ex3 

Por trás da cena, make está usando a regra de sufixo único embutida pelo POSIXly mandated

 .c: $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<  

Varie o comando ao seu gosto com make CC=gcc CFLAGS=-O2 LDFLAGS=-s e similar.

Curiosidades do dia: de fato, se você estiver disposto a nomear os alvos ao invocar o make , você pode usar um vazio ou mesmo rodar sem qualquer Makefile:

 $ make -f /dev/null CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3 gcc -O2 -s ex1.c -o ex1 gcc -O2 -s ex3.c -o ex3 $ rm -f Makefile ex1 ex3 $ make CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3 gcc -O2 -s ex1.c -o ex1 gcc -O2 -s ex3.c -o ex3 

Faça mágica!

Como regra geral, não reinvente a roda (ou regras), use as regras que já estão lá. Simplifica muito a sua vida. Isto faz pequenos e sexy makefiles para impressionar as mulheres com 🙂

Algumas sugestões (supondo que você use o GNU make , não outra coisa)

Primeiro, execute uma vez make -p , você vai entender o que as regras internas make é saber. Olhe em particular para COMPILE.c e LINK.c

Então, sugiro

  CFLAGS= -g -Wall -I. 

(porque você realmente quer -g para debugging, e -Wall para obter mais avisos)

E você provavelmente não precisa

 $(EXECUTABLE): $(OBJ) gcc -o $@ $^ $(CFLAGS) 

No entanto, sugiro adicionar antes da maioria das outras regras

 .PHONY: all clean all: $(EXECUTABLES) 

Na verdade, eu iria codificar seu Makefile (para o GNU make !) Como segue

 # file Makefile CC= gcc RM= rm -vf CFLAGS= -Wall -g CPPFLAGS= -I. SRCFILES= ex1.c ex2.c ## or perhaps $(wildcard *.c) OBJFILES= $(patsubst %.c, %.o, $(SRCFILES)) PROGFILES= $(patsubst %.c, %, $(SRCFILES)) .PHONY: all clean all: $(PROGFILES) clean: $(RM) $(OBJFILES) $(PROGFILES) *~ ## eof Makefile 

Lembre-se que a aba é um caractere significativo no Makefile -s (parte de ação das regras ). Nesta resposta, as linhas que começam com quatro espaços devem, pelo menos, começar com um caractere de tabulação .

Depois que tudo for depurado, considere executar make clean para limpar tudo e, em seguida, make -j CFLAGS=-O2 all para compilar em paralelo tudo com otimizações.

Finalmente, eu recomendo usar remake e executando remake -x para depurar o complexo Makefile -s

Claro, suponho que o seu diretório tenha apenas programas de arquivo único.

BTW, existem outros programas de construtor. Talvez você possa considerar omake

Não esqueça de usar um sistema de version control como o git para seus arquivos de origem. Também é hora de aprender tal ferramenta.

Você está perto, mas precisa de uma regra padrão:

 $(EXECUTABLE): % : %.c 

E, em seguida, uma regra padrão para criar os dois:

 all: $(EXECUTABLE) 

A resposta a seguir inclui vários executáveis, como iniciar, processo1, processo2, …, processo4.

 LOCAL_INCLUDE=./ all: clean process_first process_second init process_first: gcc -g -o process1 -I$(LOCAL_INCLUDE) process1.c -lzmq -L. -L./. gcc -g -o process2 -I$(LOCAL_INCLUDE) process2.c -lzmq -L. -L./. process_second: gcc -g -o process3 -I$(LOCAL_INCLUDE) process3.c -lzmq -L. -L./. gcc -g -o process4 -I$(LOCAL_INCLUDE) process4.c -lzmq -L. -L./. init: gcc -g -o initiate -I$(LOCAL_INCLUDE) initiate.c -lzmq -lconfig -lpthread -L. -L./. -ldl -lrt clean: rm -rf init_manager.o init_manager rm -rf process1 process2 process3 process4 

NOTA: É uma boa prática limpar e tocar em todos os arquivos executáveis ​​antes de realizá-los novamente.