Компиляция файлов .c и .s из разных подкаталогов

Вот мой make-файл http://pastie.org/1104332. Я пытаюсь скомпилировать разные файлы .c и файлы .s (файлы сборки) из разных подкаталогов в E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/, тогда компоновщик должен связать все файлы .o из каталога сборки (E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680) в файл с именем mfg-sample-app.out. Когда я запускаю make-файл, который я разместил выше, компилятор компилирует все исходные файлы в объектные файлы в каталоге сборки, но компоновщик не может открыть объектные файлы, потому что он не ищет их в каталоге сборки, который находится в E:/em35x/ build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680. Я не знаю, почему линкер не смотрит туда? это ошибка, которую я получаю:

E:\IARSystems\EmbeddedWorkbench5.4Evaluation\arm\bin\ilinkarm.exe"      -o E:/e
m35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/mfg-sample-app.out --
map E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/mfg-sample-ap
p.map --log initialization,modules,sections,veneers --log_file E:/em35x/build/mf
g-sample-app-cortexm3-iar-em357-em3xx-dev0680/mfg-sample-app.log --config E:/em3
5x/app/mfglib/ewb-em357/../../../hal/micro/cortexm3/em35x/em357/iar-cfg.icf --di
ag_suppress Lp012 --entry halEntryPoint  E:/em35x/build/alarm-library-cortexm3-i
ar-em357-em3xx/alarm-library.a E:/em35x/build/binding-table-stub-library-cortexm
3-iar-em357-em3xx/binding-table-stub-library.a  E:/em35x/build/cbke-stub-library
-cortexm3-iar-em357-em3xx/cbke-stub-library.a E:/em35x/build/end-device-bind-stu
b-library-cortexm3-iar-em357-em3xx/end-device-bind-stub-library.a  E:/em35x/buil
d/hal-library-cortexm3-iar-em357-em3xx/hal-library.a E:/em35x/build/mfglib-libra
ry-cortexm3-iar-em357-em3xx/mfglib-library.a  E:/em35x/build/security-library-co
re-cortexm3-iar-em357-em3xx/security-library-core.a E:/em35x/build/security-libr
ary-link-keys-stub-cortexm3-iar-em357-em3xx/security-library-link-keys-stub.a E:
/em35x/build/zigbee-pro-stack-cortexm3-iar-em357-em3xx/zigbee-pro-stack.a E:/em3
5x/app/mfglib/mfg-sample.o E:/em35x/hal/ember-configuration.o E:/em35x/hal/micro
/cortexm3/adc.o E:/em35x/hal/micro/cortexm3/bootloader-interface-app.o E:/em35x/
hal/micro/cortexm3/bootloader-interface-standalone.o E:/em35x/hal/micro/cortexm3
/bootloader-interface.o E:/em35x/hal/micro/cortexm3/button.o E:/em35x/hal/micro/
cortexm3/buzzer.o E:/em35x/hal/micro/cortexm3/cstartup-iar-common.o E:/em35x/hal
/micro/cortexm3/diagnostic.o E:/em35x/hal/micro/cortexm3/led.o E:/em35x/hal/micr
o/cortexm3/mfg-token.o E:/em35x/hal/micro/cortexm3/micro-common.o E:/em35x/hal/m
icro/cortexm3/micro.o E:/em35x/hal/micro/cortexm3/sleep.o E:/em35x/hal/micro/cor
texm3/token-def.o E:/em35x/hal/micro/cortexm3/token.o E:/em35x/hal/micro/cortexm
3/uart.o E:/em35x/hal/micro/generic/crc.o E:/em35x/hal/micro/generic/endian.o E:
/em35x/hal/micro/generic/mem-util.o E:/em35x/hal/micro/generic/random.o E:/em35x
/hal/micro/generic/sim-eeprom.o E:/em35x/app/util/serial/cli.o E:/em35x/app/util
/serial/serial.o E:/em35x/hal/micro/cortexm3/em35x/mpu.o E:/em35x/hal/micro/cort
exm3/faults.o E:/em35x/hal/micro/cortexm3/isr-stubs.o

   IAR ELF Linker V5.50.5.51995/W32 for ARM
   Copyright (C) 2007-2010 IAR Systems AB.
