AliOS-Things--EMW3060--nano--新增一個新模組
https://github.com/alibaba/AliOS-Things/wiki/Add-a-new-component-example.zh
一、新增一個元件:info_a
架構簡介
|----AliOS-Things
|----example
| |----nano # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a元件
| | |----nano.c
| | |----nano.h
| | |----nano.mk
| |......
|----framwork
|----info_a # framwork目錄下的新元件,有.mk檔案
| |----info_a.c
| |----info_a.h
| |----info_a.mk
|......
nano例程是最簡單的工程:它的路徑在AliOS-Things\example\nano\nano.c
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <aos/aos.h>
static void app_delayed_action(void *arg)
{
printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name());
}
int application_start(int argc, char *argv[])
{
do
{
app_delayed_action(NULL);
aos_msleep(1000);
}while( 1);
}
增加一個新模組供現有的app呼叫,執行檢視結果。 nano是aos自帶的一個最簡單的app例子,它實現了最簡單的延時迴圈列印功能,我們用它來作為例子中所用的app。 新增模組名設為 info_a,功能是列印一條特定的資訊。
在framework下建立一個 info_a 目錄。
1.增加新模組原始檔
在 info_a 目錄中建立 info_a.c :
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
void info_a_fun()
{
printf("this is in info_a\n");
}
2.增加新模組的對外標頭檔案
在 info_a 目錄中建立 info_a.h :
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef INFO_A_H
#define INFO_A_H
#ifdef __cplusplus
extern "C" {
#endif
extern void info_a_fun();
#ifdef __cplusplus
}
#endif
#endif /* INFO_A_H */
3.增加新模組的.mk檔案
.mk檔案是模組存在的標誌。每一個模組都會有一個對應的mk檔案,makefile通過搜尋mk字尾的檔案來查詢模組。其中聲明瞭一些針對該模組的定製化的東西。最基本的兩個就是該模組所包含的原始檔,標頭檔案路徑和該模組依賴的其他模組。
在info_a目錄下建立 info_a.mk:
NAME := info_a
$(NAME)_SOURCES := info_a.c
GLOBAL_INCLUDES += .
4.修改 nano 原始檔呼叫新介面
如:
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <aos/aos.h>
#include "info_a.h"
static void app_delayed_action(void *arg)
{
printf("%s:%d %s\r\n", __func__, __LINE__, aos_task_name());
info_a_fun();
}
int application_start(int argc, char *argv[])
{
do
{
app_delayed_action(NULL);
aos_msleep(10);
}while(1);
}
5. 修改 nano的 .mk 檔案依賴新模組
在nano.mk中新增一行:
$(NAME)_COMPONENTS += info_a
坑一:找不到標頭檔案
example/nano/nano.c:7:10: fatal error: info_a.h: No such file or directory
#include <info_a.h>
^~~~~~~~~~
那好,我改:
我把#include <info_a.h>
改成#include <../framework/info_a/info_a.h>
標頭檔案,直接通過絕對目錄來指定標頭檔案的地方。嘚,沒報錯了,說明這是可以解決的。
不過又出現了新的問題:
out/[email protected]/libraries/nano.a(nano.o): In function `app_delayed_action':
D:\Output\AliOS\AliOS-Things/example/nano/nano.c:12: undefined reference to `info_a_fun'
函式info_a_fun沒有找到?抱歉,標頭檔案都沒報錯了,標頭檔案裡面有的函式你居然說找不到!再仔細找!
靠!!!nano.mk裡面寫錯了!
原有的沒改的,按照文件,我要在裡面新增一句:$(NAME)_COMPONENTS += info_a
NAME := nano
$(NAME)_SOURCES := nano.c
GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP
mesh ?= 0
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif
然後,我就改成了以下這種錯誤的了!
NAME := nano
$(NAME)_SOURCES := nano.c
GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP
mesh ?= 0
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks \
info_a # 注意不能在這裡加啊!!
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif
正確的mk
NAME := nano
$(NAME)_SOURCES := nano.c
$(NAME)_COMPONENTS += info_a # 正確的做法是要在這新增啊!
GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP
mesh ?= 0
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif
- 再編譯,我的標頭檔案還是這麼寫的
#include <../framework/info_a/info_a.h>
,編譯通過! - 那我改改標頭檔案
#include <info_a/info_a.h>
,編譯失敗! - 再改檔案
#include <info_a.h>
,編譯成功!
新增一個新模組的總結
1、新模組的C檔案、H檔案、mk檔案缺一不可!
2、呼叫模組時,工程裡面的mk檔案一定要新增模組那啥!$(NAME)_COMPONENTS += info_a
3、標頭檔案的包含方式就兩種:
(1)絕對路徑:#include <../framework/info_a/info_a.h>
(2)單獨標頭檔案:#include <info_a.h>
二、再新增一個元件:info_b
架構簡介
|----AliOS-Things
|----example
| |----nano # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a、info_b元件
| | |----nano.c
| | |----nano.h
| | |----nano.mk
| |......
|----framwork
|----info_a # framwork目錄下的新元件a,有.mk檔案
| |----info_a.c
| |----info_a.h
| |----info_a.mk # 通過在這裡面新增關係,來帶出info_b元件
|----info_b # framwork目錄下的新元件b,有.mk檔案
| |----info_b.c
| |----info_b.h
| |----info_b.mk
|......
使用同樣的方法新增一個info_b資料夾
- info_b.c
- info_b.h
- info_b.mk
info_b.c
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
void info_b_fun()
{
printf("this is in info_b\n");
}
info_b.h
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef INFO_B_H
#define INFO_B_H
#ifdef __cplusplus
extern "C" {
#endif
extern void info_b_fun();
#ifdef __cplusplus
}
#endif
#endif /* INFO_A_H */
info_b.mk
NAME := info_b
$(NAME)_SOURCES := info_b.c
GLOBAL_INCLUDES += .
好的,新元件b又做好了。
現在想讓元件b“依附”在元件a上面,即,nano工程只需要#include "info_a.h"
就可以呼叫元件b的info_b_fun()
函式。只需要在info_a.mk裡面寫:
NAME := info_a
$(NAME)_SOURCES := info_a.c
$(NAME)_COMPONENTS += info_b # 新增這個依賴就可以了
GLOBAL_INCLUDES += .
如下就可以編譯了
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <aos/aos.h>
#include <info_a.h> // 沒有info_b.h的標頭檔案
static void app_delayed_action(void *arg)
{
printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name());
info_b_fun(); // 卻可以呼叫info_b裡面的元件
}
int application_start(int argc, char *argv[])
{
do
{
app_delayed_action(NULL);
aos_msleep(1000);
}while(1);
}
三、再再新增一個元件:info_c/info_c_a
架構簡介
|----AliOS-Things
|----example
| |----nano # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a、info_b元件
| | |----nano.c
| | |----nano.h
| | |----nano.mk
| |......
|----framwork
|----info_a # framwork目錄下的新元件a,有.mk檔案
| |----info_a.c
| |----info_a.h
| |----info_a.mk # 通過在這裡面新增關係,來帶出info_b元件
|----info_b # framwork目錄下的新元件b,有.mk檔案
| |----info_b.c
| |----info_b.h
| |----info_b.mk
|----info_c # 該目錄中沒有.mk檔案,它的子目錄中有.mk檔案(加了一層)
| |----info_c_a
| | |----info_c_a.c
| | |----info_c_a.h
| | |----info_c_a.mk
| |----info_c_b # 更多的新元件
| |.......
|......
檔案還是老三樣(寫法和元件a的幾乎一模一樣就是,名字加了"_c"):
- info_c_a.c
- info_c_a.h
- info_c_a.mk
就是元件在其他目錄之下,那麼在nano工程中該怎麼呼叫呢?
首先nano.mk得這麼寫:
NAME := nano
$(NAME)_SOURCES := nano.c
$(NAME)_COMPONENTS += info_c/info_c_a # info_c裡面沒有.mk檔案所以....
GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP
mesh ?= 0
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif
然後,nano.c裡面include標頭檔案就可以直接使用了
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <aos/aos.h>
#include <info_c_a.h> // 新元件c的標頭檔案
static void app_delayed_action(void *arg)
{
printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name());
info_c_a_fun(); // 新元件c裡面的函式
}
int application_start(int argc, char *argv[])
{
do
{
app_delayed_action(NULL);
aos_msleep(1000);
}while(1);
}
四、總結
把這幾種型別的元件全部試用一次,就可以大致瞭解到AliOS-Things的檔案依賴與呼叫,包括.mk檔案的寫法就沒那麼迷糊了,還有就是大型的C工程裡面包含標頭檔案的寫法也是頭痛,經過以上的實驗之後,好像有那麼點清楚了。