Компиляция нескольких файлов c не работает с определенными именами файлов

#c #linux #makefile #g

Вопрос:

Я пытаюсь скомпилировать несколько файлов .cpp, используя файл Makefile с помощью make. У меня есть файл .cpp, содержащий основную функцию, в другом файле .cpp-базовый класс (при любых сомнениях я помещу здесь весь код, который я использую). Пример имен, используемых для его компиляции или для того, чтобы он не компилировался:

-это работает, если их назвать «prova.cpp»(содержит основную функцию) и «pa.cpp»(содержит класс) (ниже команд, выполняемых файлом Makefile)

 gioele@GioPC-U:~/Dev/Cpp/Exercises/666prova$ make
g   -g -Wall -c src/prova.cpp -o obj/prova.o
g   -g -Wall -c src/pa.cpp -o obj/pa.o
g   -g -Wall obj/prova.o -o bin/provaBin
 

-это не работает, если их называть «ciao.cpp»(содержит основную функцию) и «pa.cpp»(содержит класс)

 gioele@GioPC-U:~/Dev/Cpp/Exercises/666prova$ make
g   -g -Wall -c src/pa.cpp -o obj/pa.o
g   -g -Wall -c src/ciao.cpp -o obj/ciao.o
g   -g -Wall obj/pa.o -o bin/provaBin
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text 0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:15: bin/provaBin] Errore 1
 

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

Файл с основным методом:

 #include <iostream>

int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}
 

Файл класса:

 class Class {
public:
    int x;
    int y;
};
 

Файл Makefile (все еще учусь работать с файлами Makefile, вероятно, проблема здесь, приветствуются любые советы по улучшению файла Makefile такого рода, или если я использую что-то неправильно):

 CC=g  
CFLAGS=-g -Wall
OBJ=obj
SRC=src
BINDIR=bin
BIN=$(BINDIR)/provaBin

SRCS=$(wildcard $(SRC)/*.cpp)
OBJS=$(patsubst $(SRC)/%.cpp, $(OBJ)/%.o, $(SRCS))

all: $(BIN)

$(BIN): $(OBJS)
    $(CC) $(CFLAGS)

lt; -o $@

$(OBJ)/%.o: $(SRC)/%.cpp
$(CC) $(CFLAGS) -c


lt; -o $@

clean:
$(RM) $(BINDIR)/* $(OBJ)/*

Заранее спасибо.

Комментарии:

1. вы не ссылаетесь ciao.o на свой исполняемый файл?

Ответ №1:

Вы можете исправить это, изменив одного персонажа.

В этом правиле:

 $(BIN): $(OBJS)
    $(CC) $(CFLAGS)

lt; -o $@

список обязательных $(OBJS) условий расширяется до списка объектных файлов, таких как prova.o pa.o или pa.o ciao.o . Вы хотите, чтобы Make включил этот список в команду связывания, например:

 g   -g -Wall prova.o pa.o -o bin/provaBin
 

Но автоматическая переменная $< расширяется только до первого элемента в списке необходимых компонентов. Если первый элемент представляет собой объектный файл, который не содержит main() функции, например pa.o , компоновщик будет жаловаться main() на ее отсутствие. (Если это объектный файл , содержащий main() , например, prova.o , то вы не получите эту ошибку, но у вас все еще могут возникнуть проблемы.)

Решение состоит в использовании автоматической переменной $^ , которая расширяется до полного списка предварительных условий:

 $(BIN): $(OBJS)
    $(CC) $(CFLAGS) $^ -o $@