Как я могу улучшить этот Makefile? - PullRequest
1 голос
/ 13 марта 2009

Я не очень разбираюсь в создании Makefile, но я читал make make и добился определенного прогресса. Мой Makefile работает и делает то, что я хочу.

В моей ситуации обычно требуется от 1 до 3 разных программ, которые необходимо скомпилировать и отправить в мою ТА для маркировки и тому подобного через веб-форму. Структура каждого приложения - «prog.c», «prog_lib.h» и «prog_lib.c». В прошлом я создавал отдельные каталоги для каждой программы и создавал отдельные файлы Makefile для каждого каталога, чтобы построить программу, содержащуюся внутри. Затем я копирую каждую папку и отправляю их отдельно.

В последнее время ТП просили, чтобы все исходные файлы были в одном каталоге и один Makefile с различными целевыми объектами, которые будут создаваться, чтобы их приложения для разметки могли работать без вмешательства человека.

Мне было интересно, как кто-то более опытный улучшит этот Makefile и как обычно решается моя ситуация в целом? Я хотел бы сократить объем печати, необходимый для перехода к следующему заданию, и мне нужно обновить несколько мест.

Вот мой Makefile:

ASSIGNMENT = 3
TARNAME = Assignment$(ASSIGNMENT).tar.bz2

CC = gcc
CFLAGS = -O2 -Wall -ansi -pedantic -W # I like warnings
LDFLAGS = -lm
DEBUG = -g # to resolve symbols in GDB and valgrind

FREQ_OUT = frequency_table
FREQ_SOURCES = frequency_table.c frequency_table_lib.c
FREQ_OBJECTS = frequency_table.o frequency_table_lib.o

DECODE_OUT = decode
DECODE_SOURCES = decode.c decode_lib.c
DECODE_OBJECTS = decode.o decode_lib.o

SOURCES = $(FREQ_SOURCES) $(DECODE_SOURCES)
OBJECTS = $(FREQ_OBJECTS) $(DECODE_OBJECTS)
OUT = $(FREQ_OUT) $(DECODE_OUT)

.PHONY: info
info:
    @echo -e "make info\n" \
            "\tmake all \t\t\tMake all targets\n" \
            "\tmake frequency_table \t\tMakes frequency table\n" \
            "\tmake decode \t\t\tMakes decode\n" \
            "\tmake dist \t\t\tMakes tar archive of sources and Makefile\n" \
            "\tmake clean \t\t\tRemoves all the object files and executables\n" \
            "\tmake distclean \t\t\tPerforms clean and removes tar archive"

.PHONY: all
all:    $(OUT)

$(FREQ_OUT):    $(FREQ_OBJECTS)
    $(CC) $(CFLAGS) $(DEBUG) $(LDFLAGS) $(FREQ_OBJECTS) -o $@

$(DECODE_OUT):  $(DECODE_OBJECTS)
    $(CC) $(CFLAGS) $(DEBUG) $(LDFLAGS) $(DECODE_OBJECTS) -o $@

.o:
    $(CC) -c $(CFLAGS) -o $@ $<

.PHONY: dist
dist: $(SOURCES)
    @echo "Creating tar archive. See $(TARNAME)"
    tar cvjf $(TARNAME) $(SOURCES) $(wildcard *_lib.h) Makefile

.PHONY: clean
clean:
    rm -f $(OUT) $(OBJECTS)

.PHONY: distclean
distclean: clean
    rm -f $(TARNAME)

Ответы [ 4 ]

3 голосов
/ 13 марта 2009

Сделайте цель 'all' первой, если вы не уверены, что ваши пользователи должны будут что-то набирать после 'make', чтобы получить проект для сборки. Цель 'info' хороша, но условна.

(у меня есть один make-файл, в котором цель по умолчанию - не все - в каталоге с исходным кодом для 100+ команд. Я не хочу, чтобы «make all» был по умолчанию; я ожидаю собрать только один или два что я хочу построить. Есть «все». Но это очень необычно. Обычно по умолчанию должно быть «все».)

Кроме того, ни $ (FREQ_OUT), ни $ (DECODE_OUT) не являются целью PHONY; они настоящие программы, не так ли? Цели 'all', 'info', 'dist', 'clean', 'realclean' и т. Д. - это фальшивка. Но программы, которые вы создаете, не являются.

3 голосов
/ 13 марта 2009

Вам действительно не нужны строки $(CC) $(CFLAGS) $(DEBUG) $(LDFLAGS) $(FREQ_OBJECTS) -o $@. make уже знает, как создавать двоичные файлы.

Если ваши имена файлов постоянны для разных двоичных файлов (binary.c и binary_lib.c), вы также можете создать общее правило для этого:

FOO := $(shell ls *_lib.c)
BIN = $(FOO:%_lib.c=%)

$(BIN) : % : %.o %_lib.o

РЕДАКТИРОВАТЬ: Вот как это работает:

  1. FOO - список всех файлов, заканчивающихся _lib.c
  2. BIN - это тот же список, с удаленными суффиксами "_lib.c", поэтому это список ваших двоичных файлов
  3. Последняя строка - ваше правило make. Правило гласит, что каждый foo в $ (BIN) зависит от foo.o и foo_lib.o
2 голосов
/ 13 марта 2009

По моему опыту, вам не нужна цель .o, это неявно.

Кроме того, неявная версия обычно включает значение $(CPPFLAGS), куда вы должны поместить любые -I path или -D macro параметры, которые могут вам потребоваться .

Я бы также включил $(DEBUG) в $(CFLAGS) вместо того, чтобы явно указывать его в любой из целей сборки.

1 голос
/ 13 марта 2009

Пример:

# CC, CFLAGS, etc. go here

# Object variables go here
MYPROG_OBJECTS = main.o someother.o

# all, info, etc. targets go here

# first actual target:
myprog: $(MYPROG_OBJECTS)
    <Do the linking stuff>

# This will take care of the objects, sources are placed in src directory:
%.o: src/%.c
   <The usual compilation commands>

# Automatic dependency magic:
%.d: src/%.c
   $(CC) -MM -o$@ $<

-include (MYPROG_OBJECTS:%.o=%.d)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...