开发者

I Want my makefile to be more order independent!

This is related to my previous question: Why does .PHONY not work in this situation?.

I have a makefile system that I wrote to make it easy for developers who are not familiar with make, to do their tasks. In short, there is a generic portion which would be the same for all projects, and a set of makefiles that are specific for a given project. The project specific ones include the generic ones. It worked great on make 3.80 for some reason, but when I tried it out on make 3.81 I ran into a few problems. That forced me to make changes that are mentioned in the above post. Now I have some new problems, so I decided to make another post. Like in that post, I made a much smaller and simpler set of makefiles that show the problem. Unfortunatly, the "simple" case consists of 6 files. Sorry about that. First I'll start with the "project specific" ones (these are meant to be simple):

makefile:

TARGETS:=\
    Lib1.mk \
    Lib2.mk \
    my_prog.mk \

include generic/top.mk

Lib1.mk:

BINARY:=Lib1
TYPE:=LIB
LOCATION:=a/location

include generic/rules.mk

Lib2.mk:

BINARY:=Lib2
TYPE:=LIB
LOCATION:=another/location
LIBS:=Lib1

include generic/rules.mk

my_prog.mk:

BINARY:=my_prog
TYPE:=EXE
LOCATION:=some/location
LIBS:=Lib1 Lib2

include generic/rules.mk

A quick description: Makefile simply lists the names of all the targets. A target is either a executable or a library. BINARY is the name of the library or executable (extensions are added by the generic part). TYPE is either EXE or LIB. LOCATION is where the binary should go. LIBS is whatever libraries this binary depends on. The real ones handles creating all the -L, rpath, etc. stuff for the user (as well as their equivalents for visual studio). Now for the generic ones (these do the REAL work):

generic/top.mk:

ALL_BINS:=

.PHONY: all
all:

include $(TARGETS)

all: $(ALL_BINS)

%.so %.exe:
    mkdir -p $(dir $@)
    tou开发者_开发问答ch $@

clean:
    rm -rf out

and finally..

generic/rules.mk:

ifeq (EXE,$(TYPE))
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/$(BINARY).exe
else
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/lib$(BINARY).so
endif

$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$($(a).FULL_FILE_NAME))
ALL_BINS+=$(BINARY)

$(BINARY): $($(BINARY).FULL_FILE_NAME)
$($(BINARY).FULL_FILE_NAME): $($(BINARY).DEP_LIBS)

BINARY:=
LOCATION:=
LIBS:=

Ok, in this state, things work fine. Make handles all the dependencies correctly, and if I touch any of the files, it will correctly "build" only the ones that it has to, and nothing more. The problem happens when you take the m_prog.mk line from makefile and move it to the top of the list, like so:

TARGETS:=\
    my_prog.mk \
    Lib1.mk \
    Lib2.mk \

The problem seems to be that while its is going through rules.mk for my_prog.mk it does not yet know what the full library path for Lib1 and Lib2 (they are empty strings). So in the end, it considers my_prog to be dependent on nothing and it tries to build it out of order. In this example, you just see it "touch" my_prog first and then the other 2. Of course, when I have real compiler and linker commands in there, it throws an error.

Back when I simply had the .PHONY targets depend on each other (so my_prog depended on Lib1 and Lib2) life was easy and harmonious. Now that I can't do that, life became more difficult.

You may say, "heck just put it in the right order!". Well up to now, this has been handled automatically through make for the end users. In fact, most customers have been putting things in alphabetical order. They don't know or care what order they depend on each other. It would stink to have to tell them to re-order all of that now. Sorry for the length of this post. I'd appreciate any answers!


If you set variables using the := assignment operator, the assignment is evaluated immediately.

If you set variables using just = as the assignment operator, they're evaluated lazily, as late as possible (at the time of actual use).

See http://www.gnu.org/software/automake/manual/make/Flavors.html.


There are several ways to do what you want. The cleanest is probably by using vpath. Just modify rules.mk:

$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$(a).so)
ALL_BINS+=$(BINARY)

vpath %.so out/$(LOCATION)
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