2016-03-04 98 views
0

是否存在GNU LD链接器命令语言的条件语句?链接器命令语言的条件语句LD

背景:我正在开发用于arm cortex m0 +的固件,它由bootloader和一个应用程序组成。两者都在单独的项目中进行编译和闪存,但是我使用了一个带有驱动程序,makefile和加载程序脚本的符号链接的框架,以便我可以为每个应用程序重复使用这些应用程序,而无需为每个应用程序复制这些文件。 目前我有两个装载文件,引导程序和应用程序(生成文件自动指定相应的一个),内存分配新建分配FY如下:

引导程序

MEMORY { 
    flash (rx) : ORIGIN = 0x00000000, LENGTH = 16K 
    ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K 
} 

应用

MEMORY { 
    flash (rx) : ORIGIN = 0x00004000, LENGTH = 112K 
    ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K 
} 

和makefile一样,我想把它们合并成类似的东西(使用C表达式来阐明)

MEMORY { 
#ifdef(bootloaderSymbol) 
    flash (rx) : ORIGIN = 0x00000000, LENGTH = 16K 
#else 
    flash (rx) : ORIGIN = 0x00004000, LENGTH = 112K 
#endif 
    ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K 
} 
+0

检查出一些Linux内核连接器脚本的。它们大量宏观化,并且始终是GCC和Binutils可以做的各种疯狂事情的​​一个很好的例子。 –

回答

0

虽然它不是它的主要目的,你可以随时在你的链接脚本运行C预处理 (CPP):

#if defined(MACHINE1) 
# define TARGET_ADDRESS 0x80000000 
# define SDRAM_START xxx 
# define SDRAM_SIZE yyy 
# define ROMFLAGS rx 
#elif defined(MACHINE2) 
# define TARGET_ADDRESS 0x40000000 
# define SDRAM_START zzz 
# define SDRAM_SIZE aaa 
# define ROMFLAGS rwx 
#else 
# error unknown machine 
#endif 

MEMORY 
{ 
    rom (ROMFLAGS) : ORIGIN = TARGET_ADDRESS, LENGTH = 0x00100000 
    ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00200000, LENGTH = 0x00100000 
    driver_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00100000, LENGTH = 0x00100000 
} 

... 

你只需要确保您的宏不冲突链接器脚本语法。然后保存您的链接描述为xxx.lk.in(而不是xxx.lk)和一个配方添加到您的Makefile:

xxx.lk: xxx.lk.in 
     $(CPP) -P $(INCLUDE) -D$(MACHINE) $< [email protected] 

所有剩下要做的就是xxx.lk作为依赖添加到您的最终可执行文件建立配方。我在许多项目中成功地使用了类似的流程。

+0

此方法奏效!此外,我还引入了以下技巧:1.将-P添加到预处理器的调用中,以便抑制行号输出。否则,我使用的连接器(arm-none-eabi-ld)不接受处理后的脚本。 2.我将FORCE作为伪依赖项添加到依赖项中,因为您可以在不编辑xxx.lk.in的情况下更改MACHINE,这将不会触发对xxx.lk的重新处理。但是,显然,更改MACHINE正是您为什么要替换xxx.lk的原因。 – joop

+0

@joop:我用includefiles处理的方式。不是直接在链接描述文件中定义宏,而是根据'MACHINE'来包含单独的定义文件。谨慎一点,这些都可以用我可以(重新)使用它们的方式写成“真实的”。C包括只有一个地方关心平台特色。忘了提及'-P'开关,很高兴你自己找到了。 – mfro

+0

没有足够的信誉来支持这个答案,但是也将所有内容都放在头文件中,正是我需要的! – joop

0

我之前已经走过了这条路,后来发现有一个ld命令行参数可以指定段的原点,这样可以减少在链接器脚本中找出它的必要性。从手册页:

-Tbss=org 
    -Tdata=org 
    -Ttext=org 
     Same as --section-start, with ".bss", ".data" or ".text" as the section name. 

所以你的情况,你会-Ttext = 0(引导程序)或-Ttext = 0x00004000(APP)

+0

所以,如果我理解正确的是我现在所拥有的 'MEMORY { 闪光灯(RX):ORIGIN = FLASH_ORG,长度= FLASH_LEN }' 'SECTIONS { 向量:{ *(矢量) }>闪存' 将成为LD的调用,不包含链接描述文件,而是 '-Tvectors = 0x0' ? – joop

+0

是的。这也会起作用。但是,请注意它不是(完全)同一件事。 'MEMORY'允许你告诉链接器定义区域之外的内存不是物理可用的。如果您尝试在定义区域外生成代码,您将收到错误消息。对于段起始地址,您不会(仅当它们重叠时)。如果你的代码最终超出了你的设备的极限,那么'MEMORY'可以避免头痛。 – mfro