Установите мой make-файл для компиляции C просто с помощью "make" - PullRequest
0 голосов
/ 10 января 2019

Я делаю курс «Изучите трудный путь» Зеда Шоу, и на уроке 2 я обнаружил, что в видео и книге автор использует make ex1 для компиляции своего C, а мне нужно запустить gcc -Wall -g ex1.c -o ex1. Вот мой Makefile. Кажется, первая часть - это то, что должно заставить команду make работать на компиляции, но команда «make» не компилирует ее.

CFLAGs=-Wall -g

clean:
    rm -f ex1.exe

all:
    gcc -Wall -g ex1.c -o ex1.exe




Ответы [ 4 ]

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

У вашего Makefile нет информации о зависимостях, включенной в форму Правила . Правила - это строки, начинающиеся в левом столбце (в столбце 0) и имеющие разделитель : между целями (объекты, которые будут построены) и реквизитами (объекты, предоставленные правилу)

Make выполняет цепочку правил, поэтому цель не может быть построена раньше, чем ее предпосылки, поэтому хорошей отправной точкой будет:

ex1.exe: ex1.o

это означает, что ex1.exe (первая цель в вашем Makefile) зависит от ex1.o (скомпилированный объект) .... но как. Вы добавляете команды чуть ниже, но вставляете перед командной строкой символ табуляции:

[tab char]gcc -Wall -g ex1.o -o ex1.exe

Прежде всего, посмотрите, как команда принимает ex1.o в качестве ввода для gcc и генерирует (с помощью опции -o) файл ex1.exe.

Смысл всего этого в том, что вам всегда не хватает ex1.exe, или он оказывается модифицированным (начиная с даты его изменения в файле) до обязательного условия (ex1.o), в котором будет использоваться эта команда.

Теперь, как мы скомпилируем объектный файл? (в вашем Makefile это делается напрямую)

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

эта строка нуждается в дополнительных пояснениях (хотя, если вы ее не используете, она автоматически предоставляется программой make). Она использует переменные подстановки: $(CC) расширяется до компилятора C по умолчанию (обычно cc, но Вы можете изменить это). $(CFLAGS) - это переменная, которую вы определили поверх Makefile, и она расширяется до параметров компилятора, обычно используемых для компиляции программ. $@ расширяется целевым файлом (в данном случае файлом ex1.o), а $< расширяется до левой предпосылки правой части правила. Это правило, которое очень распространено для компиляции файлов C в объектные файлы, автоматически генерируется для вас make, и больше можно создать в make advanced used (я не буду вводить здесь, из-за количества места нужно) просто сказать, что это можно записать так:

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

, что означает: любой файл с расширением .o может быть создан из файла с тем же именем, но с расширением .c с помощью следующей командной строки ниже. Это автоматически приводит к зависимости каждого .o файла от файла с тем же именем, но с расширением .c, и предварительно загружается в make.

Итак, ваш самый простой Makefile может быть:

CFLAGS=-Wall -g
src=ex1.c
ex1.exe: $(src)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(src)

Как вы видите, я использовал переменную src для описания исходных файлов C, используемых для компиляции моей программы. Зависимость будет выдана только , когда вы изменили какие-либо или предварительные условия (сейчас есть только одна, на ex1.c, но может быть и больше), и так как я делаю компиляцию и компоновку в одной и той же компиляции, я необходимо передать флаги компиляции и флаги ссылки (не используется, вы можете удалить ссылку на $(LDFLAGS) здесь) Действительно, вы могли бы написать:

ex1.exe: ex1.c
     cc -g -Wall -o ex1.exe ex1.c
clean:
     rm -f ex1.exe

Итак, действие по умолчанию - создать ex1.exe, который зависит от ex1.c (поэтому только при изменении ex1.c перекомпилируется ex1.exe. Чтобы скомпилировать его, просто выполните:

make ex1.exe

или

make

, который будет использовать первое правило по умолчанию Makefile.

clean является поддельной целью (нет файла с именем clean для генерации), поэтому при использовании

make clean

связанная с ним команда всегда выполняется. make удаляет целевые файлы (так как удаляет все созданные файлы), поэтому при следующем запуске make он заново создаст все файлы, выполнив необходимые компиляции.

ОБЩЕЕ ИСПОЛЬЗОВАНИЕ

Для простых программ, скажем, нескольких исходных .c файлов и некоторых .h файлов, с отдельной компиляцией каждого (опция -c при компиляции) и связыванием, я обычно использую этот подход (определение объектных файлов требуется для каждой целевой программы в отдельной переменной)

# makefile for programs foo and bar.

targets = foo bar
TOCLEAN = $(TARGETS)  # this variable stores what should be erased on clean target.  Here we store the programs to erase.

foo_objs = a.o b.o c.o
TOCLEAN += $(foo_objs)  # here, we add the objects of foo

foo: $(foo_objs)
    $(CC) $(LDFLAGS) -o $@ $(foo_objs)

bar_objs = d.o e.o f.o
bar_libs = -lm -lintl -lX
TOCLEAN += $(bar_objs)  # here we add the objects of bar

bar: $(bar_objs)
    $(CC) $(LDFLAGS) -o $@ $(bar_objs) $(bar_libs)

clean:
    rm -f $(TOCLEAN)

a.o b.o c.o: a.h b.h c.h globals.h
b.o c.o d.o e.o f.o: my_defs.h

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

0 голосов
/ 10 января 2019
CFLAGS = -Wall -g

all: ex1

clean:
    $(RM) ex1

.PHONY: all clean

Исправлено мое определение CFLAGS в начале и добавлено .PHONY в конце для all и clean, поэтому make знает, что файлы для них не создаются.

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

Для очень простого make-файла я делаю это:

qsorttest: qsorttest.c 
     gcc -Wall -g qsorttest.c -o qsorttest -lm

clean:
     rm -f qsorttest

"qsorttest.c" - это имя моего исходного файла, а созданный мной исполняемый файл - "qsorttest". Убедитесь, что строки под «имя программы: исходный файл» и «чистый:» вставлены и не перемещаются с помощью клавиши пробела. Некоторое время я билась головой о стену, пока не вышла из этого поиска.

Я сохраняю это как «Makefile» в том же каталоге, что и другие мои файлы для программы, и make работает каждый раз. Я просто изменяю исходные файлы и имена программ по мере необходимости и добавляю дополнительные параметры для связи библиотек, если они мне нужны.

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

Целью по умолчанию является первая цель, поэтому поменяйте их порядок так, чтобы all было значением по умолчанию.

Подробнее в документации о целях :

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