GNU make中如何将先决条件展开延迟至其他目标创建后?
Got it, let's tackle this problem head-on. The core issue here is that GNU Make parses all rule definitions before running any recipes—so you can't directly use a value generated by one recipe as a prerequisite for another rule in a single pass. But we can work around this with either dynamic Makefile includes or recursive Make calls, which fit your requirement of avoiding refactoring and replicating complex scenarios.
Method 1: Dynamic Include with Re-parsing
This approach leverages Make's ability to re-parse the Makefile when an included file is generated. Here's a simplified example matching your scenario:
# Our first target: generates a file with the prerequisite list for target2 target1: # Simulate your actual logic that writes prereqs to a file # In your real scenario, this could be compiling output, a script, etc. echo "foo.txt bar.txt" > prereq_list.txt # Rule to convert the generated prereq file into a Make-compatible variable prereq_list.txt: target1 # Write the file's content into a Make variable definition echo "TARGET2_PREREQS := $$(cat $@)" > $@.tmp # Rename to avoid partial writes breaking Make's parsing mv $@.tmp $@ # Include the generated file (the "-" suppresses errors if it doesn't exist yet) -include prereq_list.txt # Target2 now uses the dynamically defined prerequisites target2: $(TARGET2_PREREQS) @echo "Building target2 with dependencies: $(TARGET2_PREREQS)"
How it works:
- When Make first starts,
prereq_list.txtdoesn't exist. The-includedirective tells Make not to throw an error, but instead look for a rule to generate the file. - Make runs the
prereq_list.txt: target1rule: first executingtarget1to generate the raw prerequisite list, then converting that list into a valid Make variable definition. - Once
prereq_list.txtis generated, Make re-parses the entire Makefile. NowTARGET2_PREREQSis defined, sotarget2knows its dynamic prerequisites. - Finally, Make builds
target2and any of its new prerequisites (likefoo.txtorbar.txt, if you have rules for them).
Method 2: Recursive Make Call
If you prefer a simpler approach without re-parsing, you can use a recursive Make invocation to pass the generated prerequisites as a variable:
target1: # Same as before: generate the prerequisite list file echo "foo.txt bar.txt" > prereq_list.txt # Target2 first runs target1, then calls Make again with the dynamic prereqs target2: target1 # Read the prereq file and pass it to a sub-Make process $(MAKE) TARGET2_DEPS=$$(cat prereq_list.txt) build_target2 # The actual target2 logic, using the passed-in prerequisites build_target2: $(TARGET2_DEPS) @echo "Building build_target2 with dependencies: $(TARGET2_DEPS)"
How it works:
target2first ensurestarget1is run, generating the prerequisite list file.- It then launches a new Make process, passing the content of
prereq_list.txtas theTARGET2_DEPSvariable. - The sub-Make process parses the
build_target2rule with the already-known prerequisites, building them and then the target itself.
Key Notes
- Both methods avoid refactoring your existing rule structure and replicate the "prerequisite comes from a recipe-generated file" scenario you need.
- The dynamic include method is better for scenarios where the prerequisite list might change multiple times (Make will re-parse each time the included file updates).
- The recursive method is more straightforward for one-off dynamic prerequisite cases.
内容的提问来源于stack exchange,提问作者Brian

