Когда мне нужно использовать/иметь make-файл?

Я пытаюсь научиться кодировать на Raspberry PI. Я исхожу из кодирования с использованием Windows и VS Code. Сейчас я использую Linux Mint 19.1 и ssh для доступа к Raspbian 4.14.

Проблема в том, что после долгой битвы с загрузкой библиотеки, которую я пытаюсь использовать, после установки компилятора, создания файла и поиска правильной команды для запуска и включения путей я получаю undefined reference to ошибки.

Я пытаюсь скомпилировать простейший пример кода из https://github.com/hzeller/rpi-rgb-led-matrix потому что я начал с этого проекта. У меня нет другого кода или примера.

Вот команды, которые я написал в командной строке:

sudo apt-get install g++
mkdir 4panel
cd 4panel
sudo nano main.cpp
git clone https://github.com/hzeller/rpi-rgb-led-matrix.git
sudo g++ -Wall -Irpi-rgb-led-matrix/include  main.cpp -o main

Должны быть следующие команды:

sudo chmod +x main
./main

main.cpp содержит тот же код, что иhttps://github.com/hzeller/rpi-rgb-led-matrix/blob/master/examples-api-use/minimal-example.cc

#include "led-matrix.h"

#include <unistd.h>
#include <math.h>
#include <stdio.h>
#include <signal.h>

using rgb_matrix::GPIO;
using rgb_matrix::RGBMatrix;
using rgb_matrix::Canvas;

volatile bool interrupt_received = false;
static void InterruptHandler(int signo) {
  interrupt_received = true;
}

static void DrawOnCanvas(Canvas *canvas) {
  /*
   * Let's create a simple animation. We use the canvas to draw
   * pixels. We wait between each step to have a slower animation.
   */
  canvas->Fill(0, 0, 255);

  int center_x = canvas->width() / 2;
  int center_y = canvas->height() / 2;
  float radius_max = canvas->width() / 2;
  float angle_step = 1.0 / 360;
  for (float a = 0, r = 0; r < radius_max; a += angle_step, r += angle_step) {
    if (interrupt_received)
      return;
    float dot_x = cos(a * 2 * M_PI) * r;
    float dot_y = sin(a * 2 * M_PI) * r;
    canvas->SetPixel(center_x + dot_x, center_y + dot_y,
                     255, 0, 0);
    usleep(1 * 1000);  // wait a little to slow down things.
  }
}

int main(int argc, char *argv[]) {
  RGBMatrix::Options defaults;
  defaults.hardware_mapping = "regular";  // or e.g. "adafruit-hat"
  defaults.rows = 32;
  defaults.chain_length = 1;
  defaults.parallel = 1;
  defaults.show_refresh_rate = true;
  Canvas *canvas = rgb_matrix::CreateMatrixFromFlags(&argc, &argv, &defaults);
  if (canvas == NULL)
    return 1;

  // It is always good to set up a signal handler to cleanly exit when we
  // receive a CTRL-C for instance. The DrawOnCanvas() routine is looking
  // for that.
  signal(SIGTERM, InterruptHandler);
  signal(SIGINT, InterruptHandler);

  DrawOnCanvas(canvas);    // Using the canvas.

  // Animation finished. Shut down the RGB matrix.
  canvas->Clear();
  delete canvas;

  return 0;
}

Ошибки:

