2011-12-06 62 views
1

我想用一組代碼構建一個共享庫,並且一切正常,除了這個問題與我的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

如果要設定具體的目標變量,然後有可用的規則體之外的變量,你可以遞歸調用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 

你必須請記住在遞歸調用之後導出要「堅持」的變量。而且,如上所示,如果在調用之前追加任何變量,則需要使用?=進行初始分配,以便它們不會再次被設置。

-1

您可能需要使用uname來檢測操作系統,然後進行條件編譯。 This說明

+0

這根本沒有幫助。我從同一系統構建.so和.dll,因此我的開發框運行的操作系統是不相關的。 –

2

特定於目標的變量在規則的主體中可用,而不在其先決條件中。但是,即使你能夠實現這個目標,你也會遇到麻煩:如果你建立了一個圖書館,然後建立一個圖書館,那麼Make是無法知道爲第一個製作的bar.o對於第二個是錯誤的,不應該使用。

有幾種方法可以得到你想要的效果,但沒有一種是完美的。我建議使用兩個不同的目標文件名,如bar_unix.obar_windows.o

+0

「目標特定變量」是我正在尋找但不知道的短語。這現在有道理。你的獨立命名的o文件解決方案就是我使用這個工具,我想我會堅持下去。謝謝! –

+0

原來這樣做的方式是使用遞歸調用(這在我的情況下更加優雅,因爲我有很多變量需要爲工具鏈設置)。 –

相關問題