python怎么进行宏定义_应用程序命令行宏定义方式实现

本文介绍了如何在C程序中模仿u-boot的命令行宏定义方式,通过自定义lds文件实现类似功能。步骤包括生成lds文件、在Makefile中指定链接脚本、在SECTIONS中添加新的段定义,以及理解elf文件格式和连接脚本的作用。
摘要由CSDN通过智能技术生成

应用程序命令行宏定义方式实现

在u-boot开发过程中,发现u-boot命令添加非常方便,在任何编译的.c文件里面增加u_boot_CMD类似的一个命令定义,并实现命令函数,就能在命令行执行该命令。对于这点一直觉得很神奇,也按照这个格式增加了很多命令,但不知道怎么实现的。

现在想自己写个控制台程序,也想使用这种方式方便增加自己的命令,于是参照u-boot研究了一下。发现u-boot宏定义了一个“.u_boot_cmd”的Section,在command.h文件:

extern cmd_tbl_t __u_boot_cmd_start;

extern cmd_tbl_t __u_boot_cmd_end;

#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))

在u-boot.lds文件又有这段描述:

. = .;

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

看起来,__u_boot_cmd_start和__u_boot_cmd_end是在lds文件里面定义出来的,所以命令结构通过预处理,存放到了“.u_boot_cmd”的Section里面。

那么在应用程序中,如何通过lds文件实现上述功能?

步骤:

1) 生成lds文件,方法:

ld --verbose得到默认的ld script

去掉头部和尾部,这里保存为cmd.ld文件。注意:如果arm交叉编译的话,ld前面要加 arm-linux-ld --verbose > cmd.lds

生成的lds文件有头,不符合lds文件语法,需要屏蔽掉。

2) 在Makefile中通过:

$(GCC) -T$(LDSCRIPT) -o $@ $^

指定链接时使用的lds文件,如果不指定则用默认的lds文件;

(此步骤,验证生成的lds文件是合法的,起到作用的)

3)在SECTIONS增加新的端定义,添加位置在

__bss_start = .;

__bss_start__ = .;之前

. = .;

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;    -T指定连接文件,这样“u_boot_cmd”Section就生效了

gcc等编译器内置有缺省的连接脚本。如果采用缺省脚本,则生成的目标代码需要操作系统才能加载运行。为了能在嵌入式系统上直接运行,需要编写自己的连接脚本文件。编写连接脚本,首先要对目标文件的格式有一定了解。GNU编译器生成的目标文件缺省为elf格式。elf文件由若干段(section)组成,如不特殊指明,由C源程序生成的目标代码中包含如下段:.text(正文段)包含程序的指令代码;.data(数据段)包含固定的数据,如常量、字符串;.bss(未初始化数据段)包含未初始化的变量、数组等。C++源程序生成的目标代码中还包括.fini(析构函数代码)和.init(构造函数代码)等。有关elf文件格式,读者可自行参考相关资料。连接器的任务就是将多个目标文件的.text、.data和.bss等段连接在一起,而连接脚本文件是告诉连接器从什么地址开始放置这些段。例如笔者的引导程序连接文件link.lds为:

ENTRY(begin)

SECTION

{ .=0x00300000;

.text : { *(.text) }

.data: { *(.data) }

.bss: { *(.bss) }

}

其中,ENTRY(begin)指明程序的入口点为begin标号;.=0x00300000指明目标代码的起始地址为0x00300000,这一段地址为MX1的片内RAM;.text : { *(.text) }表示从0x00300000开始放置所有目标文件的代码段,随后的.data: { *(.data) }表示数据段从代码段的末尾开始,再后是.bss段。

注意makefile:

all:后面跟的是要生成的目标文件。all可以有一个或者多个目标文件。

all: $(TARGET)

%.o:%.c

$(CC) -c $(CFLAGS) $< -o $@

$(TARGET):  main.o console.o command.o cmd_date.o

# $(GCC) $(CFLAGS) -o $@ $^

$(GCC) -T$(LDSCRIPT) -o $@ $^

all是个伪目标,是所有目标的目标,其功能是编译所有的目标。

如果makefile中不写all的话,则默认遇到makefile中第一个目标为默认目标。

C/C++ code.PHONY:all

all:prog1 prog2 prog3 prog4

要编译prog1 prog2 prog3 prog4 四个目标,我们可以使用 make all 命令来编译所有的目标。

也可以 make prog3单独编译 prog3 目标。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值