Простая проблема Makefile (с простой зависимостью) - PullRequest
1 голос
/ 20 февраля 2009

У меня есть 4 файла '.cpp' и 1 заголовочный файл:

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

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

Теперь я хочу сделать это, используя стандартный make-файл. Но почему это не работает:

CXX = g++

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

TOOLSINC = Tools.hh      

all: Code1 Code2 Code3

Code1: $(TOOLSRC) $(TOOLSINC) makefile
    $(CXX) $^ -o $@  

Code2: $(TOOLSRC) $(TOOLSINC) makefile
    $(CXX) $^ -o $@  

Code3: $(TOOLSRC) $(TOOLSINC) makefile
    $(CXX) $^ -o $@  

Я получил следующую ошибку:

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

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

Ответы [ 5 ]

4 голосов
/ 20 февраля 2009

В этих целях:

Code1: $(TOOLSRC) $(TOOLSINC) makefile
    $(CXX) $^ -o $@

Результирующая команда будет:

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

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

Попробуйте что-то вроде этого:

CXX = g++

all: Code1 Code2 Code3

%.o: %.cpp
    $(CXX) $(CXXFLAGS) -c -o $@ $^

Code1: Code1.o Tools.o
    $(CXX) -o $@ $^

Code2: Code1.o Tools.o
    $(CXX) -o $@ $^

Code3: Code1.o Tools.o
    $(CXX) -o $@ $^
4 голосов
/ 20 февраля 2009

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

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

Из приведенного сообщения об ошибке g ++ решил, что make-файл должен передаваться компоновщику, как если бы это был объект. Это не так. Без make-файла на линии вы все равно будете компилировать и связывать все четыре ваших исходных файла и, вполне вероятно, оставите компоновщик, чтобы решить, какую из четырех 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, традиционно в верхней части файла.

2 голосов
/ 20 февраля 2009

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

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

1 голос
/ 20 февраля 2009

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

Code1: Code1.cpp Tools.cpp
    $(CXX) $^ -o $@
Code1: Code2.cpp Tools.cpp
    $(CXX) $^ -o $@
Code3: Code3.cpp Tools.cpp
    $(CXX) $^ -o $@

Хотя это решит вашу проблему, вам непременно следует прочитать ответ Грейфэйда о том, как делать все правильно.

0 голосов
/ 27 февраля 2009

Я не специалист по make-файлам, но я обычно так делаю, и это хорошо работает.

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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...