Понимание синтаксиса Makefile: распространенные проблемы и решения (включая «отсутствующий оператор» и «точка входа не найдена»)

Ponimanie Sintaksisa Makefile Rasprostranennye Problemy I Resenia Vklucaa Otsutstvuusij Operator I Tocka Vhoda Ne Najdena



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

Понимание основного синтаксиса Makefile

Чтобы начать создание make-файла, мы объясним основные свойства make-файла на примере кода make-файла. Чтобы получить исполняемый файл, необходимо включить в содержимое make-файла следующие синтаксические свойства:







Переменная s: базовые объекты, хранящие данные, необходимые для использования в make-файле. Эти переменные используются для указания компилятора, флагов, исходных файлов, объектных файлов и целевых файлов. В следующем образце make-файла всего пять переменных: CXX (для установки компилятора C++), CXXFLAGSc (флаги компилятора), TARGET (для установки имени целевого исполняемого файла), SRCS (для установки файла исходного кода). , OBJS (для хранения объектных файлов, созданных с помощью файла исходного кода).



Цели: Ожидаемый результат, который нужно построить из исходного кода. Это может быть целевой файл или любое символическое имя: «all» — это цель по умолчанию, которая должна быть создана с помощью переменной «TARGET», «$TARGET» зависит от переменных «OBJS», а «чистая» цель удаляет цель и объектные файлы из рабочего каталога.



Правила и команды сборки: Набор основных инструкций, которые необходимо выполнить для создания цели из исходного файла или зависимостей. Например, правило «%.o: %.cpp» показывает, что файл с расширением «cpp» используется для создания объектного файла с расширением «o», хотя оба файла содержат одно и то же имя. С другой стороны, команда сборки $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) используется для связывания объектного файла и нового целевого файла. Таким же образом команда сборки $(CXX) $(CXXFLAGS) -c $< -o $@ компилирует исходный файл в объектный файл.





Зависимости: Зависимости всегда присутствуют, когда вы хотите создать make-файл. Например, цель «все» зависит от переменной «TARGET», а цель «TARGET» зависит от переменной «OBJS». При этом переменная «OBJS» зависит от исходного файла через переменную «SRCS».

Комментарии: Понятные человеку инструкции обычно используются для объяснения назначения строки кода в случае, если вы используете файл спустя долгое время. В следующем make-файле мы используем комментарии, начинающиеся со знака «#», для пояснения каждой строки.



СХХ = г++
CXXFLAGS = -стандартный =С++ одиннадцать -Стена
ЦЕЛЬ = Новый
SRCS = main.cpp
ОБЖС = $ ( SRCS:.cpp=.o )
все: $ ( ЦЕЛЬ )
$ ( ЦЕЛЬ ) : $ ( ОБЖС )
$ ( СХХ ) $ ( CXXFLAGS ) $ ( ЦЕЛЬ ) $ ( ОБЖС )
% .О: % .cpp
$ ( СХХ ) $ ( CXXFLAGS ) $ < $ @
чистый:
РМ $ ( ЦЕЛЬ ) $ ( ОБЖС )

Распространенные проблемы и решения

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

1: Не использовать переменные

Использование переменных в make-файле является обязательным, поскольку оно необходимо для установки компиляторов, целевых файлов, исходных файлов и т. д. Наиболее распространенная проблема, с которой можно столкнуться, — это отсутствие использования какой-либо переменной в make-файле. Поэтому обязательно используйте необходимые переменные, такие как CXX, CXXFLAGSc (флаги компилятора), TARGET, SRCS и OBJS в предыдущем примере make-файла.

2. Проблема с отсутствующим разделителем

При написании make-файла необходимо очень внимательно учитывать правила отступов, поскольку использование пробелов вместо табуляции приведет к проблеме «отсутствующего разделителя» во время выполнения инструкции make. Например, мы добавляем пробел в начале правила в строке 13 и удаляем табуляцию.

$ ( ЦЕЛЬ ) : $ ( ОБЖС )
$ ( СХХ ) $ ( CXXFLAGS ) $ ( ЦЕЛЬ ) $ ( ОБЖС )

При выполнении запроса make мы получаем ошибку «отсутствует разделитель» в строке 13, и файл перестает работать. Чтобы избежать этой проблемы, обязательно используйте «tab» вместо пробелов.

делать

Чтобы избежать этой проблемы, обязательно используйте «табуляцию» вместо пробелов, как показано на следующем рисунке:

$ ( ЦЕЛЬ ) : $ ( ОБЖС )
$ ( СХХ ) $ ( CXXFLAGS ) $ ( ЦЕЛЬ ) $ ( ОБЖС )

3. Проблема «Точка входа не найдена»

Эта ошибка чаще всего возникает из-за исходного файла, а не из-за make-файла, например, когда вы пропускаете использование функции «main()» в файле исходного кода. Например, мы заменяем определение функции main() простым объявлением пользовательской функции.

#include
международное шоу ( ) {
чар v;
станд::cout << 'Введите значение: ' ;
станд::cin >> в;
станд::cout << в << станд::эндл;
возвращаться 0 ;
}

При выполнении инструкции make в командной строке Windows мы сталкиваемся с «неопределённой ссылкой на WinMain». Это связано с тем, что компилятор не находит точки входа для начала выполнения файла C++. Чтобы решить эту проблему, замените «show» на «main».

4. Использование неправильных расширений

Иногда пользователь может непреднамеренно использовать неправильные расширения исходного файла, который будет использоваться в make-файле. Использование неправильного расширения приведет к ошибкам во время выполнения, т. е. к отсутствию правила для создания цели. Мы создаем make-файл для сборки исполняемого и объектного файла для файла C++. В седьмой строке мы указываем исходный файл с расширением «c».

СХХ := г++
CXXФЛАГИ := -стандартный =С++ одиннадцать -Стена
ЦЕЛЬ = новый
SRCS = main.c
ОБЖС = $ ( SRCS:.cpp=.o )
Все: $ ( ЦЕЛЬ )
$ ( ЦЕЛЬ ) : $ ( ОБЖС )

Выполнение инструкции make приводит нас к ошибке «Нет правила для создания целевого объекта main.c». Чтобы избежать этой проблемы, обязательно используйте правильное расширение исходного файла.

делать

5: Отсутствующие зависимости

При написании make-файла вам следует включить все зависимости исходного файла, чтобы получить желаемый результат. Например, наш файл кода C++ использует файл «myheader.h» в качестве зависимости. Поэтому мы упоминаем его в файле кода C++ следующим образом:

#include
#include «myheader.h»
международное шоу ( ) {
чар v;
станд::cout << 'Введите значение: ' ;
станд::cin >> в;
станд::cout << в << станд::эндл;
возвращаться 0 ;
}

В make-файле мы намеренно игнорируем использование файла «myheader.h» в правиле сборки, записанном в строке 9.

% .О: % .cpp
$ ( СХХ ) $ ( CXXFLAGS ) $ < $ @

Теперь при использовании инструкции make мы сталкиваемся с ошибкой «Ничего не нужно делать для всех».

делать

% .О: % .cpp мойheader.h
$ ( СХХ ) $ ( CXXFLAGS ) $ < $ @

Чтобы избежать указанной проблемы и успешно запустить исходный код, укажите имя файла «myheader.h» в девятой строке make-файла, как показано ниже:

Заключение

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