You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU make中如何将先决条件展开延迟至其他目标创建后?

Dynamic Prerequisites from a Generated File in 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:

  1. When Make first starts, prereq_list.txt doesn't exist. The -include directive tells Make not to throw an error, but instead look for a rule to generate the file.
  2. Make runs the prereq_list.txt: target1 rule: first executing target1 to generate the raw prerequisite list, then converting that list into a valid Make variable definition.
  3. Once prereq_list.txt is generated, Make re-parses the entire Makefile. Now TARGET2_PREREQS is defined, so target2 knows its dynamic prerequisites.
  4. Finally, Make builds target2 and any of its new prerequisites (like foo.txt or bar.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:

  1. target2 first ensures target1 is run, generating the prerequisite list file.
  2. It then launches a new Make process, passing the content of prereq_list.txt as the TARGET2_DEPS variable.
  3. The sub-Make process parses the build_target2 rule 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:07:10