Я пытаюсь научиться кодировать на 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
Возможные исправления, которые я нашел:
sudo g++ main1.cpp main2.cpp
makefile
При поиске похожих проблем и, надеюсь, найти какое-то волшебное решение, я оказался более озадачен, чем раньше. Я понятия не имею, то ли то, что я сделал, то, что я должен был сделать.
makefile
или почему он вообще существует.Моя проблема может быть связана с моей ситуацией, но я считаю, что ответы помогут мне в будущих проектах.
Вы можете ответить на все мои вопросы и недоразумения и помочь мне понять, что происходит, или ответить только на вопрос, связанный с заголовком: Почему makefile
?
Makefile — это своего рода сценарий, который автоматизирует (полностью или частично) процесс сборки. Прежде чем иметь дело с make
, вы уже должны быть знакомы с тем, как вызывать ваш компилятор и, в частности, с тем, как создавать объектные файлы и как связать их для создания исполняемого файла.
Пожалуйста, задавайте по одному вопросу в каждом посте.
Вам не нужен/имеет make-файл. Ваша ошибка вызвана компоновщиком, и он отчаянно пытается найти реализацию используемой библиотеки (обычно это файл .a/.lib). Вам нужно указать вашему компилятору (g++) добавить библиотеку к входным данным компоновщика.
Вероятно, вам нужно сделать следующее: перейти в каталог rpi-rgb-led-matrix/lib
, запустить make
из него. Он должен скомпилировать библиотеку и выдать librgbmatrix.a
. Добавьте -Lrpi-rgb-led-matrix/lib -lrgbmatrix
к команде g++
, чтобы связать библиотеку (флажок должен стоять после main.cpp
).
Вы никогда должны использовать makefile. Но когда у вас есть 10, 50, 100 или 1000 файлов для компиляции, вы начинаете думать, что использование командной строки g++ не лучшее решение. make
— это не более чем простой скрипт для вызова компилятора с возможностью определения нескольких различных вызовов.
Я бы предпочел не использовать make-файл, а вместо этого использовать cmake.
Сначала вы должны узнать, как работает компилятор и что происходит за вашей IDE. Узнайте, что ваш компилятор делает с окнами в коде Visual Studio. Вы можете скомпилировать свой код в Powershell с визуальным C++. Изучив эту очень важную часть разработки программного обеспечения на своей любимой платформе, вы знаете, что делать на большинстве других платформ. Makefile — это инструмент, который также можно использовать в Windows для автоматизации процесса сборки.
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:
- Link .cpp files in a strict order when compiling:
sudo g++ main1.cpp main2.cpp
- [SO question with answers saying roughly the same as the previous]
Обычно не актуально. Хотя порядок связь разных объектов/библиотек существенен, это редко влияет на случай, когда все нужные C и/или C++ исходные файлы указаны в одной команде компиляции.
- The need of a makefile
Использование make
по своей сути не решает проблему, и уж точно не необходимо для решения проблемы. Написание make-файла, который обеспечивает успешную сборку, будь то напрямую или с помощью инструмента сборки, такого как CMake или Autotools, требует от вас понимания, по крайней мере, на высоком уровне, как работают компиляторы и компоновщики, каковы их входные и выходные данные и каковы их возможности. аргументы и варианты означают.
- What cpp files to link if I have just one ?
Вы вообще не связываете .cpp
(напрямую). Вы компилировать его и связываете результат с любыми необходимыми библиотеками и любыми другими объектами. g++
по умолчанию попытается сделать все это за один шаг, и в этом случае процесс условно называется «компиляция», а не «связывание», хотя выполняются обе функции. g++
можно заставить компилировать только без линковки, указав ей опцию -c
(которая, как выясняется, распространена в make-файлах), и она с радостью линкует объекты и библиотеки, ничего не компилируя, если не указывать ни одного источника файлы к нему.
В любом случае, ваш случай вовсе не просто один .cpp
файл. Это ваш единственный .cpp
файл плюс со всеми файлами библиотеки, которые вы пытаетесь использовать.
- Do I need to link all the .cpp and .h files that the library has ?
Вам не нужно компилировать (напрямую) ссылку или на какие-либо файлы .h. Но если вы хотите использовать библиотеку, исходники которой вы загрузили, вам делать необходимо скомпилировать все исходники, и вы, вероятно, должен свяжете их в настоящую библиотеку. Кроме того, если вы не создаете и не используете статическую библиотеку, вы также должны установить создавать библиотеку, которую вы создаете. Похоже, что исходники библиотеки включают make-файл, поэтому вам рекомендуется использовать make
для выполнения этих шагов.
- 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-файла.
Не
sudo g++ ...
. Почему вы хотите, чтобы g++ работал от имени пользователя root?