我正在尝试使用一组代码构建一个共享库,一切正常,除了我的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时,这不应该是第一件事,并且该规则是否会被评估?
答案 0 :(得分:2)
特定于目标的变量在规则正文中可用,而不是在其先决条件中。但是,即使你能让这个工作起来,你也要惹麻烦:如果你建立一个图书馆而另一个图书馆,那么就无法让Make知道那个是bar.o
为第一个做的是第二个是错误的,不应该使用。
有几种方法可以达到你想要的效果,但没有一种方法是完美的。我建议使用两个不同的目标文件名,例如bar_unix.o
和bar_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解释