LicheePI (荔枝派)Zero 开发笔记(3):安装 GoAhead 5.2.0 并交叉编译在 LicheePI 上运行,增加自定义 Actions

下载源码和尝试性安装

项目开发需要,使用 Goahead 作为嵌入式 WEB 服务器。以前一直选择 Goahead,这一次也不例外。到 Goahead 主页一看,只有 GoAhead 5.2.0 呈现出来。好吧,那就下载下来看看,这 5.2.0 和以前的版本在使用上到底有啥不同的地方呢?

下载主页:Download GoAhead | GoAhead Embedded Web Server | Embedded Web Servers | Embedthis Software

下载很方便,也很快捷。我是从ubuntu 18.04的桌面直接使用 Firefox 下载的,5.8MB的源码不到十秒钟就下载下来了,然后给它解压到我的工作目录。先不做任何修改,在 x86_64 平台上直接编译一遍,看编译过程怎么样,令人欣慰的是 make 和 sudo make install 没有一处错误或警告,执行完 make install 之后,在 /etc/goahead 文件夹中已经拷贝好了 auth.txt, route.txt, self.crt和 self.key 四个文件。输入 goahead -v --home /etc/goahead /var/www (事先将网页文件拷贝到了 /var/www 中了),从 Firefox 输入 127.0.0.1 直接显示出 index.html,这是一路无坑。

使用 LicheePI 的交叉编译链进行编译

在本机上编译安装后,心里有了点底。下一步使用 LicheePI 的交叉编译链 linaro-arm-linux-gnueabihf 进行编译看看。在编译之前,还是从 Makefile 开始。Goahead 5.2.0 的 Makefile 和以前版本看不出什么区别,于是转而查看 projects 目录下的几组 mk 文件。

我用的是ubuntu 18.04,打开 <你的工作目录>/goahead-5.2.0/projects/goahead-linux-default.mk 文件,找到对 CC 和 AR 的定义,可以看到如下的片段。

#
#   goahead-linux-default.mk -- Makefile to build Embedthis GoAhead for linux
#

NAME                  := goahead
VERSION               := 5.2.0
PROFILE               ?= default
ARCH                  ?= $(shell uname -m | sed 's/i.86/x86/;s/x86_64/x64/;s/arm.*/arm/;s/mips.*/mips/')
CC_ARCH               ?= $(shell echo $(ARCH) | sed 's/x86/i686/;s/x64/x86_64/')
OS                    ?= linux
CC                    ?= gcc
AR                    ?= ar
CONFIG                ?= $(OS)-$(ARCH)-$(PROFILE)
BUILD                 ?= build/$(CONFIG)
LBIN                  ?= $(BUILD)/bin
PATH                  := $(LBIN):$(PATH)

ME_COM_COMPILER       ?= 1
ME_COM_LIB            ?= 1
ME_COM_MATRIXSSL      ?= 0
ME_COM_MBEDTLS        ?= 1
ME_COM_NANOSSL        ?= 0
ME_COM_OPENSSL        ?= 0
ME_COM_OSDEP          ?= 1
ME_COM_SSL            ?= 1
ME_COM_VXWORKS        ?= 0

ME_COM_OPENSSL_PATH   ?= "/path/to/openssl"

ifeq ($(ME_COM_LIB),1)
    ME_COM_COMPILER := 1
endif
ifeq ($(ME_COM_MBEDTLS),1)
    ME_COM_SSL := 1
endif
ifeq ($(ME_COM_OPENSSL),1)
    ME_COM_SSL := 1
endif

当 CC 未赋值时默认值被定义为 gcc,AR 默认值是 ar,搜索了一下全文,只有这两个编译/打包程序。于是采用了如下命令对 Goahead 进行编译。

Bingo!居然没有任何错误和警告提示就成功了!

命令:
CC=arm-linux-gnueabihf-gcc AR=arm-linux-gnueabihf-ar make -j16

运行结果:
/home/luoyuan/Documents/gwdev/engine/../goahead-5.2.0/build/linux-x64-default/bin
make[1]: Entering directory '/home/luoyuan/Documents/gwdev/goahead-5.2.0'
make[1]: Leaving directory '/home/luoyuan/Documents/gwdev/goahead-5.2.0'
make[1]: Entering directory '/home/luoyuan/Documents/gwdev/goahead-5.2.0'
make --no-print-directory -f projects/goahead-linux-default.mk all
      [Info] Use make SHOW=1 to trace executed commands.
   [Compile] build/linux-x64-default/obj/mbedtls.o
   [Compile] build/linux-x64-default/obj/goahead-mbedtls.o
   [Compile] build/linux-x64-default/obj/action.o
   [Compile] build/linux-x64-default/obj/alloc.o
   [Compile] build/linux-x64-default/obj/auth.o
   [Compile] build/linux-x64-default/obj/cgi.o
   [Compile] build/linux-x64-default/obj/http.o
   [Compile] build/linux-x64-default/obj/fs.o
   [Compile] build/linux-x64-default/obj/jst.o
   [Compile] build/linux-x64-default/obj/file.o
   [Compile] build/linux-x64-default/obj/crypt.o
   [Compile] build/linux-x64-default/obj/osdep.o
   [Compile] build/linux-x64-default/obj/options.o
   [Compile] build/linux-x64-default/obj/rom.o
   [Compile] build/linux-x64-default/obj/js.o
   [Compile] build/linux-x64-default/obj/route.o
   [Compile] build/linux-x64-default/obj/runtime.o
   [Compile] build/linux-x64-default/obj/socket.o
   [Compile] build/linux-x64-default/obj/time.o
   [Compile] build/linux-x64-default/obj/upload.o
   [Compile] build/linux-x64-default/obj/mn-web.o
      [Copy] build/linux-x64-default/bin
   [Compile] build/linux-x64-default/obj/goahead.o
      [Link] build/linux-x64-default/bin/libmbedtls.a
      [Link] build/linux-x64-default/bin/libgoahead-mbedtls.a
      [Link] build/linux-x64-default/bin/libgo.so
      [Link] build/linux-x64-default/bin/goahead

On Linux/MacOS, you can now install via "sudo make w -j --jobserver-fds=3,4 install" or run GoAhead via: "sudo make run"
To run locally, put linux-x64-default/bin in your path

找到build/linux-x64-default/bin,看到经过 arm-linux-gnueabihf-strip 后文件列表如下。

luoyuan@iotdev:~/Documents/gwdev/goahead-5.2.0/build/linux-x64-default/bin$ dir
total 2540
drwxrwxr-x 2 luoyuan luoyuan    4096 Sep 14 20:13 ./
drwxrwxr-x 5 luoyuan luoyuan    4096 Sep 14 20:13 ../
-rw-rw-r-- 1 luoyuan luoyuan     116 Sep 13 18:41 auth.txt
-rw-r--r-- 1 luoyuan luoyuan    1724 Sep 14 20:13 ca.crt
-rw-r--r-- 1 luoyuan luoyuan    1675 Sep 14 20:13 ca.key
-rw-r--r-- 1 luoyuan luoyuan     924 Sep 14 20:13 ec.crt
-rw-r--r-- 1 luoyuan luoyuan     302 Sep 14 20:13 ec.key
-rwxrwxr-x 1 luoyuan luoyuan   28404 Sep 14 20:13 goahead*
-rw-rw-r-- 1 luoyuan luoyuan   53838 Sep 14 20:13 libgoahead-mbedtls.a
-rwxrwxr-x 1 luoyuan luoyuan 1270468 Sep 14 20:13 libgo.so*
-rw-rw-r-- 1 luoyuan luoyuan  937736 Sep 14 20:13 libmbedtls.a
-rw-r--r-- 1 luoyuan luoyuan  256338 Sep 14 20:13 roots.crt
-rw-r--r-- 1 luoyuan luoyuan    1444 Sep 14 20:13 self.crt
-rw-r--r-- 1 luoyuan luoyuan    1679 Sep 14 20:13 self.key
-rw-r--r-- 1 luoyuan luoyuan    1444 Sep 14 20:13 test.crt
-rw-r--r-- 1 luoyuan luoyuan    1679 Sep 14 20:13 test.key

goahead 的可执行文件为28404 字节,比以前版本的要大一点。libgo.so 是1.21MB,和以前版本的差不多。OK!把 goahead 和 libgo.so 这两个文件分别拷贝到目标板的 /usr/bin/ 目录和 /usr/lib/ 目录下,把 auth.txt,self.crt,self.key,和 src 目录下的默认 route.txt 拷贝到目标板的 /etc/goahead 目录下,网页文件拷贝到目标板的 /var/www 目录下,然后在 LicheePI 上执行

# goahead -v --home /etc/goahead /var/www

在 Firefox 的地址栏中输入目标板的 IP 地址:http://192.168.0.201,然后回车,Bingo!网页正确显示。

从这个过程看,Goahead 5.2.0 真心是修改了以前版本的一些毛病,例如按照上述过程编译的 Goahead 4.1.3/4.1.0/3.6.5,在初次运行时都会报无法获取本机IP地址的错误,还要去修改 http.c 的文件,在 setLocalHost 函数中将 IP 地址硬性赋值。

Goahead 5.2.0 的另一个改进是默认支持多线程 Make。

在Goahead 5.2.0 代码中增加自定义功能

和以往版本相似,在Goahead 5.2.0中增加自定义功能(jst,action,http API响应等)的通用步骤如下。

编制头文件 web-ext.h

在goahead-5.2.0/src 目录下建立一个web-ext.h的头文件,将新增功能所需的函数在这个头文件中进行预定义 ,顺便还可以 #define 你所需要的常量和结构。为了能使用 goahead API,在 web-ext.h 中要 #include "goahead.h",还可以 #include 其它你要用得到的头文件,例如 pthread.h,cJSON.h 等,代码示例如下片段。

/**
 * @brief     web-ext header file
 * @file      ...app/goahead-5.2.0/src/web-ext.h
 * @version   V1.0.0
 * @date      
 * @author    
 * @copyright Copyright(c) 2020-2022
 * @remark    
 */


#ifndef _WEB_EXT_H_GOA_5_2_0_
#define _WEB_EXT_H_GOA_5_2_0_

/*  Your user-defined defines  */

#ifndef MY_APP_ERROR_CODE
#define MY_APP_ERROR_OK 0
#define MY_APP_ERROR_EXPIRE 100
#define MY_APP_ERROR_IGNORE 200
#define MY_APP_ERROR_FAIL 900
#define MY_APP_ERROR_PAR_MIS 910
#define MY_APP_ERROR_PAR_BAD 950
#endif

#define WEB_REBOOT_STACK_SIZE 65536

#define _DBG_B0_ 1
#define _DBG_B1_ 1

/* Global includes                                       */
#include "goahead.h"
#include <pthread.h>

// Commonly used string utilities
void my_string_trim(unsigned char *s);
static void ajaxResponse(Webs *wp, char *msg);
static void ajaxReject(Webs *wp, char *msg);

// --------------------------------------------------------
// ASP actions for my_app
// --------------------------------------------------------

/**
 * @brief  Web Server jst/actions-C functions co-relation
 *
 * @return int, always 0
 */
int myAppWebServiceSetup();
int myAppWebServiceDestroy();

static void myAppError(char *rsp, int ec, char *em);

static void myActWeb_Login(Webs *wp);
static void myActGateway_GetParameters(Webs *wp);
static void myActGateway_GetIpSettings(Webs *wp);
static void myActGateway_SaveIpSettings(Webs *wp);


/**
 * @brief   Reboot gateway thread
 * @param   [in] argv: void*, nothing here
 */
static void *gw_reboot_thread(void *argv);

/**
 * @brief   Get gateway basic parameters
 *
 * @param [out] ret_json: Gateway parameters in JSON string
 * @return 0 if success; !0 for error. See MY_APP_ERROR_CODE #defines
 */
static int ws_gateway_getparameters(char *ret_json);

