Объектные файлы (.o
) создаются командами компиляции, например,
gcc -c -o foo.o foo.c ...
g++ -c -o baz.o baz.cpp ...
-c
означает compile; не связывайте . При создании
объектные файлы компилятором. Любые параметры связи, которые вы добавляете в компиляцию
команда, например
gcc -c -o foo.o foo.c -L/my/libs -lbar -lgum
просто игнорируются.
Параметры связывания активируются командой связывания, которая создает программу или общую / динамическую.
библиотека, связывая вместе объектные файлы и библиотеки, например
gcc -o prog foo.o baz.o -L/my/libs -lbar -lgum
gcc -shared -o libfoobaz.so foo.o baz.o -L/my/libs -lbar -lgum
Итак:
Для зависимостей кода, таких как glib, gdbus, gio, я должен связать их один раз при создании объектов .o в каждом из проектов компонентов.
Нет, нет, и вы не можете.
Позже
С учетом проблемы makefile вполне понятно, как устранить
$(LIBS)
справка из рецепта компиляции и то, что вам мешало. Makefile определяет:
LIBS = `pkg-config --cflags --libs glib-2.0`
что является ошибкой. $(LIBS)
расширяется до стандартного выхода
Команда:
pkg-config --cflags --libs glib-2.0
, представляющая собой единственную строку, содержащую оба обязательных параметра
для компиляции исходного кода, который #include
-s glib-2.0
API (за счет --cflags
)
а также опции связывания , необходимые для связывания программы или общей библиотеки
против libglib-2.0
(из-за --libs
). В моей системе это:
$ pkg-config --cflags --libs glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0
из которых только параметры компиляции будут выводиться с помощью:
$ pkg-config --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
и только параметры связывания будут выводиться с помощью:
$ pkg-config --libs glib-2.0
-lglib-2.0
Но поскольку оба набора параметров доступны только вместе через расширение
из $(LIBS)
вы не можете успешно скомпилировать без передачи
опция связывания -lglib-2.0
, которая является избыточной и игнорируется.
Поскольку ваш make-инструмент, очевидно, является GNU Make, make-файл (кстати, неплохой!) Лучше записать как:
Makefile
CC := gcc
CFLAGS := -g3 $(shell pkg-config --cflags glib-2.0)
BINDIR := bin
SRCS := objex.c
OUTOBJ := $(addprefix $(BINDIR)/, $(SRCS:.c=.o))
.PHONY: all clean
all: $(OUTOBJ)
$(BINDIR)/%.o : %.c
$(CC) -c $< $(CFLAGS) -o $@
$(OUTOBJ): | $(BINDIR)
$(BINDIR):
mkdir -p $(BINDIR)
clean:
$(RM) $(OUTOBJ)
, который обходится без LIBS
и работает с нуля, как:
$ make
mkdir -p bin
gcc -c objex.c -g3 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -o bin/objex.o
Обратите внимание на несколько других улучшений: -
Использование немедленного расширения (:=
), где это применимо, вместо ненужного
рекурсивное расширение (=
). См. 6.2 Два варианта переменных
Использование прямой подстановки оболочки make - $(shell command)
- в предпочтении к расширению backtick в
рецепт исполнения. См. 8.13 Функция оболочки .
all
, например clean
является фальшивой целью
и вам нужно сказать make, что это так, чтобы избежать ловушки, в которой что-то создает файл с именем all
в
директория проекта, которую вы не заметили, и таинственным образом перестает обнаруживать какую-либо работу, которую он должен выполнить.
С вашим clean
рецептом:
clean:
rm bin/*
make clean
потерпит неудачу, если когда-либо будет запущен, кроме как после успешной сборки Рецепт
заменяется на $(RM) $(OUTOBJ)
, используя предопределенный макрос удаления GNU Make, который
не подведет.
Наконец, помните, что ваш рецепт рецепта, где бы он ни находился, * требует библиотечные опции для glib-2.0
,
который вы должны указать в его make-файле:
LIBS := $(shell pkg-config --libs glib-2.0) # ...and any more library options required
для использования в рецепте, подобном:
prog: $(OBJS)
$(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
[1] Строго говоря, параметры препроцессора должны появляться в определении CPPFLAGS
(Флаги препроцессора C), не путать с CXXFLAGS
(опции компиляции C ++).
[2] Строго говоря, параметры определения, отличные от библиотек, должны появляться в определении
LDFLAGS
.