Fatal error[Li001]: could not open file "E:\em35x\app\mfglib\mfg-sample.o"
Fatal error detected, aborting.
make: *** [mfg-sample-app.out] Error 3

(сначала он компилирует исходные файлы, но в конце не может найти объектные файлы в папке сборки)

Теперь, после того, как я удалю строку 70 из файла makefile, который

OBJ = $(SRC:.c=.o) E:/em35x/hal/micro/cortexm3/faults.o E:/em35x/hal/micro/cortexm3/isr-stubs.o

тогда компоновщик может найти предыдущие скомпилированные объектные файлы в каталоге сборки и создать файл .out. И если я вручную удалю все объектные файлы из каталога сборки (который компилятор создал ранее) и снова запущу makefile (строка 70 все еще удалена), то я получаю эту ошибку:

$ make
make: *** No rule to make target `E:/em35x/build/mfg-sample-app-cortexm3-iar-em3
57-em3xx-dev0680/mfg-sample.o', needed by `mfg-sample-app.out'.  Stop.

И если я снова добавлю строку 70, которая:

OBJ = $(SRC:.c=.o) E:/em35x/hal/micro/cortexm3/faults.o E:/em35x/hal/micro/cortexm3/isr-stubs.o

затем он снова компилируется, но не связывается, потому что не может открыть объектные файлы. (Снова первая упомянутая ошибка)

Я не знаю, что я делаю неправильно. Я пробовал много вещей, но не могу найти свою проблему.

Спасибо

EDIT: я использую GNU Make 3.81

изменили предпоследнюю строку на:

$(END_DIR)/%.o : %.c

и я также внес изменения в VPATH, как было предложено Жилем, но безуспешно.

Теперь я получаю эту ошибку:

$ make
make: *** No rule to make target `E:/em35x/build/mfg-sample-app-cortexm3-iar-em3
57-em3xx-dev0680/mfg-sample.o', needed by `mfg-sample-app.out'.  Stop.

Он не компилирует какой-либо файл .c в файл .o.

EDIT: Бета, я смогу протестировать ваши линии в понедельник. Затем я сообщу о результатах, я хочу решить эту проблему, она сводит меня с ума. Спасибо

ИЗМЕНИТЬ:

Привет Бета,

Я все еще получаю ту же ошибку с кодом, который вы предложили. Это ошибка, если mfg-sample.o отсутствует в папке сборки (E:/em35x/build/mfg-sample-app-cortexm3-iar-em3 57-em3xx-dev0680):

tjoyia@TJ-PC /e/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680
$ make
make: *** No rule to make target `E:/em35x/build/mfg-sample-app-cortexm3-iar-em3
57-em3xx-dev0680/mfg-sample.o', needed by `mfg-sample-app.out'.  Stop.

Но если mfg-sample.o уже существует в папке сборки (после того, как я скомпилировал mfg-sample.c с mfg-sample.o), я получаю это сообщение:

tjoyia@TJ-PC /e/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680
$ make
found E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/mfg-sample.
o, making mfg-sample-app.out

ИЗМЕНИТЬ:

Привет, бета. Да, это сработало.

Я получил это сообщение:

tjoyia@TJ-PC /e/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680
$ make
found E:/em35x/app/mfglib/mfg-sample.c, making E:/em35x/build/mfg-sample-app-cor
texm3-iar-em357-em3xx-dev0680/mfg-sample.o
found E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/mfg-sample.
o, making mfg-sample-app.out

Итак, что мне теперь делать в моем исходном make-файле? Я хочу скомпилировать весь свой проект и связать объектные файлы (все мои файлы .c в разных местах пути в папку сборки, а затем компоновщик должен связать ранее созданные файлы .o в файл .out)

ИЗМЕНИТЬ:

Привет Бета,

