Могу ли я использовать директивы препроцессора в файле .ld? Мне нужно использовать один из двух наборов файлов .ld, и я хочу, чтобы движок сборки решал это с помощью макроса. Могу ли я это сделать?

5
Kunal 3 Мар 2015 в 19:42

3 ответа

Лучший ответ

Да, ты можешь. Вам нужно вручную запустить препроцессор для вашего сценария компоновщика, например:

in="your_linker_script.ld"
out="generated_script.ld"
cflags=-Iinclude/

gcc -E -x c $cflags $in | grep -v '^#' >$out

Флаги:

  • -E указывает GCC для запуска только препроцессора
  • -x c указывает GCC обрабатывать ваш скрипт компоновщика как исходный файл C (он необходим для запуска GCC с вашим скриптом LD)

Или вы можете просто использовать инструмент cpp, который на самом деле является препроцессором C.

После этого вы сможете использовать сгенерированный скрипт компоновщика для сборки вашей программы (например, в Makefile).

Примере

Вот как я решил эту проблему в своем проекте:

  1. Вот мой скрипт компоновщика использует препроцессор ({ Директива {X0}} и константа CONFIG_TEXT_BASE). Отрывок:

    #include <config.h>
    
  2. Здесь скрипт для создания предварительно обработанный скрипт компоновщика. Отрывок:

    gcc -E -x c -Iinclude $cflags $in | grep -v '^#'    >>$out
    
  3. Вот мой Makefile, он генерирует предварительно обработанный компоновщик сценарий в целевом объекте $(LDS_GEN) (строка 53), и этот сгенерированный сценарий используется для построения двоичного файла результата (строка 42). Отрывок:

    $(LDS_GEN): $(LDS)
            build/gen-lds.sh $(LDS) $(LDS_GEN) $(CFLAGS)
    
    $(APP).bin: $(OBJS) $(LDS_GEN)
            $(LD) $(OBJS) -T $(LDS_GEN) -o $(APP).elf
    
10
Sam Protsenko 31 Май 2019 в 14:12

Небольшое обновление спустя долгое время. Этот способ предварительной обработки работает до тех пор, пока файл памяти не будет содержать строк, вводящих в заблуждение препроцессор. Например.:

"KEEP(*path/*.o(.rodata .rodata*))"

Символ «/ *» после пути считается началом комментария (строка содержит то, что считается началом многострочного комментария C, а не шаблоном соответствия).

Эта строка действительна для компоновщика, но считается комментарием, и вывод препроцессора C удалит все, пока не будет найден предполагаемый закрывающий комментарий:

"KEEP(*path"

Полученный файл явно недействителен для компоновщика. На данный момент у меня нет решения.

0
AlSavi 31 Июл 2020 в 14:23

Чтобы упростить ответ Сэма, я добавил следующее в свой make-файл, и мы пошли :)

PRE_LD_FILE = $(PROG_NAME).ld
LD_FILE = $(PROG_NAME)_generated.ld

$(LD_FILE) : $(PRE_LD_FILE)
    cpp $(PRE_LD_FILE) | grep -v '^#'   >>$(LD_FILE)
0
Joel Roberts 30 Дек 2019 в 13:22