Дата и время публикации:
Использование в простых проектах
1.Что такое GNU Make?
Утилита GNU Make является средством, позволяющим управлять генерацией исполняемых и иных файлов программы из исходных текстов (англ.source code).
Она, трактует как собирать одну и оболее программ с помощью правил, перечисленных в файле Makefile. Поэтому в директории проекта должен быть находится собственноручно написанный этот файл, что несомненно является затруднительным в больших проектах, но упрощает жизнь в простых, таких как uncurses .
Сборка проекта uncurses (версии 0.2), пропущенного через сито GNU Make, проиллюстрированна на рисунке 1.1
Рисунок 1.1
На котором изображены файлы на входе и выходе утилиты GNU Make и цели Makefile, которые позволяют генерировать в конечном итоге исполняемые файлы w.select и m.echo, а так же файл дистрибьюции uncurses-0.2.tar.gz и его контрольную сумму.
2. Использование Makefile
В листинге 2.1 приведен Makefile проекта uncurses.
Листинг 2.1
001 002 CC := $(if $(CC),$(CC),/usr/bin/gcc) 003 RM := $(if $(CC),$(CC),/bin/rm) 004 005 CFLAGS=-g -Werror 006 007 DEPS = ucurses.h ucurses_modes.h ukeys.h 008 009 MECHO_OBJ = mecho.o 010 WSELECT_OBJ = wtypeselect.o 011 012 %.o: %.c $(DEPS) 013 $(CC) -c -o $@ $< $(CFLAGS) 014 015 all: m.echo w.select 016 017 .PHONY: clean dist m.echo w.select 018 019 m.echo: $(MECHO_OBJ) 020 $(CC) -o $@ $(MECHO_OBJ) $(CFLAGS) -lncurses 021 022 w.select: $(WSELECT_OBJ) 023 $(CC) -o $@ $(WSELECT_OBJ) $(CFLAGS) -lncurses 024 025 clean: 026 rm *.o m.echo w.select 027 028 ## Name of package 029 PACKAGE_NAME = uncurses 030 ## Define to the version of this package. */ 031 PACKAGE_VERSION = 0.2 032 TAR := $(if $(TAR),$(TAR),/bin/tar czvf ) 033 DISTDIR = $(PACKAGE_NAME)-$(PACKAGE_VERSION) 034 DISTFILES = CHANGELOG Makefile $(DEPS) mecho.c wtypeselect.c 035 REMOVE_DISTDIR = \ 036 if test -d "$(DISTDIR)"; then \ 037 find "$(DISTDIR)" -type d ! -perm -200 -exec chmod u+w {} ';' \ 038 && rm -rf "$(DISTDIR)" \ 039 || { sleep 5 && rm -rf "$(DISTDIR)"; }; \ 040 fi 041 COPIED_FILES = `for FILE in $$DISTFILES; do cp $$ $(DISTDIR); done` 042 043 dist: $(DISTFILES) 044 $(REMOVE_DISTDIR) 045 test -d "$(DISTDIR)" || mkdir "$(DISTDIR)" 046 for file in $(DISTFILES); do \ 047 echo -n "Copy " $$file ;\ 048 cp -fpR $$file $(DISTDIR) || exit 1;\ 049 echo " Ok"; \ 050 done 051 $(TAR) $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz $(DISTDIR) >/dev/null 2>&1; 052 if test -f "$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz"; then \ 053 sha1sum $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz < $(PACKAGE_NAME)-054 $(PACKAGE_VERSION).tar.gz.sha1; \ 055 echo "$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz created!"; \ 056 rm -rf $(DISTDIR) ; \ 057 fi 058
В строке 1,2 и 32 определяем переменные, в т.ч. определенные по умолчанию, такие как $(CC),$(RM). Переменая $(TAR) к такой относится, но не исключая того, что в будущем может ей стать, применяем условное выражение $(if) в формате, показанном в листинге 2.2
Листинг 2.2
TEST := $(if $(TEST),$(TEST),$(нечто другое))
В котором проверяется переменная $(TEST) на предмет присвоения ей значения – в результате чего make повторно переназначит $(TEST) или $(нечто другое), если установлено, что её значение отсутсвует.
В строках 5 и 7 определяем флаги компилятору GCC(1) и зависимости в виде заголовочных файлов, показанные ранее на рисунке 1.1
В строке 12 и 13 опредяляется общее правило сборки для каждого объектного файла (все файлы с расширением .o) компилируется из файла исходного кода (все файлы с расширением .с, имеющие зависимость от заголовочных файлов, перечисленных ранее в переменной $(DEPS), строке 7 листинга 2.1
В строке 19,20 и 22,23 определены правила для сборки целей m.echo и w.select, которые являются финальной стадией компоновки ранее собранных объектных файлов в соответсвующие исполняемые бинарные модули, описываемые $@, и их линковку с библиотекой ncurses.
В строке 17, в .PHONY перечисляем цели, которые желательно сделать абстрактными для того, чтобы не был нарушен последовательный порядок их вызыва для цели all, которая определена в строке 15 листинга 2.1
В строках 28,...,56 демонстрируется возможность использования SHELL для создания файла дистрибутива uncurses-0.2.tar.gz, показанный на рисунке 1.1
3.1 GNU Make
3.2 GNU Make:Conditional Syntax
3.3 Makefile set if variable is empty
3.3 GNU Make:Variables Used by Implicit Rules