2013-09-29 2 views
2

У меня есть hello-world.c, что я хотел бы скомпилировать до hello-world двоичный код. Но hello-world.c зависит от нескольких функций, определенных в ../helpers/a.c и ../helpers/b.c, и каждый из этих помощников включает ../helpers/a.h и ../helpers/b.h соответственно.Makefile для одной цели с несколькими зависимостями .c и .h

Мой текущий Makefile выглядит

CC  = @gcc 
CFLAGS = -g -Wall -Wextra -Werror 
CFLAGS += 

LDLIBS = 
LDLIBS += 

OBJS = ../helpers/a.o ../helpers/b.o 

SOURCES = hello-world.c 
DESTS = hello-world 

new: clean all 

clean: 
    @rm -rf *.o */*.o $(DESTS) 

all: $(OBJS) $(DESTS) 

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

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

, но он не работает, возвращая make: *** No rule to make target `../helpers/a.o', needed by `all'. Stop.

Я понимаю, что Makefile не кажется, чтобы увидеть правила для %.o, но я не вижу Зачем.

Edit: Makefile отладки:

[email protected]:/media/sf_procmon/procmon$ make --debug=b 
GNU Make 3.81 
Copyright (C) 2006 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. 

This program built for x86_64-pc-linux-gnu 
Reading makefiles... 
Updating goal targets.... 
File `new' does not exist. 
    File `clean' does not exist. 
    Must remake target `clean'. 
    Successfully remade target file `clean'. 
    File `all' does not exist. 
    File `../helpers/a.o' does not exist. 
    Must remake target `../helpers/a.o'. 
make: *** No rule to make target `../helpers/a.o', needed by `all'. Stop. 
+0

Использование шаблонов правил для файлов в других папках работает для меня. Я запустил этот make-файл, и a.o и b.o были созданы, как ожидалось. Вы уверены, что используете 'make all' в правильном каталоге? –

+0

Хм, это странно. Я запускаю make inhe right dir, но я получаю эту ошибку. – alexandernst

+0

Почему бы не помещать ваши вспомогательные функции в библиотеку? Тогда вам не придется собирать их каждый раз. –

ответ

0

Это гораздо легче получить работу, если вы поставите Makefile в родительском каталоге. Тогда вы можете написать что-то вроде этого:

CC  = gcc 
CFLAGS = -g -Wall -Wextra -Werror 
CPPFLAGS = -Ihelpers 

DESTS  = hello-world/hello-world 
OBJS  = helpers/a.o helpers/b.o hello-world/hello-world.o 

# Do not make 'all' depend directly on object files. 
all: $(DESTS) 

# Clean rules should always be prefixed with '-' to avoid 
# errors when files do not exist. Do not use 'rm -r' when 
# there shouldn't be directories to delete; do not delete 
# wildcards when you can use explicit lists instead. 
# Never use '@'. 
clean: 
     -rm -f $(OBJS) $(DESTS) 

# An explicit linkage rule is needed for each entry in DESTS. 
hello-world/hello-world: hello-world/hello-world.o \ 
         helpers/a.o helpers/b.o 
     $(CC) $(CFLAGS) $(LDFLAGS) -o [email protected] $^ $(LIBS) 

# The main function of these dependency lists is to prevent 
# Make from deleting object files after each build. We also 
# take the opportunity to specify header dependencies. 
# We rely on the built-in %.o:%.c rule for commands. 
hello-world/hello-world.o: hello-world/hello-world.c \ 
          helpers/a.h helpers/b.h 
helpers/a.o: helpers/a.c helpers/a.h 
helpers/b.o: helpers/b.c helpers/b.h 

# This tells Make that 'all' and 'clean' are not files to be created. 
.PHONY: all clean 

Для дальнейшего изложения этой техники, см водораздела бумаги «Recursive Make Considered Harmful» и связанное с ним примечание реализации.

+0

Я не могу поместить его в родительский каталог, потому что структура dir представляет несколько разных проектов без какого-либо отношения (за исключением того, что они делят папку помощников). – alexandernst

+0

1) Не имеет значения, что структура каталогов представляет собой несколько разных проектов, единственным подключением которых является папка помощников; они должны * все еще * все использовать один и тот же make-файл в родительском каталоге. Вы обнаружите, что это меньше проблем в целом, чем любая другая форма организации. 2) 'CPPFLAGS' означает флаги C * preprocessor *. Переменная флага, специфичная для C++, - 'CXXFLAGS'. Встроенное правило для компиляции '.c' файлов использует' CFLAGS' и 'CPPFLAGS'; правило для файлов '.cc' /' .cpp' использует 'CXXFLAGS' и' CPPFLAGS'. – zwol

+0

BTW, «примечания по реализации» по ссылке в моем ответе показывают технику хранения информации для каждого каталога в каждой директории Makefiles, все еще получая преимущества нерекурсивного make. Это намного сложнее, чем выше, но я бы не стал заниматься небольшими проектами. – zwol

0

мне удалось исправить мой Makefile:

CC  = gcc 
CFLAGS = -g -Wall -Wextra -Werror 
CFLAGS += 

LDLIBS = 
LDLIBS += 

OBJS = ../helpers/a.o ../helpers/b.o hello-world.o 

SOURCES = hello-world.c 
DESTS = hello-world 

new: clean all 

clean: 
    @rm -rf *.o */*.o ../helpers/*.o $(DESTS) 

all: $(DESTS) 

hello-world: $(OBJS) 
    $(CC) $(CFLAGS) $(LDFLAGS) -o [email protected] $^ $(LIBS) 

Одной из проблем было то, что плохо чистое правило, которое я написал стерла a.c и b.c и Makefile действовал из-за этого.

Смежные вопросы