Ссылка C++ undefined в Makefile

Я создал свой Makefile для простой программы, но он постоянно возвращает неопределенную ссылку для функций класса:

g++ -c src/main.cpp -o lib/main.o
g++ -c src/functions.cpp -o lib/functions.o
g++ -c src/Circular.cpp -o lib/Circular.o
g++ lib/main.o -o bin/app.exe
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: lib/main.o:main.cpp:(.text+0x20): undefined reference to `Circular::Circular()'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [app.exe] Error 1

Вот мой Makefile:

app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o -o bin/app.exe

lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o

lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o

lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o

Вот небольшой фрагмент main.cpp:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>


#include "../include/Circular.h"
#include "../include/functions.h"

using namespace std;

int main(int argc, const char * argv[]) {

     Circular item;
     return 0;
 }

Circular.h:

#include "node.h"


class Circular
{
    public:
        Circular();
        
        node *start;
        node *last;
        int counter;
}

Circular.cpp:

#include "../include/Circular.h"
#include <iostream>

using namespace std;


Circular::Circular()
{
    start = NULL;
    last = NULL;            
}

и node.h:

struct node
{
    int data;
    struct node *next;
    struct node *prev;
};

Я знаю, что проблема связана с компоновщиком и Makefile, но, хотя я пробовал разные возможные решения, почему-то это не работает. Поэтому, может быть, кто-то увидит мою ошибку. Спасибо!

2 ответа

Решение

Мне удалось создать Makefile из этого источника.

Makefile выглядит так:

CXX = g++
CXXFLAGS = -std=c++17 -Wall
LXXFLAGS = -std=c++17
OBJECTS = main.o Circular.o functions.o
TARGET = main

$(TARGET): $(OBJECTS)
    $(CXX) $(LXXFLAG) $(OBJECTS) -o $(TARGET)
main.o: main.cpp Circular.cpp Circular.h functions.cpp functions.h
    $(CXX) $(CXXFLAGS) -c main.cpp
Circular.o: Circular.cpp 
    $(CXX) $(CXXFLAGS) -c Circular.cpp
functions.o: functions.cpp 
    $(CXX) $(CXXFLAGS) -c functions.cpp
clean:
    rm -f $(TARGET) $(OBJECTS)

А также добавил cout вам Круговой конструктор, чтобы проверить выполнение, как показано ниже:

#include "Circular.h"
#include <iostream>

using namespace std;


Circular::Circular()
{
    start = NULL;
    last = NULL;   
    cout << "Yes!" << endl;     
}

Вот результат: Выходные данные
Не забудьте поставить точку с запятой для вашего класса Circular в вашемCircular.h.
ПРИМЕЧАНИЕ. Если вы не можете использовать make в cmd, используйтеchoco install make.

В Makefile должен быть структурирован для построения зависимостей, а затем окончательная сборка в .exe. Каждый путь должен быть указан именно так, а не приблизительно:

app.exe: lib/main.o lib/Circular.o lib/functions.o 
  g++ lib/main.o lib/Circular.o lib/functions.o -o app.exe

lib/main.o: src/main.cpp
  g++ -c src/main.cpp -o lib/main.o

lib/functions.o: src/functions.cpp
  g++ -c src/functions.cpp -o lib/functions.o

lib/Circular.o: src/Circular.cpp
  g++ -c src/Circular.cpp -o lib/Circular.o

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

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

Другие вопросы по тегам