获取makefile以从同一文件构建两个目标但具有不同的标志

时间:2013-07-25 13:01:18

标签: makefile dependencies gnu-make

我正在更改一个项目Makefile,以便构建一个完全相同但可以向编译器传递不同标志的可执行文件。

在更改之前,Makefile是这样的:

    TARGETS = elilo.efi

    all : check_gcc $(SUBDIRS) $(TARGETS)

    elilo.efi : elilo.so

    elilo.so : $(FILES)
    elilo.o : elilo.c $(ARCH)/sysdeps.h
    ...
    $(SUBDIRS): dummy
        $(MAKE) -C $@
    ...
    include Make.rules

其中:

  • $(SUBDIRS)存储项目的所有子目录
  • $(FILES),存储必须创建的所有.o文件,以便链接elilo.so
  • check_gcc只检查编译器版本并在需要时退出

此外,Make.rules包含编译和链接文件的一般规则:

%.efi: %.so 
    $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
           -j .rela -j .reloc --target=$(FORMAT) $*.so $@

%.so: %.o 
    $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES)

%.o: %.c         # Rule number 1
    $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
# a rule for .S
%.o: %.S 
    $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

我的尝试:

到目前为止,我已经尝试了以下内容以获得新目标,并且能够使用所有规则编译它们

TARGETS = elilo.efi usb

all : $(TARGETS)

elilo.efi : check_gcc $(SUBDIRS) elilo.so
        touch $@.touch

elilo.so : $(FILES)

.PHONY : usb
usb : check_gcc $(SUBDIRS)
    CFLAGS += "-DBoot64" $(MAKE) boot64.efi
    touch $@.touch

boot64.efi : elilo.so
    $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
           -j .rela -j .reloc --target=$(FORMAT) $> $@

使用Make.rules:

%.efi: %.so 
    $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
           -j .rela -j .reloc --target=$(FORMAT) $*.so $@

%.so: %.o
    $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES)

%.o: %.c usb.touch elilo.touch     # Rule number 1
    $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
...

但它看起来不像我对规则编号1 所做的更改,因为它现在在制作$(SUBDIRS)时停止,可能是因为该规则非常普遍而且影响了项目目录及其子目录中的每个目标文件......

基本上,我想要做的是,就像elilo.efi一样构建boot64.efi,但是将标志-DBoot64传递给编译器,这样一些.c文件就会改变它的行为。关于如何做到这一点的任何提示?

2 个答案:

答案 0 :(得分:1)

我认为你应该像这样:所以:

usb : check_gcc $(SUBDIRS)
    rm elilo.so
    CFLAGS += "-DBoot64" $(MAKE) boot64.efi
    touch $@.touch

因为如果elilo.so已经在没有“Boot64”的情况下构建,那么它将无法重建

答案 1 :(得分:1)

我想我终于找到了解决方案。而不是修改Make.rules中的“原型”规则。我已经构建了一个新的不同路径来构建bootx64.efi,因此它的构建方式与elilo.efi构建的方式相同。

代码如下:

all : check_gcc $(TARGETS)

######################## NORMAL ELILO ################################

elilo : $(SUBDIRS)
    $(MAKE) elilo.efi
    rm -f $(FILES)

elilo.efi : elilo.so

elilo.so : elilo.o $(FILES)

elilo.o : elilo.c $(ARCH)/sysdeps.h

############################ USB ELILO ###############################
# SUBDIRS must be build using a for, as if not done so, make 
# would take the rule as executed and SUBDIRS wouldn't be compiled 
# with the new flag

usb :
    for dir in $(SUBDIRS); do \
      $(MAKE) -C $$dir CFLAGS="$(CFLAGS) -DBOOTX64"; \
    done
    $(MAKE) bootx64.efi CFLAGS="$(CFLAGS) -DBOOTX64"

bootx64.efi : bootx64.so

bootx64.so : bootx64.o $(FILES)

# bootx64.o is build the same way elilo.o is build (code from the 
# prototype rules has been copied)

bootx64.o : elilo.c $(ARCH)/sysdeps.h
    $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

#######################################################################

最后,$(FILES)变量已被修改,从中取出elilo.o,如elilo.o, 和bootx64.o是区分.so文件的。现在这个.o文件是硬编码的 每个相应的规则。