2016-03-04 31 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