Мы должны использовать Makefile, чтобы собрать все вместе для нашего проекта, но наш профессор никогда не показывал нам, как это сделать.
У меня есть только один файл a3driver.cpp
. Драйвер импортирует класс из местоположения "/user/cse232/Examples/example32.sequence.cpp"
.
Вот и все. Все остальное содержится в .cpp
.
Как бы я сделал простой Makefile для создания исполняемого файла с именем a3a.exe
?
Ответы:
Поскольку это для Unix, исполняемые файлы не имеют никаких расширений.
Стоит отметить, что
root-config
это утилита, которая обеспечивает правильные флаги компиляции и компоновки; и правильные библиотеки для создания приложений против root. Это просто деталь, связанная с первоначальной аудиторией этого документа.Сделай меня, детка
или ты никогда не забудешь первый раз, когда тебя сделали
Вводное обсуждение make и как написать простой make-файл
Что такое марка? И почему я должен заботиться?
Инструмент под названием Make является менеджером зависимостей сборки. То есть он должен знать, какие команды нужно выполнить и в каком порядке взять ваш программный проект из коллекции исходных файлов, объектных файлов, библиотек, заголовков и т. Д. И т. Д. - некоторые из которых могли измениться недавно --- и превращение их в правильную актуальную версию программы.
На самом деле, вы можете использовать Make и для других вещей, но я не буду об этом говорить.
Тривиальный Makefile
Предположим, что у вас есть каталог, содержащий:,
tool
tool.cc
tool.o
support.cc
support.hh
иsupport.o
который зависитroot
и должен быть скомпилирован в вызываемую программуtool
, и предположим, что вы взламывали исходные файлы (что означает, что существующийtool
сейчас устарел) и хотите скомпилируйте программу.Чтобы сделать это самостоятельно, вы могли бы
Проверьте, является ли один из них
support.cc
илиsupport.hh
новееsupport.o
, и, если это так, выполните команду вродеПроверьте, является ли один из них
support.hh
илиtool.cc
новееtool.o
, и если да, выполните командуПроверьте,
tool.o
является ли новее, чемtool
, и если так, выполните команду какУф! Что за хлопоты! Здесь есть что вспомнить и несколько шансов ошибиться. (Кстати, особенности представленных здесь командных строк зависят от нашей программной среды. Эти работают на моем компьютере.)
Конечно, вы можете просто запустить все три команды каждый раз. Это бы сработало, но оно плохо масштабируется для существенного программного обеспечения (например, DOGS, которое компилируется с нуля на моем MacBook более 15 минут).
Вместо этого вы можете написать файл под названием
makefile
так:и просто введите
make
в командной строке. Который выполнит три шага, показанных выше, автоматически.Здесь строки с отступом имеют форму «target: dependencies» и сообщают Make, что соответствующие команды (строки с отступом) должны выполняться, если какая-либо из зависимостей новее, чем target. То есть строки зависимости описывают логику того, что необходимо перестроить, чтобы учесть изменения в различных файлах. Если
support.cc
изменения, это означает, чтоsupport.o
должны быть восстановлены, ноtool.o
могут быть оставлены в покое. Когдаsupport.o
измененияtool
должны быть перестроены.Команды, связанные с каждой линией зависимостей, обозначаются вкладкой (см. Ниже), которая должна изменить цель (или, по крайней мере, коснуться ее, чтобы обновить время модификации).
Переменные, встроенные правила и другие полезности
На этом этапе наш make-файл просто запоминает работу, которая должна быть выполнена, но нам все еще приходилось разбираться и вводить все необходимые команды в полном объеме. Так не должно быть: Make - это мощный язык с переменными, функциями манипулирования текстом и целым рядом встроенных правил, которые могут упростить нам задачу.
Сделать переменные
Синтаксис для доступа к переменному гриму является
$(VAR)
.Синтаксис для назначения переменной Make:
VAR = A text value of some kind
(илиVAR := A different text value but ignore this for the moment
).Вы можете использовать переменные в правилах, таких как эта улучшенная версия нашего make-файла:
который немного более читабелен, но все же требует много печатать
Сделать функции
GNU make поддерживает множество функций для доступа к информации из файловой системы или других команд в системе. В этом случае мы заинтересованы в том,
$(shell ...)
что расширяет к выходу аргумента (ов), и$(subst opat,npat,text)
который заменяет все экземплярыopat
сnpat
в тексте.Воспользовавшись этим, мы получаем:
который легче набирать и гораздо более читаемый.
Заметь
Неявные и шаблонные правила
Как правило, мы ожидаем, что все исходные файлы C ++ должны обрабатываться одинаково, и Make предоставляет три способа заявить это:
Неявные правила встроены, и некоторые из них будут обсуждаться ниже. Шаблонные правила указываются в виде
Это означает, что объектные файлы генерируются из исходных файлов C с помощью показанной команды, где «автоматическая» переменная
$<
расширяется до имени первой зависимости.Встроенные правила
Make имеет целый набор встроенных правил, которые означают, что очень часто проект может быть скомпилирован очень простым make-файлом.
В GNU make встроено правило для исходных файлов на Си, которое показано выше. Точно так же мы создаем объектные файлы из исходных файлов C ++ с правилом вроде
$(CXX) -c $(CPPFLAGS) $(CFLAGS)
.Одиночные объектные файлы связаны с использованием
$(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
, но это не будет работать в нашем случае, потому что мы хотим связать несколько объектных файлов.Переменные, используемые встроенными правилами
Встроенные правила используют набор стандартных переменных, которые позволяют вам указывать информацию о локальной среде (например, где искать включаемые файлы ROOT) без переписывания всех правил. Наиболее вероятными для нас являются:
CC
- использовать компилятор CCXX
- использовать компилятор C ++LD
- компоновщик для использованияCFLAGS
- флаг компиляции для исходных файлов CCXXFLAGS
- флаги компиляции для исходных файлов C ++CPPFLAGS
- флаги для c-препроцессора (обычно включают пути к файлам и символы, определенные в командной строке), используемые C и C ++LDFLAGS
- флаги компоновщикаLDLIBS
- библиотеки для ссылкиОсновной Makefile
Используя преимущества встроенных правил, мы можем упростить наш make-файл для:
Мы также добавили несколько стандартных целей, которые выполняют специальные действия (например, очистка исходного каталога).
Обратите внимание, что когда make вызывается без аргумента, он использует первую цель, найденную в файле (в данном случае все), но вы также можете назвать цель, которую хотите получить, что и делает
make clean
удаление объектных файлов в этом случае.У нас все еще есть жестко запрограммированные зависимости.
Некоторые Таинственные Улучшения
Заметь
make
тоls -A
увидите файл с именем,.depend
который содержит вещи, которые выглядят как строки зависимостиДругое Чтение
Знайте ошибки и исторические заметки
Язык ввода для Make чувствителен к пробелам. В частности, строки действий, следующие за зависимостями, должны начинаться с вкладки . Но ряд пробелов может выглядеть одинаково (и действительно есть редакторы, которые будут молча преобразовывать вкладки в пробелы или наоборот), что приводит к тому, что файл Make выглядит правильно и все еще не работает. Это было определено как ошибка на ранней стадии, но ( история продолжается ) это не было исправлено, потому что уже было 10 пользователей.
(Это было скопировано с поста вики, который я написал для аспирантов по физике.)
источник
-pthread
Флаг, заставляющийgcc
определять необходимые макросы,-D_REENTRANT
не нужен.root-config
). Должна быть предложена более общая альтернатива с той же способностью, если таковая имеется, или ее следует просто исключить. Я не понизил голосование из-за перечисления и объяснения наиболее часто используемых макросов make.Я всегда думал, что это было легче изучить на подробном примере, так что вот как я думаю о make-файлах. Для каждого раздела у вас есть одна строка, которая не имеет отступа, и показывает название раздела, за которым следуют зависимости. Зависимости могут быть либо другими разделами (которые будут выполняться до текущего раздела), либо файлами (которые при обновлении приведут к повторному запуску текущего раздела при следующем запуске
make
).Вот быстрый пример (имейте в виду, что я использую 4 пробела, где я должен использовать вкладку, переполнение стека не позволяет мне использовать вкладки):
Когда вы
make
печатаете, он выберет первый раздел (a3driver). a3driver зависит от a3driver.o, поэтому он перейдет в этот раздел. a3driver.o зависит от a3driver.cpp, поэтому он будет работать, только если a3driver.cpp изменился с момента последнего запуска. Предполагая, что он был (или никогда не был запущен), он скомпилирует a3driver.cpp в файл .o, затем вернется к a3driver и скомпилирует окончательный исполняемый файл.Поскольку существует только один файл, он может быть сокращен до:
Причина, по которой я показал первый пример, заключается в том, что он показывает силу make-файлов. Если вам нужно скомпилировать другой файл, вы можете просто добавить другой раздел. Вот пример с secondFile.cpp (который загружается в заголовок с именем secondFile.h):
Таким образом, если вы измените что-либо в secondFile.cpp или secondFile.h и перекомпилируете, он будет перекомпилировать только secondFile.cpp (не a3driver.cpp). Или, альтернативно, если вы что-то измените в a3driver.cpp, он не будет перекомпилировать secondFile.cpp.
Дайте мне знать, если у вас есть какие-либо вопросы по этому поводу.
Также традиционно включать раздел с именем «all» и раздел с именем «clean». «all» обычно собирает все исполняемые файлы, а «clean» удаляет «артефакты сборки», такие как файлы .o и исполняемые файлы:
РЕДАКТИРОВАТЬ: я не заметил, что вы на Windows. Я думаю , что единственное различие изменяя
-o a3driver
к-o a3driver.exe
.источник
Почему всем нравится перечислять исходные файлы? Простая команда поиска может позаботиться об этом легко.
Вот пример простого C ++ Makefile. Просто поместите его в каталог, содержащий
.C
файлы, а затем введитеmake
...источник
У вас было два варианта.
Вариант 1: самый простой makefile = NO MAKEFILE.
Переименуйте «a3driver.cpp» в «a3a.cpp», а затем в командной строке напишите:
И это все. Если вы используете GNU Make, используйте «make», «gmake» или что-то еще.
Вариант 2: 2-строчный make-файл.
источник
nmake
.link
Командная строка также выглядит очень специфичной для конкретного компилятора, и должна в самом крайнем случае документа , в котором один.Ваш файл Make будет иметь одно или два правила зависимости в зависимости от того, будете ли вы компилировать и ссылаться одной командой или одной командой для компиляции и одной командой для ссылки.
Зависимости - это дерево правил, которые выглядят следующим образом (обратите внимание, что отступ должен быть TAB):
Там должна быть пустая строка после того, как команды для цели, и должен не быть пустой строкой перед командами. Первая цель в make-файле - это общая цель, а другие цели создаются, только если от них зависит первая цель.
Так что ваш make-файл будет выглядеть примерно так.
источник
Я предлагаю (обратите внимание, что отступ - это TAB):
или
Последнее предложение немного лучше, так как оно использует неявные правила GNU Make. Однако для работы исходный файл должен иметь то же имя, что и конечный исполняемый файл (то есть:
tool.c
иtool
).Обратите внимание, что нет необходимости объявлять источники. Промежуточные объектные файлы создаются с использованием неявного правила. Следовательно, эта
Makefile
работа для C и C ++ (а также для Fortran и т. Д.).Также обратите внимание, что по умолчанию Makefile используется
$(CC)
в качестве компоновщика.$(CC)
не работает для связывания объектных файлов C ++. Мы модифицируемLINK.o
только из-за этого. Если вы хотите скомпилировать код на C, вам не нужно форсироватьLINK.o
значение.Конечно, вы также можете добавить свои флаги компиляции с переменной
CFLAGS
и добавить свои библиотеки вLDLIBS
. Например:Примечание: если вам нужно использовать внешние библиотеки, я предлагаю использовать pkg-config для правильной установки
CFLAGS
иLDLIBS
:Внимательный читатель заметит, что это
Makefile
не восстанавливает должным образом, если один заголовок изменен. Добавьте эти строки, чтобы решить проблему:-MMD
позволяет создавать файлы .d, содержащие фрагменты Makefile о зависимостях заголовков. Вторая строка просто использует их.Конечно, хорошо написанный Makefile должен также включать
clean
иdistclean
правила:Обратите внимание,
$(RM)
это эквивалентrm -f
, но это хорошая практика, чтобы не звонитьrm
напрямую.all
Правило также ценится. Для того, чтобы работать, это должно быть первое правило вашего файла:Вы также можете добавить
install
правило:DESTDIR
по умолчанию пусто. Пользователь может установить его для установки вашей программы в альтернативной системе (обязательно для процесса кросс-компиляции). Сопровождающие пакета для многократного распространения могут также изменитьсяPREFIX
, чтобы установить ваш пакет в/usr
.Последнее слово: не помещайте исходные файлы в подкаталоги. Если вы действительно хотите это сделать, сохраните это
Makefile
в корневом каталоге и используйте полные пути для идентификации ваших файлов (т.е.subdir/file.o
).Подводя итог, ваш полный Makefile должен выглядеть так:
источник
make
что я знаю (GNU Make и BSD Make), не нуждается в пустых строках между правилами. Тем не менее, существует множествоmake
реализаций со своими собственными ошибками.Я использовал ответ Фридмада . Я изучил это некоторое время, и, похоже, это хороший способ начать. Это решение также имеет четко определенный метод добавления флагов компилятора. Я ответил снова, потому что я внес изменения, чтобы он работал в моей среде, Ubuntu и g ++. Иногда больше примеров - лучший учитель.
Makefiles кажутся очень сложными. Я использовал один, но он генерировал ошибку, связанную с отсутствием связи в библиотеках g ++. Эта конфигурация решила эту проблему.
источник