Получить используемые заголовочные и исходные имена файлов, анализируя Makefile - PullRequest
0 голосов
/ 04 января 2019

Я хотел бы извлечь все имена файлов *.cc и *.h из файла Makefile, который также содержит неиспользуемые цели.Пример Makefile здесь: https://gist.github.com/berceanu/7554a9c4371b807e425259c7e99b5de9

Я попытался запустить make -Bnd и посмотреть на удаленные файлы, но я не знаю, пропускает ли это что-нибудь.

make -Bnd | grep "Pruning file" | sort | uniq

Ожидаемый результат: список всех файлов *.h и *.cc, используемых make run в указанном выше Makefile.

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Ваш подход к извлечению этой информации из Makefile, вероятно, неправильный.make не знает, какие заголовочные файлы используются на самом деле .make знает только, какие заголовочные файлы вы явно указали make в зависимостях, и это не очень надежно.Информация в Makefile может быть неверной по двум причинам.Он может содержать неиспользуемые цели (как вы заметили) или неиспользуемые заголовочные файлы.Он может пропустить заголовочные файлы, которые на самом деле включены, но не упомянуты в Makefile.Еще хуже то, что если фактическое включение заголовочных файлов зависит от макросов, например #ifdef XYZ_FEATURE #include "additionalHeaderFile.h" #endif.

Существует как минимум три способа, которыми вы можете сгенерировать желаемый список, то есть список .cc и .h файлов, фактически используемых во время компиляции:

  • (вслепую доверяет Makefile) make -n --print-data-base
  • (следует за реальными файлами сборки, но также немного сложен для анализа) strace -f make
  • (полагается на функцию, присутствующую в GCC, clang, armcc и, возможно, других компиляторах для поколения Makefile, очень надежная) Добавить CPPFLAGS:=-MMD к Makefile, запустить make clean,затем make, затем используйте cat *.d, чтобы получить список всех файлов .cc и .h, использованных для сборки run.Вы даже можете сделать это, не изменяя Makefile: make clean; make CPPFLAGS:=-MMD && cat *.d | sed -e 's/\\//g' -e 's/:/ /g' -e 's/ \+/\n/g' | sort -u.

Кроме того, у Makefile, которым вы поделились в гисте, есть большое количество проблем.

  • По умолчанию цель должна быть названа all 1 2 3 .Это не должно быть имя двоичного файла, это будет просто цель .PHONY.
  • Переменная со списком объектных файлов должна иметь имя OBJS или OBJECTS, а не OBJ.Имя OBJ вводит в заблуждение, потому что оно в единственном числе.
  • Вместо rm используйте $(RM), что подразумевает -f и, следовательно, не будет проблем в случае, если файл не существует.(Как побочный эффект, Makefile станет более переносимым, так как не все платформы используют rm для удаления файлов.)
  • clean не является файлом и, следовательно, должно быть .PHONYtarget.
  • clean должен использовать :: вместо : для своего рецепта, чтобы в будущем, когда Makefile был больше и разделен на несколько файлов, каждый файл мог иметь свой собственный clean target без проблем.
  • Переменные, не зависящие от правил, следует раскрывать в момент определения, а не в том случае, когда на них ссылаются, и, таким образом, они определяются с использованием := вместо =.
  • Вместо C++ используйте CXX, который уже определен.
  • Вместо помещения параметров в C++ / CXX, используйте LDFLAGS, потому что вы связываете.
  • У вас должен быть исходный файл с тем же базовым именем, что и двоичный файл.Затем вы можете использовать встроенное правило для связывания.
  • Явные зависимости в Makefile являются трудной задачей для обслуживания.Каждый раз, когда оператор #include для заголовочного файла проекта добавляется, удаляется или изменяется, Makefile необходимо будет обновлять, и это легко забыть, и это очень неприятно, особенно когда оператор #include находится взаголовочный файл.Даже с должной осмотрительностью, это также невидимый конфликт слияния.Вместо явных зависимостей в Makefile, вы должны использовать CPPFLAGS+=-MMD в начале вашего Makefile и добавить -include $(wildcard *.d) в конце вашего Makefile, и добавить *.d в список файлов дляудалить в clean.Затем вы можете удалить все правила зависимостей из Makefile (за исключением правила для связи).
  • Называть двоичный файл run не очень хорошая идея.Пользователи, которые видят, что у вашей Makefile есть цель run, ожидают, что она будет запускать реальной программы, а не связывать ее.
  • Лучше, чтобы каждый объект упоминался насобственная линия.Это значительно уменьшает конфликты слияния в проектах, когда несколько разработчиков одновременно изменяют список объектов.

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

LDFLAGS:=-Wno-deprecated -lm
CPPFLAGS+=-MMD
BINARY:=program

OBJECTS:= \
    $(BINARY).o \
    binomh.o \
    # More objects here

.PHONY: all
all: $(BINARY)

$(BINARY): $(OBJECTS)

.PHONY: clean
clean::
    $(RM) \
        $(BINARY) \
        *.[adios] \

-include $(wildcard *.d)

То, что Makefile будет делать то же самое, что и ваш Makefile, но оно почти не требует обслуживания .Нет необходимости обновлять зависимости, так как они автоматически берутся из файлов зависимостей, сгенерированных препроцессором C.*.[adios] также удалит файлы, созданные в случае, если вы добавили -save-temps к любому из CFLAGS, CXXFLAGS или CPPFLAGS.

Этот тип Makefile, как известно, работает дляGCC, clang, AOCC (AMD Optimizing C Compiler) и armcc.Это, вероятно, работает и для ряда других компиляторов и препроцессоров, особенно когда они основаны или пытаются быть совместимыми с GCC или clang / LLVM.

Кстати, если вам интересно знать, чтоэто работает для вас с высокой степенью достоверности, помимо опыта: я взял ваш Makefile и добавил к нему следующие строки, чтобы воспроизвести структуру вашего исходного кода.Заголовочные файлы будут просто пустыми файлами.Исходные файлы C ++ будут списками #include операторов, взятых из зависимостей в вашем Makefile.

%.cc:
    grep '^$*\.o.*:' $(MAKEFILE_LIST) | sed -e 's/.*://' -e 's/.*$*\.cc//' -e 's/ \([^ ]\+\)/#include "\1"\n/g' >$@

%.h:
    touch $@
0 голосов
/ 04 января 2019

Вместо -Bnd я бы предложил использовать --dry-run --print-data-base для выгрузки полной базы данных целей, их зависимостей, правил, переменных и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...