/**
 * @brief   Get gateway IP settings
 *
 * @param [out] ret_json: Gateway IP settings in JSON string
 * @return 0 if success; !0 for error. See MY_APP_ERROR_CODE #defines
 */
static int ws_gateway_getipsettings(char *ret_json);

/**
 * @brief Save IP(v4) settings to gateway
 *
 * @param [in] ipmode: 1 for Static; 2 for DHCP
 * @param [in] ipaddr: IPv4 address set to gateway
 * @param [in] subnetmask: Subnet mask of IP address
 * @param [in] defaultgateway: Default gateway of the gateway
 * @param [in] dnsprimary: IPv4 address of primary DNS server
 * @param [in] dnssecondary: IPv4 address of secondary DNS server
 * @return 0 if success; !0 for error. See MY_APP_ERROR_CODE #defines
 */
static int ws_gateway_saveipsettings(const int ipmode,
                                     const char *ipaddr,
                                     const char *subnetmask,
                                     const char *defaultgateway,
                                     const char *dnsprimary,
                                     const char *dnssecondary);


// ----------------- End of Extensions ----------------------------

#endif // _WEB_EXT_H_GOA_5_2_0_

编制 web-ext.c 文件,实现在 web-ext.h 中所定义的所有函数

这里只列出了 myAppWebServiceSetup() 函数的内容,其余的就略去详细内容了哈。。。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "web-ext.h"

int tvnMnWebServiceSetup()
{
    // ---------------------------------------------------------------
    // ASP Actions for Web extension
    // ---------------------------------------------------------------

    websDefineAction("aspWeb_Login",               myActWeb_Login);
    websDefineAction("aspGateway_GetGwParameters", myActGateway_GetParameters);
    websDefineAction("aspGateway_GetIpSettings",   myActGateway_GetIpSettings);
    websDefineAction("aspGateway_GetToken",        myActGateway_GetToken);
    websDefineAction("aspGateway_SaveIpSettings",  myActGateway_SaveIpSettings);
    websDefineAction("aspGateway_UploadToken",     mnyActGateway_UploadToken);

    // ---------------------   End of extension   --------------------
}

修改 goahead.c 文件将web-ext.h #include 进来,并调用相应函数

直接上代码吧。

#if ME_UNIX_LIKE && !MACOSX
    /*
        Service events till terminated
     */
    if (websGetBackground())
    {
        if (daemon(0, 0) < 0)
        {
            error("Cannot run as daemon");
            return -1;
        }
    }
#endif

    /*  揍是介个  */
    myWebServiceSetup();

    websServiceEvents(&finished);      /*  找到这条指令 ! */
    logmsg(1, "Instructed to exit");
    websClose();
    
    /*  还有介个  */
    myWebServiceDestroy();

#if WINDOWS
    windowsClose();
#endif
    return 0;
}

将 web-ext.o 链接到 goahead 的编译链条中

  • 修改 .../goahead-5.2.0/projects/goahead-linux-default.mk 文件,把 web-ext 链接进编译链条中。需要做如下的修改:3.1 找到 clean: 段(大概在第110行上下),将 web-ext.o 加入到删除列表中
clean:
	rm -f "$(BUILD)/obj/action.o"
	rm -f "$(BUILD)/obj/alloc.o"
	rm -f "$(BUILD)/obj/auth.o"
	rm -f "$(BUILD)/obj/cgi.o"
	rm -f "$(BUILD)/obj/cgitest.o"
	rm -f "$(BUILD)/obj/crypt.o"
	rm -f "$(BUILD)/obj/file.o"
	rm -f "$(BUILD)/obj/fs.o"
	rm -f "$(BUILD)/obj/goahead-mbedtls.o"
    ......
    ......
    ......
    rm -rf "$(BUILD)/obj/web-ext.o"
    ......
    ......
	rm -f "$(BUILD)/bin/libgo.so"
	rm -f "$(BUILD)/bin/libgoahead-mbedtls.a"
	rm -f "$(BUILD)/bin/libmbedtls.a"

clobber: clean
	rm -fr ./$(BUILD)
  • 在 goahead-linux-default.mk 的最后,加上如下 Make 命令