/tmp/cci8MGL5.o: In function `main':
main.cpp:(.text+0x264): undefined reference to `rgb_matrix::RGBMatrix::Options::Options()'
main.cpp:(.text+0x2a8): undefined reference to `rgb_matrix::CreateMatrixFromFlags(int*, char***, rgb_matrix::RGBMatrix::Options*, rgb_matrix::RuntimeOptions*, bool)'
collect2: error: ld returned 1 exit status

Возможные исправления, которые я нашел:

    1. Связывайте файлы .cpp в строгом порядке при компиляции: sudo g++ main1.cpp main2.cpp
    1. Этот
    1. Потребность в makefile

При поиске похожих проблем и, надеюсь, найти какое-то волшебное решение, я оказался более озадачен, чем раньше. Я понятия не имею, то ли то, что я сделал, то, что я должен был сделать.

    1. Какие файлы cpp связать, если у меня есть только один?
    1. Нужно ли связывать все файлы .cpp и .h, которые есть в библиотеке?
    1. Я ничего не понимаю в makefile или почему он вообще существует.

Моя проблема может быть связана с моей ситуацией, но я считаю, что ответы помогут мне в будущих проектах.

Вы можете ответить на все мои вопросы и недоразумения и помочь мне понять, что происходит, или ответить только на вопрос, связанный с заголовком: Почему makefile?

Не sudo g++ .... Почему вы хотите, чтобы g++ работал от имени пользователя root?

Benjamin T 28.05.2019 16:13

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

melpomene 28.05.2019 16:15

Пожалуйста, задавайте по одному вопросу в каждом посте.

HolyBlackCat 28.05.2019 16:21

Вам не нужен/имеет make-файл. Ваша ошибка вызвана компоновщиком, и он отчаянно пытается найти реализацию используемой библиотеки (обычно это файл .a/.lib). Вам нужно указать вашему компилятору (g++) добавить библиотеку к входным данным компоновщика.

Zaiborg 28.05.2019 16:24

Вероятно, вам нужно сделать следующее: перейти в каталог rpi-rgb-led-matrix/lib, запустить make из него. Он должен скомпилировать библиотеку и выдать librgbmatrix.a. Добавьте -Lrpi-rgb-led-matrix/lib -lrgbmatrix к команде g++, чтобы связать библиотеку (флажок должен стоять после main.cpp).

HolyBlackCat 28.05.2019 16:25

Вы никогда должны использовать makefile. Но когда у вас есть 10, 50, 100 или 1000 файлов для компиляции, вы начинаете думать, что использование командной строки g++ не лучшее решение. make — это не более чем простой скрипт для вызова компилятора с возможностью определения нескольких различных вызовов.

Yksisarvinen 28.05.2019 16:27

Я бы предпочел не использовать make-файл, а вместо этого использовать cmake.

Devolus 28.05.2019 16:44

Сначала вы должны узнать, как работает компилятор и что происходит за вашей IDE. Узнайте, что ваш компилятор делает с окнами в коде Visual Studio. Вы можете скомпилировать свой код в Powershell с визуальным C++. Изучив эту очень важную часть разработки программного обеспечения на своей любимой платформе, вы знаете, что делать на большинстве других платформ. Makefile — это инструмент, который также можно использовать в Windows для автоматизации процесса сборки.

Thomas Sablik 28.05.2019 16:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
353
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

The problem is that, after a long battle with downloading the library that I am trying to use, after installing a compiler, creating a file, and finding the right command to run and include paths I get undefined reference to errors.

На SO уже есть множество вопросов и ответов, касающихся таких проблем, особенно Что такое ошибка неопределенной ссылки/неразрешенного внешнего символа и как ее исправить?.

Possible fixes that I found:

    1. Link .cpp files in a strict order when compiling: sudo g++ main1.cpp main2.cpp
    1. [SO question with answers saying roughly the same as the previous]

Обычно не актуально. Хотя порядок связь разных объектов/библиотек существенен, это редко влияет на случай, когда все нужные C и/или C++ исходные файлы указаны в одной команде компиляции.

    1. The need of a makefile

Использование make по своей сути не решает проблему, и уж точно не необходимо для решения проблемы. Написание make-файла, который обеспечивает успешную сборку, будь то напрямую или с помощью инструмента сборки, такого как CMake или Autotools, требует от вас понимания, по крайней мере, на высоком уровне, как работают компиляторы и компоновщики, каковы их входные и выходные данные и каковы их возможности. аргументы и варианты означают.

    1. What cpp files to link if I have just one ?

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

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

    1. Do I need to link all the .cpp and .h files that the library has ?

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

    1. I don't understand a thing about makefile or why it even exists.

Makefile — это входные данные для make. Хорошо написанный определяет правила создания одной или нескольких «целей» и выражает предпосылки (как правило, исходные источники или другие цели) для этого. make использует их вместе с набором встроенных правил, чтобы выяснить, какие шаги нужно предпринять для создания целей, которые вы просите создать, а также какие шаги он может пропустить. Обычно, например, make-файлы пишутся таким образом, что если вы создаете проект с несколькими исходными кодами, изменяете только один исходный файл, а затем снова создаете, перекомпилируется только измененный исходный код.

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

В целом тогда:

When do I need to use/have a makefile?

Никогда. Но предоставление хорошего и использование make для создания вашего проекта имеет следующие преимущества:

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

Это также может быть достигнуто с помощью простого сценария сборки, но make также может дать вам

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

Спасибо за ваше терпение, чтобы ответить на все мои вопросы. Несмотря на то, что проблема не устранена, я знаю, что лучше понимаю назначение компиляторов, редакторов ссылок и make-файла.

bleah1 29.05.2019 13:16

Другие вопросы по теме