Хорошо, у меня это работает, но как насчет двух файлов .s79, как я могу их также скомпилировать в объектные файлы в каталоге сборки? Почему VPATH не работает, и я думаю, что мое создание файла зависимостей (.d) не вызывается, как я могу вызвать его. Я хочу, чтобы все файлы .h (инструкции #include в исходных файлах) автоматически распознавались и зависели от объектного файла.

И после этого я хочу преобразовать файлы .out, но они не вызываются.

Вот проблема:

Знаете ли вы, как я могу добавить это в свой make-файл:

ielftool.exe --srec --verbose E:\em35x\build\mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680\mfg-sample-app.out E:\em35x\build\mfg-sample- приложение-cortexm3-iar-em357-em3xx-dev0680\mfg-sample-app.s37

Он должен преобразовать файл mfg-sample-app.out в mfg-sample-app.s37 после того, как файл .out будет создан/слинкован из объектных файлов.


person billz    schedule 20.08.2010    source источник


Ответы (3)


Во-первых, эта ссылка указывает не на make-файл, а на результат вашей попытки запустить make. Во-вторых, я не вижу доказательств того, что это действительно произвело mfg-sample-app.o, но вы говорите, что это произошло, так что я поверю вам на слово.

Есть несколько разных вещей, которые могут вызывать эту ошибку. Я предлагаю вам восстановить строку 70, начать с чистого листа и выполнить make дважды. Я думаю, что есть хороший шанс, что он создаст объектные файлы на первом проходе и найдет их на втором. И что бы он ни делал, мы чему-то научимся. (Я бы посоветовал вам также перейти на более авторитетный компилятор/компоновщик, такой как gcc, но похоже, что он использует некоторые флаги нестандартным образом.)

Вторую ошибку легко понять: вы удалили строку, определяющую список объектов, и правило было определено в терминах этого списка, поэтому Make больше не знал, как создавать эти объекты. Но меня пугает, что Make знал, как вызывать компоновщик без этого списка; это говорит о том, что в вашем make-файле много избыточности, что плохо.

Кстати, какую марку вы используете? Попробуйте запустить make -v и посмотрите, что там написано.

EDIT:
Теперь, когда я могу взглянуть на make-файл, я думаю, что могу прояснить эту загадку.

Исходный файл, о котором идет речь, E:/em35x/app/mfglib/mfg-sample.c. Имея строку 70, Make просто меняет .c на .o и делает вывод, что рассматриваемый объектный файл - E:/em35x/app/mfglib/mfg-sample.o. Но вы жестко запрограммировали путь к каталогу сборки во флагах компилятора (очень плохая практика), так что именно туда идут файлы объектов. Затем, когда Make доходит до этапа компоновки, он не может найти E:/em35x/app/mfglib/mfg-sample.o и умирает.

Когда вы запускаете без строки 70, она использует более раннюю строку и заключает, что mfg-sample.o должна быть в каталоге сборки. Если этот объектный файл уже существует до запуска, Make связывает объектные файлы вместе, и все в порядке. Но если файла нет, то Make не может его собрать, потому что этот makefile знает только один способ построить объектный файл, а именно путем компиляции исходного кода, который находится в том же каталоге, где он намеревается построить объект< /эм>. Поскольку такого исходного файла в каталоге сборки нет, он умирает.

Этот make-файл может потребовать много работы, но вот самое маленькое изменение, которое (вероятно) решит вашу проблему. (Вы не сказали, какую версию Make вы используете — это работает для GNUMake.) Избавьтесь от строки 70 и измените предпоследнюю строку:

$(END_DIR)/%.o : %.c

Теперь независимо от того, куда, по мнению Make, должен поместиться объектный файл, он будет искать исходный файл без пути (mfg-sample.c), а VPATH найдет его.

P.S. Жиль указал, что разделитель в VPATH может не работать в Windows. Если предложенное мной изменение не работает, попробуйте также изменить разделитель, как предлагает Жиль (изменение только разделителя не поможет).

EDIT:
Похоже, что VPATH не работает. Мы можем обойтись без него, но я хотел бы провести последний эксперимент, прежде чем мы откажемся от него. Пожалуйста, попробуйте это и сообщите нам, что происходит:

END_DIR = E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680

OBJ = $(END_DIR)/mfg-sample.o 

VPATH = E:/em35x/app/mfglib

mfg-sample-app.out : $(OBJ)
  @echo found $<, making $@

$(END_DIR)/%.o : %.c
  @echo found $<, making $@
  @touch $@

РЕДАКТИРОВАТЬ 3:
Хорошо, VPATH не работает — возможно, позже мы сможем выяснить, почему.

Попробуйте это (это может сработать, а может и нет - мне сложно тестировать пути в стиле Windows):

END_DIR = E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680

OBJ = $(END_DIR)/mfg-sample.o 

mfg-sample-app.out : $(OBJ)
  @echo found $<, making $@

$(END_DIR)/mfg-sample.o : E:/em35x/app/mfglib/mfg-sample.c

$(END_DIR)/%.o :
  @echo found $<, making $@
  @touch $@

РЕДАКТИРОВАТЬ 4:

Скрестите пальцы и попробуйте вставить это в ваш настоящий make-файл (и избавиться от строки 70):

$(END_DIR)/mfg-sample.o: E:/em35x/app/mfglib/mfg-sample.c

$(END_DIR)/ember-configuration.o: E:/em35x/hal/ember-configuration.c

CORTEXM3 = adc \
bootloader-interface-app \
bootloader-interface-standalone \
bootloader-interface \
button \
buzzer \
cstartup-iar-common \
diagnostic \
led \
mfg-token \
micro-common \
micro \
sleep \
token-def \
token \
uart

CORTEXM3_OBJS = $(patsubst %,$(END_DIR)/%.o,$(CORTEXM3))
$(CORTEXM3_OBJS): $(END_DIR)/%.o : E:/em35x/hal/micro/cortexm3/%.c

GENERIC = crc \
endian \
mem-util \
random \
sim-eeprom

GENERIC_OBJS = $(patsubst %,$(END_DIR)/%.o,$(GENERIC))
$(GENERIC_OBJS): $(END_DIR)/%.o : E:/em35x/hal/micro/generic/%.c

$(END_DIR)/cli.o $(END_DIR)/serial.o: $(END_DIR)/%.o : E:/em35x/app/util/serial/%.c

$(END_DIR)/mpu.o: E:/em35x/hal/micro/cortexm3/em35x/mpu.c

$(END_DIR)/%.o :
    $(CC) $(CFLAGS) $(INCLUDES) $<

Посмотрите, почему VPATH так удобен?

РЕДАКТИРОВАТЬ 5:

  • The s79 files:

    Изменяем правило (последние две строки EDIT 4):

    # change this:
    #
    # $(END_DIR)/%.o :
    #    $(CC) $(CFLAGS) $(INCLUDES) $<
    
    # to this:
    
    $(END_DIR)/mfg-sample.o \
    $(END_DIR)/ember-configuration.o \
    $(CORTEXM3_OBJS) \
    $(GENERIC_OBJS) \
    $(END_DIR)/cli.o $(END_DIR)/serial.o \
    $(END_DIR)/mpu.o:
        $(CC) $(CFLAGS) $(INCLUDES) $<
    

    (Вы можете поместить эти цели в одну строку, если хотите, я стремился к удобочитаемости.)

    Убедитесь, что это работает, затем добавьте другое правило для источников s79:

    $(END_DIR)/faults.o $(END_DIR)/isr-stubs.o : $(END_DIR)/%.o : E:/em35x/hal/micro/cortexm3/%.s79
        @echo attempting to build $@ from $<
        $(ASM) $(AFLAG) $(AFLAG1) $(AFLAG2) $(AFLAG3) $(AFLAG4) $<
    

    И обязательно добавьте эти два параметра к переменной OBJ, чтобы Make знал, что нужно mfg-sample-app.out.

  • VPATH. I don't know why VPATH isn't working. More investigation is possible, but it's very difficult to do remotely like this. You can try a long shot: in the experimental makefile I suggested (in the second EDIT block) change the VPATH line to this:

    vpath %.c E:/em35x/app/mfglib
    

    (Обратите внимание на нижний регистр.)

  • Dependency files (.d). I don't know whether the commands in the rules work (I don't have access to your "Embedded Workbench" tools), but the reason the rules aren't being invoked is that the include statements use a variable (sources) which is undefined. Make can't find any source files that way, so it doesn't think it has to include anything, so it doesn't think it has to build anything (and couldn't even if it wanted to because it can't find the sources). You can use the SRC variable instead, but don't forget to add in the s79 files.

  • Converting the .out files. Piece of cake:

    E:\em35x\build\mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680\mfg-sample-app.s37 : mfg-sample-app.out
        ielftool.exe --srec --verbose $< $@
    

    (Если вы хотите, чтобы это была ваша цель по умолчанию, поместите ее перед всеми остальными.) Я жестко запрограммировал путь к цели s37, потому что вы указали ее. Вероятно, вы могли бы обойтись только mfg-sample-app.s37.

    person Beta    schedule 20.08.2010
    comment
    ссылку поменяли. Теперь он указывает на make-файл. Пожалуйста, посмотрите на это - person billz; 20.08.2010
    comment
    Я должен использовать этот компилятор для проектов в специальных параметрах флага. - person billz; 20.08.2010
    comment
    Он создает объекты только тогда, когда строка 70 не пропущена, и переопределяет предыдущую переменную OBJ в make-файле. Когда я пропускаю строку 70 и использую переменную OBJ перед строкой 70, тогда она связывает объекты (если они уже созданы в каталоге сборки), если я их удаляю, это дает ошибку, о которой я упоминал во второй части моего вопроса. - person billz; 20.08.2010
    comment
    смогу протестировать в понедельник. Спасибо - person billz; 21.08.2010
    comment
    а что с файлами .s79? - person billz; 24.08.2010

  • У вас есть два определения OBJ. Один явно перечисляет все объекты и говорит, что они находятся в END_DIR, но нет правила создавать объектный файл в одном месте из исходного файла в другом каталоге. Второе правило использует исходные файлы и заменяет .c на .o (при этом объектные файлы будут находиться в том же каталоге, что и исходный код).

    После того как вы удалили второе правило, make использовала первое определение, чтобы определить, где должны находиться объектные файлы для компоновки, но не знала, как их сгенерировать. Это объясняет вторую ошибку. Чтобы исправить это, либо измените правило компиляции, чтобы поместить объектные файлы в другой каталог, либо используйте правило в строке 70, в котором говорится, что они находятся в том же месте, что и исходный код.

    Непонятно, почему не сработал первый проход, но я бы рекомендовал убрать генерацию и включение файлов зависимостей (.d) до тех пор, пока не заработает компиляция. Я обнаружил, что гораздо полезнее создавать их как побочный эффект компиляции, чем создавать их явно. Если их нет, значит, вы ничего не скомпилировали и все равно должны выполнить полную сборку.

    person Kirk Kelsey    schedule 20.08.2010
    comment
    Я не знаю, что именно вы имеете в виду? Что я должен делать? Я хочу скомпилировать исходные файлы (которые находятся в разных подкаталогах) в папке сборки (объектные файлы). Затем компоновщик должен связать все объектные файлы из папки сборки в файл .out. - person billz; 20.08.2010
    comment
    вынос генерации и включение файлов зависимостей (.d) тоже не помогло. - person billz; 20.08.2010

    Компоновщик делает именно то, что ему говорят: ему говорят связать «E:\em35x\app\mfglib\mfg-sample.o», которого не существует.

    Есть проблема с определением VPATH в make-файле: : используется и как индикатор диска DOS/Windows, и как разделитель пути. В Windows необходимо заменить : на ; или пробелами. (Это может нарушить совместимость с другими реализациями make для Unix, возможно, поэтому автор скрипта, сгенерировавшего этот (часть) make-файл, использовал :.)

    VPATH = E:/em35x/app/mfglib/ E:/em35x/hal/ E:/em35x/hal/micro/cortexm3/ E:/em35x/hal/micro/generic/ E:/em35x/app/util/serial/ E:/em35x/hal/micro/cortexm3/ E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/
    
    person Gilles 'SO- stop being evil'    schedule 20.08.2010
    comment
    но mfg-sample.o находится в E:/em35x/build/mfg-sample-app-cortexm3-iar-em357-em3xx-dev0680/ Как я могу указать компоновщику связать E:/em35x/build/mfg-sample- приложение-cortexm3-iar-em357-em3xx-dev0680/mfg-sample.o - person billz; 21.08.2010
    comment
    @ATJ: Это то, что намеревался сделать человек, написавший make-файл, с функцией VPATH. VPATH указывает make искать зависимости в указанных каталогах в дополнение к текущему каталогу (дополнительную информацию см. в руководстве make). Попробуйте предложенное мной изменение, оно должно работать, если в make-файле нет другой ошибки. - person Gilles 'SO- stop being evil'; 21.08.2010