简体   繁体   中英

Trying to understand the EXACT procedural flow/logic regarding GNU makefile parsing/execution

I've been reading GNU make site, but many thing seem annoyingly left out. It's clear that there are two stages for variable expansion, but it's not clear to me what goes on with regard to expanding/combining rules.

For example, I have a rule written here for the linker that I've purposely triggered an error with...


$(BUILD)/$(APP_NAME): $(OBJ_LIST)
    $(FP_COMPILER) $(PARAMS) $^ $(LPARAMS) -o $(BUILD)/$(APP_NAME)

$(BUILD)/$(APP_NAME): foo

foo:
    @echo bar

At some stage before the linker recipe is called, 'foo' is appended to the list of prerequisites and it shows up in the input list from expanding $^. Because foo is not an object file we get the error.

C:/msys64/mingw64/bin/g++.exe -Wall -g3 build/obj/main.o build/obj/phase1.o build/obj/phase2.o build/obj/phase3.o build/obj/helper/line_fetcher.o foo -lstdc++ -lm  -o build/test.exe
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find foo: No such file or directory
collect2.exe: error: ld returned 1 exit status

Even listing 'foo' as.phony doesn't prevent it from showing up when $^ is expanded. If I want to have a prerequisite target that does something before the link, I have to figure out some other place to put it so that it doesn't show up when $^ is expanded.

I'm aware there's ways to extract just the "*.o" files I want for the linker (I've already figured it out). That isn't my question. I'm more interested in understanding the internal logic of "make" so I don't encounter other types of bugs due to things being parsed/executed in an order I didn't expect.

There are far too many very different questions here for a SO question. Please choose one question and ask it with clarity.

You seem to have already found the best resource for this, the GNU make manual. You ask:

What isn't explained is how and when rulesets themselves are expanded.

but that is explained, in that same page which shows how rules are expanded:

immediate : immediate ; deferred
        deferred

If that's not the answer you want you need to focus your question more clearly and explain what about this is not clear.

You also ask:

If I want to have a prerequisite target that does something before the link, I have to figure out some other place to put it so that it doesn't show up when $^ is expanded.

There is no "other place to put it". Makefiles have only targets and prerequisites, and the definition of $^ is that it expands to all the prerequisites. That's it. There's nothing else.

If there are some prerequisites that you don't want to appear in the link line, you have to use a function to only expand to the ones you want, for example $(filter %.o,$^) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM