【问题标题】:How to add precompiled library to ESP8266 SDK?如何将预编译库添加到 ESP8266 SDK?
【发布时间】:2020-03-24 07:08:56
【问题描述】:

我有一个预编译的库(.a 扩展名),我想在 ESP8266 RTOS SDK 示例中使用它。

在以下路径(ESP8266_RTOS_SDK\components\esp8266\lib)中有一个文件夹,里面有 22 个 .a 文件。我已经把我的库放在那里了,但是编译器就像它没有识别我的库的功能。

我已经阅读了一些关于编辑一些 makefile 的内容。我真的应该这样做吗?如果是,我想知道要编辑哪个文件? (放置在哪个路径上)

编辑

这是我的工作文件夹:

我被 Espressif(ESP8266 的开发者)指导在 component.mk 上制作如下所示,但它不起作用,编译一直显示“未定义的引用”对于库的功能。

然后我在 Windows 上创建了一个名为 COMPONENT_PATH 的环境变量,其路径与第一张图片中显示的相同。

这有什么问题吗?

编辑 2

在 main: 中创建文件夹“include”:

在 C 代码之上添加:#include "include/lib123.h",其中仅包含一行:int sum (int a, int b);

在 main 上添加了一个调用:int result = sum(1,2);

得到编译器错误:未定义对“sum”的引用

编辑 3

对于每次编译尝试,文件夹 \esp\tcp_server\build 中的以下文件都会更新。

这里就不直接放了,因为文件有10000多行:https://raw.githubusercontent.com/jefersonpehls/esp8266_freeRTOS_firebase/master/tcp_server.map

EDIT4

当我尝试制作时,显示的是这样的:

make
Toolchain path: /opt/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc
Toolchain version: crosstool-ng-1.22.0-100-ge567ec7b
Compiler version: 5.2.0
Python requirements from C:/msys32/home/sandr/esp/ESP8266_RTOS_SDK/requirements.txt are satisfied.
LD build/tcp_server.elf
C:/msys32/home/sandr/esp/tcp_server/build/main\libmain.a(tcp_server_v5.o):(.literal.app_main+0x24): undefined reference to `sum'
C:/msys32/home/sandr/esp/tcp_server/build/main\libmain.a(tcp_server_v5.o): In function `app_main':
C:/msys32/home/sandr/esp/tcp_server/main/tcp_server_v5.c:382: undefined reference to `sum'
collect2.exe: error: ld returned 1 exit status
make: *** [C:\msys32\home\sandr\esp\ESP8266_RTOS_SDK/make/project.mk:510: /home/sandr/esp/tcp_server/build/tcp_server.elf] Error 1

编辑 5

这是我用来制作的完整步骤

sandr@DESKTOP-MA6RTB6 MINGW32 ~
$ cd ~/esp/tcp_server

sandr@DESKTOP-MA6RTB6 MINGW32 ~/esp/tcp_server
$ export PATH="$PATH:/opt/xtensa-lx106-elf/bin"

sandr@DESKTOP-MA6RTB6 MINGW32 ~/esp/tcp_server
$ make
Toolchain path: /opt/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc
Toolchain version: crosstool-ng-1.22.0-100-ge567ec7b
Compiler version: 5.2.0
Python requirements from C:/msys32/home/sandr/esp/ESP8266_RTOS_SDK/requirements.txt are satisfied.
LD build/tcp_server.elf
C:/msys32/home/sandr/esp/tcp_server/build/main\libmain.a(tcp_server_v5.o):(.literal.app_main+0x24): undefined reference to `sum'
C:/msys32/home/sandr/esp/tcp_server/build/main\libmain.a(tcp_server_v5.o): In function `app_main':
C:/msys32/home/sandr/esp/tcp_server/main/tcp_server_v5.c:382: undefined reference to `sum'
collect2.exe: error: ld returned 1 exit status
make: *** [C:\msys32\home\sandr\esp\ESP8266_RTOS_SDK/make/project.mk:510: /home/sandr/esp/tcp_server/build/tcp_server.elf] Error 1

编辑 6

