我什么时候需要使用/拥有一个makefile?

时间:2019-05-28 14:10:16

标签: c++ c linux makefile raspberry-pi

我正在尝试学习如何在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. This
    1. 需要makefile

在寻找类似问题并希望找到一些魔术解决方案时,我最终比以前更加困惑。我不知道我做的是我应该做的。

    1. 如果我只有一个,可以链接哪些cpp文件?
    1. 我是否需要链接库中所有的.cpp和.h文件?
    1. 我不了解关于makefile或它为什么存在的事情。

我的问题可能与我的情况有关,但我相信答案会帮助我进行将来的项目。

您可以自由回答我所有的问题和误解,并帮助我了解发生了什么或仅回答与标题相关的问题:为什么makefile

1 个答案:

答案 0 :(得分:3)

  

问题是,在与库的长期争夺战之后   安装编译器后,我尝试使用的方法是创建文件,   并找到正确的命令来运行并包含我得到的 undefined路径   参考错误。

关于SO的问题已经有很多关于此类问题的解答,尤其是What is an undefined reference/unresolved external symbol error and how do I fix it?

  

我发现的可能的修复程序:

     
      
    1.   
    2. 在编译时按严格顺序链接.cpp文件:sudo g++ main1.cpp main2.cpp
    3.   
  •   
    1.   
    2. [SO问题的答案与前面的回答大致相同]
    3.   
  •   

通常不相关。尽管不同对象/库的 link 顺序很重要,但是在同一编译命令中指定了所有需要的C和/或C ++ 源文件的情况下,这很少影响这种情况。< / p>

  
      
    1.   
    2. 需要makefile
    3.   
  •   

使用make并不能固有地解决问题,并且肯定不是解决问题的必要条件。无论是直接还是通过诸如CMake或Autotools之类的构建工具,编写一个能够成功构建的makefile,都需要您至少在高层次上了解编译器和链接器的工作方式,它们的输入和输出以及它们的含义。参数和选项的意思。

  
      
    1.   
    2. 如果我只有一个,可以链接哪些cpp文件?
    3.   
  •   

您根本不会直接链接.cpp。您编译,并将结果链接到任何所需的库和任何其他对象。 g++将默认尝试一步一步完成所有操作,在这种情况下,即使同时执行了两个功能,该过程也通常称为“编译”,而不是“链接”。通过指定g++选项,可以使-c仅在不链接的情况下进行编译(事实证明,在makefile中很常见),它将很高兴地链接对象和库而无需进行任何编译如果您没有命名任何源文件。

无论如何,您的情况完全不是一个.cpp文件。这是您一个.cpp文件 plus 您要使用的所有库文件。

  
      
    1.   
    2. 我是否需要链接库中所有的.cpp和.h文件?
    3.   
  •   

您不需要编译(直接)链接任何.h文件。但是,如果要使用下载了源代码的库,则要做需要编译所有源代码,并且可能应该将它们链接到实际库中。此外,除非您生成并使用静态库,否则还应该 install 构建的库。库资源似乎包含一个makefile,因此建议您使用make执行这些步骤。

  
      
    1.   
    2. 我不了解makefile或为什么它存在。
    3.   
  •   

makefile是make的输入。写得好的人定义了如何构建一个或多个“目标”的规则,并表达了这样做的前提条件(通常是原始资源或其他目标)。 make结合使用这些规则和一组内置规则来确定要构建目标的构建步骤,以及可以跳过的步骤。例如,典型的做法是编写makefile,以便在构建多源项目时,仅修改一个源文件,然后再次生成,只有重新编译的源才可以编译。

当您习惯于只有少量资源的项目时,这似乎微不足道,但是对于大型项目而言,这很重要,因为大型项目的完全重建成本很高-在某些情况下,甚至很多小时。但是,即使一个完整的构建只需要几分钟,但如果您真的只需要花费几秒钟,那么在整天的工作中这将浪费大量时间。

总体,然后:

  

我什么时候需要使用/拥有一个makefile文件?

从不。但是提供一个好的文件并使用make来构建您的项目具有以下优点:

  • 以持久,可操作的形式存储所有必需的构建命令,包括选项和参数,因此
  • 提供一致的自动化构建。

这些也可以通过简单的构建脚本来实现,但是make也可以为您提供

  • 通过仅构建过时的片段来加快构建速度,并且
  • 关于如何从相应来源构建特定种类目标的内置知识。