引言

前段时间因公司内部业务调整,需要将自己的手头上的有关esp8266和esp32的相关项目移交出去,为了保护核心代码,应领导要求需将一些核心的代码打包成静态库(有关静态库和动态库的概念,我在之前的文章中都有介绍,以及如何在linux和windows中如何制作)。那么今天我们就来介绍下如何基于ESP8266_RTOS_SDK(idf框架,这里以esp8266为例,esp32完全同样的原理)制作我们自己的静态库,既能提供他人使用,又能隐藏自己的源代码。相信大家在日常开发中,常常会见到以.a结尾的文件,这并是我们今天的目标——静态库,往往第三方组件就是以.a和.h的方式提供给我们使用。 好了,话不多说,进入我们的主题~

forum.jpg


第一种:自己手工打包制作

首先需要说明的是,文章中我会介绍2种方式制作我们的静态库,第一种是自己手动使用工具链中的ar工具来制作;第二种是利用esp8266(或esp32)工程编译完成自动生成静态库的方式。

OK,先来介绍下第一种方式~

1)提供静态库的原材料,即.c和.h,这里我以简单的实现加,减,乘为例,具体如下:

C++
//simplecal.h 内容#ifndef _SIMPLE_CAL_H__#define _SIMPLE_CAL_H__int  myadd(int a, int b);


int  mysub(int a, int b);


int  mymul(int a, int b);


#endif/****分割线********///simplecal.c 内容#include "simple_cal.h"int myadd(int a, int b){
        return (a+b);
}

int mysub(int a, int b){
        return (a-b);
}

int mymul(int a, int b){
        return (a*b);
}

2)接着我们使用工具链中的ar工具来打包,需要说明的是如果esp8266环境则使用的是xtensa-lx106-elf工具链,如果是esp32则使用的是xtensa-esp32-elf工具链,相信大家在搭建开发环境的时候就已熟悉(如果不清楚的小伙伴请参考我的开发环境搭建相关视频)。这里我编写了一个简单的makefile来管理制作过程,具体内容如下:

Makefile
PRO_SRC := $(wildcard *.c)
PRO_OBJ := $(patsubst %.c,%.o,$(PRO_SRC))
CC := xtensa-lx106-elf-           #若是esp32,请改为 “xtensa-esp32-elf”${make_lib}.a:$(PRO_OBJ)
        @echo ${PRO_SRC}
        @echo ${PRO_OBJ}
        $(CC)ar -rc lib$(make_lib).a $^
        strip $(addprefix lib, $@) --strip-debug --strip-unneeded
        
${PRO_OBJ}:%.o:%.c$(CC)gcc -c $< -I .             #-nostdlib -nostdinc .PHONY:cleanclean:
        rm -rf lib*.a *.o

我们将以上makefile和原材料.c和.h放在一个目录中,如下:

forum.jpg


然后打开msys32(这里我以windows环境为例,linux环境也是同样操作), 并cd到该目录中,然后命令行输入:

Go
make make_lib=simplecal

forum.jpg

在上图红框标注的libsimplecal.a就是我们的制作的静态库。

3)接着我们我们把libsimplecal.a 和 simple.h加入到工程中测试。我们创建一个third_components的文件夹,具体目录层级如下图(需要说明的是大家不用和我一样创建各个目录存放相应的文件,这里我是强迫症,按正规实际项目规范来,根据不同的文件存放相应的目录中):

forum.jpg


最后在include文件夹中存放了simple.h , 在lib文件夹中存放了libsimlecal.a。

重点:在third_components顶层目录中创建了一个componet.mk文件,内容如下:

Makefile
COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_SRCDIRS := .

COMPONENT_ADD_INCLUDEDIRS += . myapp/include
COMPONENT_SRCDIRS += . myapp

LIBS += simplecal

COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH)/myapp/lib $(addprefix -l,$(LIBS))

说明:

