Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2974237
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: 嵌入式

2014-11-28 15:25:56

原文地址:http://blog.chinaunix.net/uid-23780428-id-4367351.html

include $(INCLUDE_DIR)/package.mk一般在软件包的基本信息完成后再引入,他定义了用户态软件包的规则。
             编译包分为用户态和内核模块,用户态软件包使用Package,内核模块使用KernelPackage。“$(INCLUDE_DIR)/kernel.mk”文件对于软件包为内核时不可缺少,“$(INCLUDE_DIR)/package.mk”应用在用户态。接下来讲述用户态软件包。
用户程序的编译包以“Package/”开头,然后接着软件名,在Package定义中的软件名可以与软件包名不一样,而且可以多个定义。
2.2.3、第19行”define Package/luci-app-szloogson

     包的名称为”luci-app-szloogson“。

     接下来定义的包括:

        SECTION:包的类型,预留。

        CATEGORY:分类,在menuconfig的菜单下将可以找到。

     SUBMENU:包在make menuconfig的位置,此处即在”LuCi/3. Applications“下。

        TITLE:用于软件包的简短描述,将显示在”make menuconfig“中。

        DESCRIPTION:用于软件包的详细描述,已放弃使用。如果使用DESCRIPTION将会提示“error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description”。

        URL:软件包的下载位置。

        MAINTAINER:维护者选项。

        DEPENDS:与其他软件的依赖。即如编译或安装需要其他软件时需要说明。如果存在多个依赖,则每个依赖需用空格分开。依赖前使用+号表示默认显示,即对象沒有选中时也会显示,使用@则默认为不显示,即当依赖对象选中后才显示。

2.2.4、第27行define Package/luci-app-szloogson/description
        软件包的详细描述,取代前面提到的DESCRIPTION详细描述。此处定义的信息将显示在”make menuconfig“中。
2.2.5、第31行”define Build/Prepare“
        编译准备方法,对于网上下载的软件包不需要再描述。对于非网上下载或自行开发的软件包必须说明编译准备方法。本文所用的准备方法就是首先创建软件包目录,然后将源码拷贝到刚刚创建的目录中。按OpenWrt的习惯,一般把自己设计的程序全部放在src目录下。
2.2.6、第36行"define Build/Configure”
        Build/Configure:在Automake中需要进行“./configure”,所以本配置方法主要针对需要配置的软件包而设计,一般自行开发的软件包可以不在这里说明。本文设计的package由自己写makefile,所以此处没有定义。
2.2.7、第39行”define Build/Compile“
        编译方法,没有特别说明的可以不予以定义。如果不定义将使用默认的编译方法Build/Compile/Default
        自行开发的软件包可以考虑使用下面的定义:

点击(此处)折叠或打开

  1. define Build/Compile
  2.    $(MAKE) -C $(PKG_BUILD_DIR) \
  3.      $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I$(LINUX_DIR)/include"
  4. Endef
        本文此处指定了交叉编译器和体系结构。
2.2.8、第46行”define Package/luci-app-szloogson/install“
        软件包的安装方法,包括一系列拷贝编译好的文件到指定位置。调用时会带一个参数,就是嵌入系统的镜像文件系统目录,因此$(1)表示嵌入系统的镜像目录。一般可以采用下面的方法:

点击(此处)折叠或打开

  1. define Package/luci-app-szloogson/install
  2.     $(INSTALL_DIR) $(1)/usr/bin
  3.     $(INSTALL_BIN) $(PKG_BUILD_DIR)/gsc3280_led $(1)/usr/sbin/
  4. endef
        
   INSTALL_DIR、INSTALL_BIN在”$(TOPDIR)/rules.mk“文件中定义,所以本Makefile必须引入$(TOPDIR)/rules.mk文件。
        INSTALL_DIR :=install -d -m0755:创建所属用戶可读写、执行,其他用戶可读可执行的目录。
        INSTALL_BIN:=install -m0755:编译好的文件到镜像文件目录。
        安装文件放在files子目录下,不要与源代码文件目录“src”混在一起,以提高可读性。 
        如果用户态软件在boot时要自动运行,则需要在安装方法说明中增加自动运行的脚本文件安装和配置文件安裝方法。
        例如:

点击(此处)折叠或打开

  1. define Package/luci-app-szloogson/install
  2.     #install shell
  3.     $(INSTALL_DIR) $(1)/etc/init.d
  4.     $(INSTALL_BIN) ./files/loogson.init $(1)/etc/init.d/loogson
  5.     #install config
  6.     $(INSTALL_DIR) $(1)/etc/config
  7.     $(INSTALL_CONF) ./files/loogson.config $(1)/etc/config/loogson
  8. endef

        使用清晰的文件扩展名,更方便安裝识别文件。
        Package/$(PKG_NAME)/preinst
        软件包安装前处理方法,使用脚本语言,因此定义的第一行需要下面的格式
     #!/bin/sh:调用时带入的参数为嵌入式系统的镜像目录。
     Package/$(PKG_NAME)/postinst:软件包安装后处理方法,使用脚本语言。
     Package/$(PKG_NAME)/prerm:软件包删除前处理方法,使用脚本语言
     Package/$(PKG_NAME)/postrm:软件包删除后处理方法,使用脚本语言
     程序接下来安装luci文件。
