从不同的子目录编译.c文件和.s文件

时间:2010-08-20 17:26:12

标签: makefile linker-errors gnu-make

这是我的makefile 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的文件中。 当我运行上面发布的makefile时,编译器会将所有源文件编译到构建目录中的目标文件中,但链接器无法打开目标文件,因为它不在构建目录中查找它们,即E:/ em35x /建立/ MFG-样品-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

(首先它编译源文件,但最后它无法在build文件夹中找到目标文件)

现在我从makefile中删除第70行

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

然后它再次编译但没有链接,因为它无法打开目标文件。 (第一次提到错误)

我不知道我做错了什么。我尝试过很多东西,但找不到我的问题。

由于

编辑:我使用的是GNU Make 3.81

已将倒数第二行更改为:

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

我也按照吉尔斯的建议改变了VPATH,但没有运气。

现在我得到了这个erorr:

$ 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文件

编辑:测试版,我将在星期一测试你的行。然后我会报告结果,我想解决这个问题,这让我发疯。感谢

修改

Hi Beta,

我仍然使用您建议的代码获得相同的错误。这是错误,如果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

修改

Hi Beta, 是的,这很有用。

我收到了这条消息:

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

那么,我现在应该在原始的makefile中做什么?我想编译我的整个项目并链接目标文件。(所有我在不同路径位置的.c文件到build文件夹中,然后链接器应该将之前创建的.o文件链接到.out文件中)

修改

Hi Beta,

好的,我得到了它的工作,但是两个.s79文件怎么能得到它们也编译成构建目录中的目标文件?为什么VPATH不工作,我认为我的可靠性文件创建(.d)没有调用我如何获得被调用。我希望所有.h文件(源文件中的#include语句)都被自动识别并依赖于目标文件。

之后我想转换.out文件,但不会被调用。

问题在于:

你知道如何将它添加到我的makefile中:

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

在从目标文件创建/链接.out文件后,应将mfg-sample-app.out文件转换为mfg-sample-app.s37。

3 个答案:

答案 0 :(得分:1)

首先,该链接不指向makefile,它指向尝试运行make的输出。其次,我没有看到它实际产生mfg-sample-app.o的证据,但你说它确实如此,我会接受你的话。

有几种不同的东西可能导致此错误。我建议你恢复第70行,从干净的平板开始并运行make 两次。我认为它很有可能在第一次传递时构建目标文件并在第二次传递时找到它们。无论它做什么,我们都会学到一些东西。 (我建议你也改成一个更有信誉的编译器/链接器,比如gcc,但看起来好像这个以非标准的方式使用了一些标志。)

您得到的第二个错误很容易理解:您删除了定义对象列表的行,并且根据该列表定义了规则,因此Make不知道如何构建这些对象。但令我害怕的是Make知道如何在没有该列表的情况下调用链接器;它表明你的makefile中有很多冗余,这很糟糕。

顺便说一句,您使用的是什么?尝试运行make -v并查看其内容。

修改:
现在我可以看一下makefile,我想我可以清理这个谜。

有问题的源文件是E:/em35x/app/mfglib/mfg-sample.c。在第70行的情况下,只需将.c更改为.o,并得出相关目标文件为E:/em35x/app/mfglib/mfg-sample.o的结论。但是你已经将构建目录路径硬编码到编译器标志中(一个非常坏的做法),所以这就是对象文件所在的位置。然后,当Make进入链接步骤时,它找不到E:/em35x/app/mfglib/mfg-sample.o,并且死亡。

当您在没有第70行的情况下运行时,它会使用前面的行并得出mfg-sample.o应该在构建目录中的结论。如果在运行之前该对象文件已存在,请将目标文件链接在一起,一切顺利。但是如果文件不存在,则Make无法构建它,因为这个makefile只知道构建目标文件的一种方法,那就是编译源代码,它位于构建对象的同一目录中< / em>的。由于构建目录中没有这样的源文件,它就会死掉。

这个makefile可以使用很多工作,但这是(可能)解决问题的最小变化。 (你还没有说过你使用什么版本的Make - 这适用于GNUMake。)摆脱第70行并修改倒数第二行:

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

现在,无论Make认为目标文件应该去哪里,它都会查找没有路径(mfg-sample.c)的源文件,VPATH会找到它。

P.S。 Gilles指出VPATH中的分隔符可能无法在Windows中运行。如果我建议的更改不起作用,请尝试更改分隔符,因为Gilles建议(单独更改分隔符不会有帮助)。

修改:
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:

用手指交叉并尝试将其拼接到真正的makefile中(并删除第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:

  • s79文件:

    我们更改规则(编辑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。我不知道为什么VPATH无法正常工作。可以进行更多的调查,但这样做远程很难。您可以尝试远景:在我建议的实验性makefile中(在第二个EDIT块中)将VPATH行更改为:

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

    (注意小写。)

  • 依赖文件(.d)。我不知道规则中的命令是否有效(我无法访问您的“嵌入式工作台“工具”,但未调用规则的原因是include语句使用未定义的变量(sources)。 Make无法找到任何源文件,因此它不认为它必须包含任何东西,因此它不认为它必须构建任何东西(甚至不想它,因为它找不到来源)。您可以使用SRC变量,但不要忘记添加s79文件。

  • 转换.out文件。小菜一碟:

    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

  • 答案 1 :(得分:0)

    您有两种OBJ定义。一个明确列出了所有对象并说它们在END_DIR中,但是没有规则在一个地方从另一个目录中的源文件构建一个目标文件。第二个规则使用源文件并将.c替换为.o(并且目标文件将与源文件位于同一目录中)。

    删除第二个规则后,使用第一个定义来标识目标文件的链接位置,但不知道如何生成它们。这解释了第二个错误。要修复它,要么修改编译规则以将目标文件放在不同的目录中,要么使用第70行上的规则说明它们与源位于同一位置。

    目前尚不清楚为什么第一遍不起作用,但我建议在编译工作之前取出依赖文件(.d)的生成和包含。我发现将它们构建为编译的副作用比创建它们更有用。如果它们不存在,那么你还没有编译任何东西,无论如何都必须进行完整的构建。

    答案 2 :(得分:0)

    链接器完全按照它所说的做了:它被告知链接“E:\ em35x \ app \ mfglib \ mfg-sample.o”,它不存在。

    makefile中VPATH的定义存在问题::既用作DOS / Windows驱动器指示器,又用作路径分隔符。在Windows上,您必须将:替换为;或空格。 (这可能会破坏与make的其他unix实现的兼容性,这可能是生成此(部分)makefile的脚本的作者使用:的原因。)

    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/