Makefile не дает ожидаемых результатов компиляции

#c #linux #gcc #makefile #g

Вопрос:

Я совсем новичок в Make. Я пытаюсь написать Makefile для создания приложения Linux C / C среднего размера, как показано ниже.

Создание простого Makefile путем размещения всех исходных файлов в одном месте и явного перечисления исходных файлов работает нормально для меня, но я бы хотел, чтобы он был более общим.

У меня есть все мои исходные файлы (C и C ) в src папке в разных подкаталогах. У меня есть файлы заголовков внутри inc inc/common папки and, а затем библиотеки внутри lib папки.

Makefile выполняется на том же уровне :

 SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin

CXX := /bin/arm-linux-gnueabi-g  

EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)   
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))

CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c  11 -Wall
LDFLAGS  := -Llib
LDLIBS   := 

.PHONY: all clean

all: $(EXE)

$(EXE): $(OBJ) | $(BIN_DIR)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c

lt; -o $@

$(BIN_DIR) $(OBJ_DIR):
mkdir -p $@

clean:
@$(RM) -rv $(BIN_DIR) $(OBJ_DIR)

-include $(OBJ:.o=.d)

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

 compilation terminated.
/bin/arm-linux-gnueabi-g   -Iinc -Iinc/common -MMD -MP -std=c  11 -Wall -c -o obj/main.d.o
cc -Llib  obj/main.d.o   -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
 

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

1. рассмотрите возможность использования github.com/cppfw/prorab это значительно упростит вашу makefile работу и сделает ее универсальной, как вы хотите

Ответ №1:

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

Это неправильно:

 $(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
 

Правило шаблона — это шаблон, который сообщает make «если вы хотите создать цель, соответствующую этому шаблону, вы можете создать ее из предварительных условий, соответствующих этому шаблону».

Здесь вы перечисляете ВСЕ свои исходные файлы в качестве предварительного условия для КАЖДОГО объектного файла. Предположим SRC , установлено значение foo.c bar.c biz.c baz.c , затем оно расширяется до:

 obj/%.o : foo.c bar.c biz.c baz.c | obj
        $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c

lt; -o $@

Вы говорите make, что каждая отдельная .o цель зависит от ВСЕХ исходных файлов, а не только от одного для этого объектного файла. Кроме того, автоматическая переменная $< всегда расширяется до первого предварительного условия, которое здесь всегда будет foo.c . Итак, вы компилируете foo.c четыре раза, создавая каждый из объектных файлов.

Самое первое важное правило при отладке make-файлов — внимательно просматривать выходные данные (командные строки), которые выполняют печать. Если они неверны, значит, ваш makefile неверен. Если вы это сделаете, вы увидите, что все строки компиляции компилируются из одного и того же источника, например:

 g   -c foo.c -o obj/foo.o
g   -c foo.c -o obj/bar.o
g   -c foo.c -o obj/biz.o
g   -c foo.c -o obj/baz.o
 

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

Тебе это нужно:

 $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
        @mkdir -p $(@D)
        $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c

lt; -o $@

который сообщает make, как создать объектный файл из одного исходного файла.

Вам также необходимо создать фактический выходной каталог, в который будет помещен объектный файл. Простого создания $(OBJ_DIR) недостаточно, если объектный файл отображается в подкаталоге.