Синтаксис Makefile: Статическая библиотека lib $ (library) .a ($ objects) - PullRequest
1 голос
/ 16 декабря 2010

Я обновляю некоторые Makefiles, чтобы перейти от Make 3.81 к 3.82. Во многих местах автор использовал нечто подобное для создания статических библиотек:

all: lib$(library).a($objects)

Кажется, что каждый файл .o строится по очереди и вставляется в .a, используя ar:

g++ -O2 <snip> -o some_obj.o some_cpp.cpp
ar rv libsome_lib.a some_obj.o
etc...

Эта новая версия make, тем не менее, задыхается от:

*** No rule to make target 'libsome_lib.a()', needed by 'all'

Могу ли я заменить этот ярлык тем способом, которым я привык к этому:

lib$(library).a: $(objects)
     ar -rs lib$(library).a $objects

Спасибо.

EDIT

Похоже, мне нужно лучшее образование в Makefile. Вот большая выдержка из оригинального Makefile:

CXXFLAGS += -O2 -g -Wall -Wunused-parameter \
    `pkg-config --cflags gthread-2.0 glibmm-2.4 gtkmm-2.4`

libs +=  `pkg-config --libs gthread-2.0 glibmm-2.4` -lc

%.d: %.cpp
    $(SHELL) -ec '$(CXX) -M $(CPPFLAGS) $(CXXFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'
%.d: %.c
    $(SHELL) -ec '$(CXX) -M $(CPPFLAGS) $(CXXFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'

from_sources = $(patsubst %.c,$(2),$(filter %.c, $(1)))  $(patsubst %.cpp,$(2),$(filter %.cpp, $(1)))

sources = $(shell cat sources.inc)
objects = $(call from_sources,$(sources),%.o)
depends = $(call from_sources,$(sources),%.d)

library = some_lib

.PHONY: all clean fresh

all: lib$(library).a($(objects))

clean:
    <SNIP>

if neq($(MAKECMDGOALS),clean)
    include $(depends)
endif

Когда это работает под 3.81, я получаю все созданные зависимости .d, затем make начинает g ++ с помощью файлов obj. В 3.82 я получаю файлы .d, но не .o, и make завершается неудачно с "*** Нет правил для создания ..."

Ответы [ 3 ]

4 голосов
/ 27 марта 2014

Это синтаксис "члена архива", поддерживаемый в gnu make.Это слишком близко к инструментам на мой вкус, но это так.Первоначальная ошибка может быть вызвана тем, что $ (objects) является пустым.Но я действительно не уверен.Вот некоторая документация:

http://www.gnu.org/software/make/manual/make.html#Archive-Members

11.1 Элементы архива в качестве целей

Отдельный элемент файла архива можно использовать в качестве цели или предпосылки в make,Вы указываете члена с именем member в архивном файловом архиве следующим образом:

 archive(member)

Эта конструкция доступна только в целях и предварительных условиях, но не в рецептах!Большинство программ, которые вы можете использовать в рецептах, не поддерживают этот синтаксис и не могут работать непосредственно с участниками архива.Это могут делать только программы ar и другие, специально предназначенные для работы с архивами.Следовательно, действительные рецепты для обновления целевого элемента архива, вероятно, должны использовать ar.Например, это правило гласит: создать члена hack.o в архиве foolib, скопировав файл hack.o:

 foolib(hack.o) : hack.o
         ar cr foolib hack.o

Фактически, почти все цели-члены архива обновляются именно таким образом, инеявное правило, чтобы сделать это для вас.Обратите внимание: флаг 'c' для ar необходим, если файл архива еще не существует.

3 голосов
/ 16 декабря 2010

Ваш путь выглядит хорошо, но в старом make-файле должно быть что-то еще, если старый способ работал вообще.

О, и просто для хорошей формы я бы предложил это:

lib$(library).a: $(objects)
     ar -rs $@ $^

EDIT
Не расстраивайся из-за того, что не понимаешь. у него довольно кривая обучения.

Здесь все еще не достаточно, чтобы продолжить, но если sources.inc не слишком велик, вы можете попробовать следующее в 3.81 и 3.82 и искать различия:

experiment:
    @echo sources: $(sources)
    @echo objects: $(objects)
    @echo depends: $(depends)

До сих пор есть свидетельства того, что objects пусто в 3.82, но если файлы .d перестраиваются под 3.82, это говорит о том, что depends не пуст, что очень странно.

1 голос
/ 16 декабря 2010

Возможно, но у вас нет явного правила для преобразования чего-то вроде xyz.cpp в xyz.o, которое вам может понадобиться для ваших источников, прежде чем пытаться внедрить их объекты в библиотеку. может быть подходящим неявным правилом для этого, поэтому проверьте сначала.

Первый вопрос, который я задам: что случилось с $objects, из-за которого вы попытались нацелиться на libsome_lib.a() (т. Е. В круглых скобках ничего не было)?

Если честно, я стараюсь по возможности избегать этих охватывающих правил, предпочитая явные операторы зависимостей (если, конечно, не существует lot зависимостей). Да, я знаю, что это делает make-файлы больше и помечает меня как минимум частичку луддита, но я предпочитаю, чтобы вещи работали над вещами, которые работают умно.

Cut'n'paste - один из самых сильных инструментов в моем наборе инструментов: -)

...