Простой make-файл с цепочечными зависимостями. «Входной файл компоновщика не используется, так как компоновка не выполнена» и g ++ -c

0

Я только начал использовать make файлы и столкнулся с проблемой. (Проект C++)
Я пытаюсь создать цепочку зависимостей:

main.cpp зависит от класса a. А класс a зависит от класса b.

Основная идея состоит в том, чтобы перекомпилировать класс a, используя allready скомпилированный класс b, тогда как класс a не имеет функции main(). (Когда класс a изменен)

Вот мой makefile:

Makefile

all: main.o

main.o: main.cpp classa.o
        g++ main.cpp classa.o -o main.o

classa.o: classa.h classa.cpp classb.o
        g++ -c classa.cpp classb.o -o classa.o

classb.o: classb.h classb.cpp
        g++ -c classb.cpp -o classb.o

И код:

main.cpp

#include "classa.h"

int main() {
    ClassA a;
    return 0;
}

classa.h

#ifndef CLASSA_H
#define CLASSA_H

#include "classb.h"

class ClassA {
private:
    ClassB b;
public:
    ClassA();
};

#endif // CLASSA_H

classa.cpp

#include "classa.h"

ClassA::ClassA() {
}

classb.h

#ifndef CLASSB_H
#define CLASSB_H

class ClassB {
public:
    ClassB();
};

#endif // CLASSB_H

classb.cpp

#include "classb.h"

ClassB::ClassB() {
}

Проблема:

Когда я использую make -f makefile, я получаю следующую ошибку:

g++ -c classb.cpp -o classb.o
g++ -c classa.cpp classb.o -o classa.o
g++: warning: classb.o: linker input file unused because linking not done
g++ main.cpp classa.o -o main.o
classa.o: In function 'ClassA::ClassA()':
classa.cpp:(.text+0x18): undefined reference to 'ClassB::ClassB()'
collect2: error: ld returned 1 exit status
makefile:4: recipe for target 'main.o' failed
make: *** [main.o] Error 1

Я считаю, что он начинается с повторного использования classb.o с параметром -c.
Мне -c является магическое "использование, когда я компилирую код без параметра main()".

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

С уважением, шоколад

Теги:
makefile
g++
compilation

1 ответ

1
Лучший ответ

Ваш make файл должен выглядеть следующим образом:

all: main

main: main.cpp classa.o classb.o
        g++ main.cpp classa.o classb.o -o main

classa.o: classa.h classa.cpp
        g++ -c classa.cpp -o classa.o

classb.o: classb.h classb.cpp
        g++ -c classb.cpp -o classb.o

Вы .o файлы .o из файлов .cpp а затем связываете файлы .o с окончательным выходом (также созданным из файла .cpp).

Вам необходимо указать все соответствующие объектные файлы при связывании и не нужно -c их при компиляции (что происходит, когда вы используете флаг -c который указывает gcc пропустить шаг связывания).

Ключ здесь заключается в том, что classa.o не зависит от classb.o или classb.cpp (он, вероятно, зависит от classb.h хотя в этом случае вы можете добавить это к требованиям). Полностью связанный двоичный файл зависит от обоих из них, и они тогда зависят друг от друга по мере необходимости.

Тем не менее, вы можете значительно упростить вышеупомянутый make файл, не указав свои собственные правила и просто используя встроенные правила. Следующий make файл должен делать то, что вы хотите.

all: main

main: classa.o classb.o

classa.o: classa.h
classb.o: classb.h

Если вам понадобятся пользовательские флаги компилятора/компоновщика, вы можете использовать переменные по умолчанию, чтобы использовать их в соответствующих строках. См. 10.3 Переменные, используемые неявными правилами, и 10.2 Каталог встроенных правил для переменных и какие правила их используют.

  • 0
    Большое спасибо за разъяснение моего заблуждения! Оно работает. :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню