2011-01-12 8 views
8

Tengo un código común (por ejemplo, hello.cpp) que utilizan varios ejecutables. Estoy usando una sola Makefile para construir todo:Ayuda para simplificar un Makefile para varios archivos ejecutables

EXE=app1.out app2.out 
SRC=hello.cpp 
OBJ=$(SRC:.cpp=.o) 
SRC_MAIN=app1.cpp app2.cpp 
OBJ_MAIN=$(SRC_MAIN:.cpp=.o) 
all: $(EXE)  
app1.out: app1.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected]  
app2.out: app2.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected]  
.cpp.o: 
    g++ -c $< -o [email protected]  
clean: 
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN) 

No estoy muy feliz de tener un objetivo específico para cada ejecutable - los objetivos son esencialmente los mismos. ¿Hay alguna forma de hacer esto con un objetivo para todos los ejecutables? Tenía la esperanza de que algo como esto funcionaría:

EXE=app1.out app2.out 
SRC=hello.cpp 
OBJ=$(SRC:.cpp=.o) 
SRC_MAIN=app1.cpp app2.cpp 
OBJ_MAIN=$(SRC_MAIN:.cpp=.o) 
all: $(EXE) 
.o.out: $(OBJ) 
    g++ $< $(OBJ) -o [email protected] 
.cpp.o: 
    g++ -c $< -o [email protected] 
clean: 
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN) 

Pero consigo un error de vinculación:

[email protected]:~/cpp/stack$ make -f Makefile2 
g++ -c app1.cpp -o app1.o 
g++ app1.o hello.o -o app1.out 
g++: hello.o: No such file or directory 
make: *** [app1.out] Error 1 
rm app1.o 

Por alguna razón se trata de construir app1.out sin la construcción de su dependencia hello.o. ¿Alguien puede explicar por qué esto no funciona y sugerir algo que sí funciona?

Aquí está el resto del código ficticio, por las dudas.

app1.cpp:

#include "hello.h" 
int 
main(void) 
{ 
    print_hello(); 
} 

app2.cpp:

#include "hello.h"  
int 
main(void) 
{ 
    for (int i = 0; i < 4; ++i) 
     print_hello(); 
    return 0; 
} 

hello.cpp:

#include "hello.h"  
#include <stdio.h>  
void 
print_hello() 
{ 
    printf("hello world!\n"); 
} 

hello.h:

#ifndef HELLO_H 
#define HELLO_H 
void 
print_hello(); 
#endif 

Respuesta

4

El problema parece ser que está utilizando reglas de sufijo de estilo antiguo. A partir de la información de la marca:

Suffix rules cannot have any prerequisites of their own. If they have any, they are treated as normal files with funny names, not as suffix rules. Thus, the rule:

.c.o: foo.h 
      $(CC) -c $(CFLAGS) $(CPPFLAGS) -o [email protected] $< 

tells how to make the file '.c.o' from the prerequisite file 'foo.h', and is not at all like the pattern rule:

%.o: %.c foo.h 
      $(CC) -c $(CFLAGS) $(CPPFLAGS) -o [email protected] $< 

which tells how to make '.o' files from '.c' files, and makes all '.o' files using this pattern rule also depend on 'foo.h'.

La solución es utilizar las reglas de patrón de nuevo cuño:

%.out: %.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected] 
%.o: %.cpp 
    g++ -c $< -o [email protected] 

(También tenga en cuenta que no es necesario definir un .cpp a .o regla; make tiene un valor predeterminado sensible.)

+0

Gracias por su respuesta. Uso la regla .cpp to .o para proporcionar 'CPPFLAGS' personalizados al compilador. No los mostré en el código de muestra porque estaba manteniendo las cosas simples. ¿Los valores predeterminados 'make' seguirán incluyendo los nombres de las variables" predeterminadas "(por ejemplo,' CFLAGS', 'CPPFLAGS',' LDFLAGS', etc.)? – misha

+1

Sí, pero 'CPPFLAGS' es para el preprocesador C. 'CXXFLAGS' es para indicadores de C++. –

Cuestiones relacionadas