开发者

Alternative to secondary expansion in a makefile for GNU make 3.79.1

开发者 https://www.devze.com 2023-02-12 09:06 出处:网络
I\'ve been working on a makefile that uses secondary expansion not knowing that this feature only exists since version 3.8开发者_运维问答1 of GNU make. Unfortunately, there are some old machines aroun

I've been working on a makefile that uses secondary expansion not knowing that this feature only exists since version 3.8开发者_运维问答1 of GNU make. Unfortunately, there are some old machines around here that only have make 3.79.1 installed and on these machines, the makefile doesn't work, of course. Is there an alternative to secondary expansion?

The rule for a C++ program where I use it looks like the following:

.SECONDEXPANSION:

# Pattern rule for linking
%_$(SYSTEM) : $$(%_ofiles) $(EXEC)/%_$(SYSTEM).o
    $(LD) $(LDFLAGS) -o $@ $^ $(LIBS)

# Example for an ofiles variable
prog1_ofiles = $(C1) $(C2)

C1 = $(OFILES)/C1.o

C2 = $(OFILES)/C2.o

I know - the best solution would be to install a current make version. But our system administrator was not enthusiastic about it ;) So I'm looking forward to your suggestions.

Btw, does anyone know where to get the documentation of GNU make 3.79.1 - I couldn't find it anywhere.


Just add make-3.81 sources in your source tree. Your main Makefile first should compile make-3.81 using whatever make is available and then use make-3.81 for compiling everything else.


What about a function/macro? Using eval would achieve the same result as the secondary expansion. Certainly not as clean, but less typing than all the explicit rules.

define PROGRAM_template
$(1)_$(SYSTEM) : $$($(1)_ofiles) $(EXEC)/$(1)_$(SYSTEM).o
       $(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
endef

$(foreach target, prog1 prog2 prog3, \
    $(eval $(call PROGRAM_template, $(target)))

Maybe you can wrap $$(%_ofiles) with eval in your original code and omit the foreach. Not sure...


No $(eval)?, bah! You will have to write some shell to emit the specific make syntax into file.mk (say), and then include that into the Makefile. You bootstrap the process by telling make that the Makefile depends on file.mk. Make first has to update Makefile before anything else. So it will create file.mk, include it, and restart itself.

For your case it looks like file.mk will just contain dependencies and no recipes. A brief sketch:

%_${SYSTEM}: ${EXEC}/%_${SYSTEM}.o
    $(LD) $(LDFLAGS) -o $@ $^ $(LIBS)

file.mk:
    echo '%_${SYSTEM}: ${prog1_ofiles}' >$@

Makefile: file.mk

include file.mk
0

精彩评论

暂无评论...
验证码 换一张
取 消