COMPONENT_ADD_INCLUDEDIRS += myapp/include //为工程添加自己的头文件路径

COMPONENT_SRCDIRS += myapp //为工程添加自己的源文件路径(这里我们没有源文件,因此无关紧要,可写可不写)

LIBS += simplecal

COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH)/myapp/lib $(addprefix -l,$(LIBS)) //为工程添加链接属性,即指定我们的静态库名, 和静态库的路径


4)最后我们尝试编译, 命令行输入make

forum.jpg


出现以上内容,说明我们编译通过,接着就可以下载到板子上看程序跑起来验证结果是否正确(因板子没带回来,放公司了,故这里就不给大家演示了,结果是正确的,大家可以自己验证下)

forum.jpg

测试主函数

重点!!! 使用上述的方法制作静态库是完全正确的, 但是在实际应用过程,我发现制作的静态库会链接到esp8266内部的irom中,因为irom本身空间较小,当我们的源代码再增多点,就会出现重定位超过范围,报错:“dangerous relocation :.....out of range”

forum.jpg

期间我粗略分析了下esp8266工程框架的makefile 以及一些相关链接脚本,

forum.jpg


但是未能找到相关的链接的处理方式, 使其链接到外部的flash中, 之后我也咨询了乐鑫的技术支持,也未能得到很好的解释。于是乎我暂时先把这问题搁置一下(因为最近个人事比较多 - -!),回头抽时间再完整分析下乐鑫的整体框架Makefile和链接脚本,看看能否找到解决的方法。

接下来介绍第二种方式,这个亲测有效,而且更适合大众,不需要考虑复杂的Makefile和链接脚本和gcc工具链等等因素,直接上手就能用。OK,开始行动~

第二种:利用现有的工程

首先还是在工程目录中创建一个文件夹如simplecal(名称随意,但是如果不是叫components,则需要在工程主Makefile中添加EXTRA_COMPONENT_DIRS,来指定自己的额外增加的组件),并把源文件simple.c 和simple.h放到simple目录中:

forum.jpg


同时创建了一个component.mk文件,其内容:

Makefile
COMPONENT_ADD_INCLUDEDIRS += .
COMPONENT_SRCDIRS += .

再次提醒,在工程主Makefile中添加以下内容:

Go
EXTRA_COMPONENT_DIRS := ./simplecal

forum.jpg


好了,接着我们直接make编译,编译完成后,会在工程路径中自动生成了build文件夹, 我们进入找到simplecal文件夹:

forum.jpg


然后我们进去simplecal中, 可以看到自动为我们生成了libsimplecal.a静态链接库

forum.jpg


接着我们还是按照上面的方式测试下是否可用,将工程目录中的simplecal文件中的simple_cal.c源文件删除,然后把静态库libsimplecal.a拷贝进来:

forum.jpg


同时我们需要修改下component.mk文件,内容如下:

Makefile
COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_SRCDIRS := .

COMPONENT_ADD_LDFLAGS += -L . $(COMPONENT_PATH)/libsimplecal.a

接着我们我们删除build整个文件夹,再次make,全编译:

forum.jpg


可以看到是编译成功,接着就是下载到开发板中实际验证咯~

总结

以上2种方式都能制作esp8266/esp32平台的静态库,当我们制作完成并应用工程中,这里有个关键的地方,即为工程添加链接参数COMPONENT_ADD_LDFLAGS,格式的话请参考上面。在第一种方式可能在链接重定位时有点问题,大家可以亲测下,如果遇到跟我相同的情况,有解决的方法也可以下方留言告知我下(非常感谢),本想偷个懒的我,也只能老老实实的详细研究下乐鑫的整体框架,若找到解决方案再另开文章介绍。以上描述可能省略一些细节,若大家在实际操作中,有任何疑问,欢迎留言,转发,或私信。 好了今天的分享先到这,对物联网,嵌入式等感兴趣的小伙伴,记得关注,转发~

forum.jpg