2.2.9、第66行”$(eval $(call BuildPackage,luci-app-szloogson))“
     完成前面定义后,必须使用eval函数实现各种定义。其格式为:
     对于一般软件包:$(eval $(call Package,$(PKG_NAME)))
     或对于内核模块:$(eval $(call KernelPackage,$(PKG_NAME)))
     如果一个软件包有多个程序,例如:一个应用程序有自己的内核模块,上面使用的“PKG_NAME”需要灵活变通。eval函数可能设计多个。也可以当成多个软件包处理。
2.2.10、本文没有用到的

     Package/$(PKG_NAME)/conffiles:本包安装的配置文件,一行一个。如果文件结尾使用“/”,则表示为目录。用于备份配置文件说明,在sysupgrade命令执行时将会用到。

2.3、内核模块包定义
     Linux分为内核态和用户态。开发者开发的内核部分可以直接加入Linux的Kernel程序,也可以生成内核模块以便需要时装入内核。OpenWrt一般希望开发者生成内核模块,在Linux启动后自动装载或手工使用insmod命令装载。内核模块使用“KernelPackage”开头,其他与一般软件包基本相同。
     在内核模块定义中增加“SUBMENU”表示子菜单位置,在“$(INCLUDE)/kernel.mk”对内核模块定义了CATEGORY为kernel modules,所以内核模块在menuconfig中的主菜单为kernel modules,然后有下一级子菜单$(SUBMENU)。在子菜单下可以看到以kmod-$( PKG_NAME)项目。
     DEFAULT表示直接编入内核或产生内核模块,y表示直接编入内核,m表示产生内核模块。
     AUTOLOAD表示自动装入内核,一般表示方法为:
     AUTOLOAD:=$(call AutoLoad, $(PRIORITY),$(AUTOLOAD_MODS))
     AutoLoad的第一个参数$(PRIORITY)为优先级,01为最优先,99为最后装载。有关自动装载可以在/etc/modules.d目录下看到,第二个参数$(AUTOLOAD_MODS)模块名,每个模块名以空格符分隔。即可同时装载多个内核模块。
     在开发过程最好不要使用自动装载,需经过严格调试后再使用,可以减轻调试的工作量。
     用户态的软件包中沒有内核模块的“AUTOLOAD”参数。如果软件需要在boot时自动运行,则需要在“/etc/init.d”增加相应的脚本文件。 脚本文件需要START参数,说明在boot时的优先级,如果在boot启动后再启动,则需要STOP参数。如果STOP参数存在,其值必须大于START。由“/etc/rc.d/S10boot”知道,装载内核模块的优先级为10,需要使用自己设计的内核模块的程序其START的值必须大于10。同样由“/etc/rc.d/S40network”知道,使用网络通信的程序其START的值必须大于40。
2.4、脚本文件
     脚本文件需要start()和stop()两个函数,start()是执行程序,stop()是关闭程序。关闭程序一般需要执行killall命令。
     在(一)中我们讨论了点击“应用”后执行的脚本文件在“/etc/init.d/loogson”目录下,程序如下:

点击(此处)折叠或打开

  1. #!/bin/sh /etc/rc.common
  2. (C) 2014 openwrt.org
  3. # add by Davied Huang <apple_guet@126.com>

  4. START=50

  5. LED_BIN="/usr/sbin/gsc3280_led"


  6. control_board()
  7. {
  8.     local ledstatus, lednum;
  9.     
  10.     config_get_bool ledstatus $1 ledstatus
  11.     
  12.     config_get lednum $1 lednum
  13.     
  14.     echo "${lednum} ${ledstatus}"
  15.     ${LED_BIN} ${lednum} ${ledstatus}
  16. }

  17. start() {
  18.     config_load loogson
  19.     config_foreach control_board controlboard
  20. }

  21. stop() {
  22.     config_load loogson
  23.     #config_foreach stop_instance controlboard
  24. }
        说明:
        1) 在“start”函数中,首先使用“config_load”函数加载“/etc/config/”目录下的loogson配置文件。
        2) “config_foreach”遍历"/etc/init.d/loogson"配置文件中的Section,并且执行"control_board"函数。
        3) 在"control_board"函数中,使用“config_get_bool”获得操作LED的开关状态,config_get获得操作第几个LED。
        4) "config_load"、“config_foreach”、“config_get”和“config_get_bool”等函数由其他脚本提供,可以直接使用。
        5) 最后执行可执行文件,后面加上可执行文件需要的参数。该可执行文件的源码为:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<fcntl.h>
  4. #include<asm/ioctl.h>

  5. int main(int argc,char *argv[])
  6. {
  7.     int fd;

  8.     if (argc != 3) {
  9.         printf("wrong cmd!\n");
  10.     }
  11.     fd = open("/dev/led", O_RDWR);
  12.     if(fd == -1){
  13.         printf("open led failed!\n");
  14.     }
  15.     ioctl(fd, argv[1], argv[2]);    
  16.         
  17.     close(fd);
  18.     return 0;
  19. }
三、参考资料
        官方说明文档: http://luci.subsignal.org/trac/wiki/Documentation
        LuCI上配置Makefile: http://luci.subsignal.org/trac/wiki/Documentation/Modules
        CBI文档: http://luci.subsignal.org/trac/wiki/Documentation/CBI
        Luci模块说明文档: http://luci.subsignal.org/trac/wiki/Documentation/ModulesHowTo
        Luci类库的函数定义和使用说明: 
        UCI接口在脚本文件中的官方说明: http://wiki.openwrt.org/doc/devel/config-scripting

阅读(4023) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~