#
#	web-ext.o
#	99
#	
DEPS_99 += $(BUILD)/inc/goahead.h
DEPS_99 += $(BUILD)/inc/js.h

$(BUILD)/obj/web-ext.o:  src/web-ext.c $(DEPS_99)
	@echo '   [Compile] $(BUILD)/obj/web-ext.o'
	mkdir -p "$(BUILD)/inc"
	@cp src/web-ext.h $(BUILD)/inc/web-ext.h
	@touch $(BUILD)/inc/web-ext.h
	$(CC) -c -o $(BUILD)/obj/web-ext.o $(CFLAGS) $(DFLAGS) \
	    -D_FILE_OFFSET_BITS=64 \
		-D_FILE_OFFSET_BITS=64 \
		-DMBEDTLS_USER_CONFIG_FILE=\"embedtls.h\" \
		-DME_COM_OPENSSL_PATH=$(ME_COM_OPENSSL_PATH) \
		$(IFLAGS) "-I$(ME_COM_OPENSSL_PATH)/include" \
        src/web-ext.c
  • 找到第530行上下,将 web-ext.o 加入到 DEPS_40 (libgo要用到的)的最后,如下所示
#
#   libgo
#
DEPS_40 += $(BUILD)/inc/osdep.h
ifeq ($(ME_COM_MBEDTLS),1)
    DEPS_40 += $(BUILD)/bin/libgoahead-mbedtls.a
endif
ifeq ($(ME_COM_OPENSSL),1)
    DEPS_40 += $(BUILD)/bin/libgoahead-openssl.a
endif
DEPS_40 += $(BUILD)/inc/goahead.h
DEPS_40 += $(BUILD)/inc/js.h
DEPS_40 += $(BUILD)/obj/action.o
......
......
......

DEPS_40 += $(BUILD)/obj/time.o
DEPS_40 += $(BUILD)/obj/upload.o

# 下一条将 web-ext.o 加入到 libgo 的编译链条中
DEPS_40 += $(BUILD)/obj/web-ext.o  
  • 最后,找到第590行上下,在 $(BUILD)/bin/libgo.so: $(DEPS_40) 这一段中,按照如下修改,将 web-ext.o 加进去。注意这一段的第一行末尾加上了 $(DEPS_99),就是第2步新建的一个 DEPS 段;还有就是在所有 .o 的最后加上 web-ext.o
$(BUILD)/bin/libgo.so: $(DEPS_40) $(DEPS_99)
	@echo '      [Link] $(BUILD)/bin/libgo.so'
	$(CC) -shared -o $(BUILD)/bin/libgo.so $(LDFLAGS) $(LIBPATHS) \
		"$(BUILD)/obj/action.o" \
		"$(BUILD)/obj/alloc.o" \
		"$(BUILD)/obj/auth.o" \
		"$(BUILD)/obj/cgi.o" \
		"$(BUILD)/obj/crypt.o" \
		"$(BUILD)/obj/file.o" \
		"$(BUILD)/obj/fs.o" \
		"$(BUILD)/obj/http.o" \
		"$(BUILD)/obj/js.o" \
		"$(BUILD)/obj/jst.o" \
		"$(BUILD)/obj/options.o" \
		"$(BUILD)/obj/osdep.o" \
		"$(BUILD)/obj/rom.o" \
		"$(BUILD)/obj/route.o" \
		"$(BUILD)/obj/runtime.o" \
		"$(BUILD)/obj/socket.o" \
		"$(BUILD)/obj/time.o" \
		"$(BUILD)/obj/upload.o" \
		"$(BUILD)/obj/web-ext.o" \
		$(LIBPATHS_40) $(LIBS_40) $(LIBS_40) $(LIBS) 

上面的步骤做完后,执行

CC=arm-linux-gnueabihf-gcc AR=arm-linux-gnueabihf-ar make -j16

指令即可将 web-ext.h/web-ext.c 中的函数功能加入到 libgo.so 中。

上述步骤,亲测可用,供学习交流。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硬核老骆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值