从规则设置OS变量

时间:2011-12-06 23:08:36

标签: makefile

我正在尝试使用一组代码构建一个共享库,一切正常,除了我的Makefile这个问题。到目前为止,这是我的(简化)Makefile:

OBJS = bar.o

libfoo.so:    OS = LINUX      # These don't seem to happen
libfoo.dll:   OS = WINDOWS

# Linux
ifeq ($(OS), LINUX)
CC = gcc
...

# Windows
else ifeq ($(OS), WINDOWS)
CC = i686-pc-mingw32-gcc
...
endif


all: libfoo.so libfoo.dll

libfoo.so: clean $(OBJS)
    ...

libfoo.dll: clean $(OBJS)
    ...


bar.o: bar_$(OS).c bar.h
    ...

因此,当您输入make libfoo.so时,我希望首先设置OS = LINUX。然后,当它到达bar.o(它是libfoo的依赖关系)时,它应该知道要使用哪个bar_$(OS).c。但是,我收到错误:

make: *** No rule to make target `bar_.c', needed by bar.o. Stop.

这告诉我,当它尝试生成bar.o时,$(OS)未设置。但是,当我尝试制作libfoo.so时,这不应该是第一件事,并且该规则是否会被评估?

3 个答案:

答案 0 :(得分:2)

特定于目标的变量在规则正文中可用,而不是在其先决条件中。但是,即使你能让这个工作起来,你也要惹麻烦:如果你建立一个图书馆而另一个图书馆,那么就无法让Make知道那个是bar.o为第一个做的是第二个是错误的,不应该使用。

有几种方法可以达到你想要的效果,但没有一种方法是完美的。我建议使用两个不同的目标文件名,例如bar_unix.obar_windows.o

答案 1 :(得分:0)

如果要设置特定于目标的变量,然后在该规则的主体外部使用该变量,则可以在导出变量后以递归方式调用Makefile:

OBJS ?= foo.o                    # Use ? so it isn't blown away on recursive call

libfoo.so: OS = LINUX
libfoo.so: OBJS += linux_only.o
libfoo.so:
    $(MAKE) -s build_libfoo_linux

build_libfoo_linux: $(OBJS)
    @echo "OS = $(OS)"           # Should print "OS = LINUX"

export OS                        # Can be anywhere

您必须记住在递归调用调用后导出要“保持”的变量。而且,如上所示,如果您在通话之前附加到任何变量,您将需要使用?=进行初始分配,以便第二次不设置它们。

答案 2 :(得分:-1)

您可能希望使用uname检测操作系统,然后进行有条件的编译。 This解释