2013-07-27 5 views
0

У меня есть Makefile, который работает до сих пор. Хотя, по мере того как он начал расти, перекомпиляция всех источников каждый раз начиналась слишком долго. Вот отрывок из рабочей версии:Makefile - файл зависимостей в папке «Нет такого файла или каталога»

CC=$(CROSS_COMPILE)g++ 
CFLAGS=-Wall -I./include -pg -O2 
VPATH=./src:./include 

all: dotgazer.cpp dotgazer/Dot.cpp 
    $(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv` 

Есть намного больше зависимостей, но эти два достаточно, чтобы показать, что проблема есть. Я пытаюсь переместить этап компиляции каждого файла cpp в отдельную цель. Когда дело доходит до файла верхнего уровня (dotgazer.cpp), это не проблема, и общее правило %.o: %.cpp отлично работает. Но я не могу заставить вторую зависимость работать. Вот как это выглядит сейчас:

CC=$(CROSS_COMPILE)g++ 
CFLAGS=-Wall -I./include -pg -O2 
VPATH=./src:./include 

all: dotgazer.o dotgazer/Dot.o 
    $(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv` 

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

dotgazer/Dot.o: dotgazer/Dot.cpp 
    $(CC) -c $(CFLAGS) $^ -o [email protected] 

Я пробовал различные вариации Dot.o правил, но ни один из них не похоже на работу. Ошибка, которую я получаю с приведенной выше:

Fatal error: can't create dotgazer/Dot.o: No such file or directory 

Как это сделать? Я бы предпочел иметь файлы .o в тех же папках, что и их источники. Кроме того, я был бы благодарен за общие правила (например, %.o: %.cpp), так как есть много исходных файлов, и я не хочу, чтобы Makefile слишком раздувался. Спасибо!

+0

Я мог бы быть быть немым, но не '% .o:% .cpp' и' dotgazer/Dot.o: dotgazer/правила Dot.cpp' удвоение? Как, не последняя ли цель, уже обработанная первой? –

+0

@AdamGoodwin Я думал, что он будет работать таким образом (требуется только правило '% .o:% .cpp'). Но получается - нет. Поэтому я добавил второе правило, особенно для второй зависимости, и он все еще не работает. Только с правилом '% .o:% .cpp', сообщение одно и то же:' невозможно создать dotgazer/Dot.o: нет такого файла или каталога' – Wojtek

+0

Хм, я просто попробовал ваш make-файл, и он отлично работал для меня. Он работал даже с целью «% .o» и без цели «dotgazer/Dot.o». Вы не ошиблись с именем файла или каталогом? Или вы делаете что-то вроде запуска make-файла откуда-то, кроме своего собственного каталога? –

ответ

1

Я думаю, что ваш Makefile немного специфичен и, следовательно, подвержен ошибкам. Я предлагаю посмотреть на следующий пример, который более общий, чем ваш.

В моем примере используется катализ неявных правил make. Для cpp-файлов уже существует общее неявное правило. Так почему бы не использовать его !?

Справочное руководство описывает его следующим образом:

Компиляция C++ программ

n.o производится автоматически из n.cc, n.cpp или n.C с рецептом формы $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c.

Так что если у вас есть %.o файлов в качестве предпосылок, как в правиле dotgazer.out: $(OBJS)make применяется выше неявного правила для всех этих файлов автоматически. Предположим, что вы установили действительные значения для CXX, CPPFLAGS и/или CXXFLAGS.

Кроме того, вам не нужно добавлять свои источники вручную к переменной. В большинстве случаев для создания исполняемого файла необходимы все источники в дереве каталогов вашего проекта. Если это не так, вы должны подумать о создании соответствующего дерева, которое отражает это.

С find несет ответственность за назначение источников CPPFILES, нам также не нужно устанавливать VPATH. Из-за нашего использования find и patsubst у нас есть только одно явное имя файла в нашем Makefile. Это делает работу над реальным проектом с большим количеством различных источников намного более плавным.

Конечно, вам не нужны правила all и clean. Я просто добавил их для удобства.

CXX=$(CROSS_COMPILE)g++ 
CPPFLAGS=-I./include 
CXXFLAGS=-Wall -pg -O2 
LDLIBS=`pkg-config --libs opencv` 

CPPFILES=$(shell find . -name "*.cpp") 
OBJS=$(patsubst %.cpp, %.o, $(CPPFILES)) 

all: dotgazer.out 
    @echo $(CPPFILES) 
    @echo $(OBJS) 

dotgazer.out: $(OBJS) 
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS) 

clean: 
    rm -f $(OBJS) 
+0

Удивительный ответ, спасибо! В нем есть все, что мне нужно, все файлы, скомпилированные отдельно, '.o' файлы в соответствующих папках. Однако есть одна проблема: функции OpenCV не распознаются, несмотря на настройки LDLIBS. Вот результат: http://pastebin.com/zV9btgqN Правило 'dotgazer.out' должно выглядеть так:' $ (CXX) $^-o $ @ $ (LDLIBS) '. Но все же, это отличный ответ! – Wojtek

+0

Вы правы, я должен изменить '$ (CXX) $ (LDLIBS) $^-o $ @' на '$ (CXX) $ (LDLIBS) -o $ @ $ ^'. 'g ++ --help' sais, что входные файлы должны появиться после опций. С наилучшими пожеланиями – user1146332

+0

Это не проблема. '-o' может прийти в любое время. Проблема в том, что библиотеки _must_ приходят последними (и порядок, в котором перечислены библиотеки, также может быть важен). Кроме того, 'CPPFLAGS' предназначены для флагов препроцессора C (' -I'/'-D'); Флаги компилятора, такие как '-Wall -pg -O2', принадлежат' CXXFLAGS' (для C++). Чтобы связать, используйте что-то вроде '$ (CXX) $ (CXXFLAGS) $ (LDFLAGS) -o $ @ $^$ (LDLIBS)' – MadScientist

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