#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)
недостаточно, если объектный файл отображается в подкаталоге.