2009-02-20 5 views
1

У меня есть 4 файла '.cpp' и 1 заголовочные файлы:простая задача Makefile (с простой зависимостью)

Tools.cpp 
Code1.cpp 
Code2.cpp 
Code3.cpp 

and Tools.hh 

Теперь все Code1.cpp, Code2.cpp, Code3.cpp использовать функции, хранящиеся в Tools.cpp.

В настоящее время, что я делаю, чтобы собрать все из них использует этот простой скрипт:

#!/bin/bash 
echo "compiling Code1.cpp"; 
g++ Code1.cpp Tools.cpp -o Code1 

echo "compiling Code2.cpp"; 
g++ Code2.cpp Tools.cpp -o Code2 

echo "compiling Code3.cpp"; 
g++ Code3.cpp Tools.cpp -o Code3 

Это все работает отлично.

Теперь я хочу сделать это с помощью стандартного файла makefile. Но почему это оленья кожа»работа:

CXX = g++ 

TOOLSRC = Tools.cpp Code1.cpp Code2.cpp \ 
Code3.cpp  

TOOLSINC = Tools.hh  

all: Code1 Code2 Code3 

Code1: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

Code2: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

Code3: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

ошибка я получил это:

ld: warning in makefile, file is not of required architecture 
ld: duplicate symbol neighbors(std::vector<int, std::allocator<int> >&, int, int)in /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccQCrGHe.o and /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccreq9YU.o 

collect2: ld returned 1 exit status 
make: *** [FindNeighbours] Error 1 

Как я могу исправить ошибки?

ответ

4

В этих целях:

Code1: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

В результате команды будет:

g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1 

Это явно не то, что вы хотите.g++ пытается скомпилировать как файл заголовка, так и make-файл и не знает, что делать с make-файлом. Вы также заявляете зависимости от всех трех основных блоков для каждой единицы. Поэтому, если Code3.cpp изменится, Code1 потребует перекомпиляции. Это также нежелательно.

попробовать что-то вроде этого, вместо:

CXX = g++ 

all: Code1 Code2 Code3 

%.o: %.cpp 
    $(CXX) $(CXXFLAGS) -c -o [email protected] $^ 

Code1: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 

Code2: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 

Code3: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 
2

Hm. Обычно вы указываете зависимости от объектных файлов с расширениями «.o». Возможно, что Make запущен, так как он имеет встроенные правила для файлов разных типов.

Ошибка в том, что вы пытаетесь связать make-файл с программой, передав $^компилятору.

+0

Привет, что альтернатива $^тогда? – neversaint

+0

Вам не нужно ничего, make должен иметь возможность выводить команду build самостоятельно. Или сделайте это как greyfade, не завися от make-файла. – unwind

1

С правой стороны правила вы должны поставить только файлы, которые являются полезными.

Code1: Code1.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 
Code1: Code2.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 
Code3: Code3.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 

Хотя это решает вашу проблему, вы обязательно должны прочитать ответ Грейфэйда о том, как делать вещи «Правильный путь».

+0

Это сделает процесс компилятора tools.cpp более одного раза - что не нужно. См. Greyfade ниже для приятного объяснения и Rberteig для еще более короткого makefile. – nimrodm

4

Короче говоря, $^ не то, что вы хотите здесь. Он оценивает «имена всех предварительных условий с пробелами между ними». В задаче Makefile, который вызывает все три целей использовать практически идентичные командные строки, что каждый выглядеть

g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1 

Из сообщения об ошибке цитируемого г ++ решил, что Makefile должен быть передан линкером, как если бы это было объект. Это не так. Без makefile в строке вы все равно будете компилировать и связывать все четыре исходных файла и, скорее всего, оставите компоновщик, чтобы решить, какую из четырех функций main() использовать.

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

all: Code1 Code2 Code3 
Code1: Code1.o Tools.o 
Code2: Code2.o Tools.o 
Code3: Code3.o Tools.o 

Code1.o Code2.o Code3.o Tools.o: Tools.hh 

Если вам необходимо установить некоторые опции компилятора можно добавить определение для CXXFLAGS, традиционно в верхней части файла.

+0

и LDFLAGS для управления процессом связывания. У меня никогда не было нового GNU make, имеющего неявные правила для связывания. Спасибо что подметил это. – nimrodm

+0

Gnu make, похоже, является объединением каждой функции, найденной в любой версии сделанного когда-либо построенного. Руководство огромно, но стоит прочитать хотя бы один раз ... Я все еще узнаю об этом после более чем 20 лет использования различных версий make на широком спектре систем. – RBerteig

0

Я не эксперт Makefiles, но это, как я обычно делаю это, и это хорошо работает.

COMPILER = g++ 
CXXFLAGS = 
EXECUTABLE = code 

all: code 

code: Code1.o Code2.o Code3.o Tools.o 
    ${COMPILER} ${CXXFLAGS} -o ${EXECUTABLE} Code1.o Code2.o Code3.o Tools.o 

Code1.o: Code1.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code1.cpp 

Code2.o: Code2.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code2.cpp 

Code3.o: Code3.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code3.cpp 

Tools.o: Tools.cpp Tools.hh 
    ${COMPILER} ${CXXFLAGS} -c Tools.cpp 

clean: 
    rm *.o 
    rm ${EXECUTABLE} 
Смежные вопросы