这是 esp\tcp_server\Makefile 的内容

#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := tcp_server

EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common


include $(IDF_PATH)/make/project.mk

这是esp\tcp_server\main\component.mk的内容

#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files 
# in directory, adding 'include' to include path.)

COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/lib123.a

IDF_PATH 是 C:\msys32\home\sandr\esp\ESP8266_RTOS_SDK

编辑 7

这是 $(IDF_PATH)/make/project.mk

https://github.com/jefersonpehls/esp8266_freeRTOS_firebase/blob/master/project.mk

【问题讨论】:

  • 发布文字,而不是文字图片
  • “未定义引用”是链接器错误,而不是编译器错误。发布整个构建日志,而不是描述它。这是必不可少的诊断信息——所有这些信息,而不仅仅是最终的错误消息。
  • 地图文件不是我们这里需要的。 构建日志 是构建期间 向控制台输出的所有文本。即包含您正在描述的错误消息的文本。
  • LD build/tcp_server.elf 是链接器命令行。奇怪的是它使用大写字母,但它不包含您在 component.mk 中设置的任何标志。不知何故,您需要使 ld 命令行在我的回答中看起来像这样。为此,您必须更好地了解您的构建是如何设置的,或者至少告诉使用您是如何构建它的 - 发出了什么命令以及项目和/或制作文件的内容(作为文本,而不是图片文本)。
  • 您需要将~/esp/tcp_server/makefile 和~/esp/tcp_server/main/component.mk 的文本内容添加到您的问题中

标签: sdk embedded static-libraries esp8266 rtos


【解决方案1】:

链接对象库代码是链接器而不是编译器的工作。

仅将库放在文件夹中是不够的,链接器需要知道库的路径和库名称。该文件不必与其他库位于同一文件夹中,尽管这样可以避免向链接器命令行添加额外的库路径。

如果使用 GNU 工具链,链接器 (ld) 使用 -L<searchdir> 开关注册库路径,对于名为 libXXX.a 的库,链接它的开关是 -lXXX

例如:

ld -o program.elf main.o module.o -L.\MyLibraries -llinkthis.a

将链接 liblinkthis.a 在构建目录的 MyLibraries 子文件夹中。

如果使用gccg++ 驱动程序编译和链接,这些开关可以传递给驱动程序并用于调用ld。例如:

gcc main.c -o main.o -c
gcc module.c -o module.o -c
gcc -L.\MyLibraries -llinkthis.a main.o module.o -o program.elf 

或者对于单个源构建:

gcc main.c -L.\MyLibraries -llinkthis.a -o program.elf

对于其他工具链,请参阅关于链接静态库的工具链/链接器文档。

对于包含许多模块的复杂构建,那么您当然应该使用 makefile 或类似的构建管理工具,或者(更容易)带有项目/构建管理器的 IDE。 IDE 可能允许您通过对话框添加库和路径,而不必知道工具链的所有单独开关,make 和类似工具对于复杂的构建可能更灵活,但有点神秘。但是使用make 与如何链接静态库的问题并没有直接关系。

【讨论】:

  • 是在 .a 中转换 .o 的链接器吗?在这个转换中我需要尝试隐藏符号吗?
  • @abomin3v3l 在您的编辑中,您尝试链接 include/lib123.a,但 lib123.a 不在子目录“include”中。实际上没有“包含”。我的回答是对如何链接的一般描述。 make 文件需要按照我的建议生成命令行。您只需要 -l123,因为您的库位于构建目录中。
  • @abomin3v3l 链接器没有转换任何东西,它链接。它结合了多个目标文件,确定它们在图像中的位置,并解析目标代码与实际地址之间的符号链接。
  • lib123.a 的正确路径应该是什么?我的环境变量路径是否正确?为什么是“include/lib123.a”?从哪里得到“包含/”?感谢您的帮助!
  • @abomin3v3l 构建日志将说明一切(通过显示 make 生成的命令),但您没有提供。 “但它不起作用”不是有用的诊断;构建输出的消息是。
猜你喜欢
  • 1970-01-01
  • 2022-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多