最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

xcodebuild - Xcode custom build rule, file dependencies in order - Stack Overflow

programmeradmin1浏览0评论

I have added my own build rule to Xcode, to compile a custom type of file. Let's call it .foo.

I need to be able to specify that file A should be compiled before file B (since B depends on A). I have already written the logic to calculate these dependencies in a Run Script build phase, which runs before the Compile Sources phase. I can guarantee that there are no cycles (or if there are, it's ok for the build to fail).

How do I tell Xcode about these file dependencies for .foo files, so that it compiles them in the right order?

Things I've tried:

  • outputting a "discovered dependency file" for each .foo file, into the derived sources directory, then adding it to my .foo build rule. I believe the syntax of the file should be B.foo: A.foo (indicating that A must be compiled before B). I've tried it with both just filenames and with full paths. Xcode is finding the file, but does not seem to act upon it.
  • Outputting an xcfilelist for each .foo file. This one I can't get to work -- in the "Input file lists" section of my .foo rule, Xcode doesn't seem to want to expand any build variables that refer to the current file. For example, if I add an item $(DERIVED_SOURCES_DIR)/$(INPUT_FILE_NAME).deps to the "input file lists" section, Xcode will expand "DERIVED_SOURCES_DIR" but will not expand "INPUT_FILE_NAME". From this I conclude that you can't have a per-file input file list, you can only have one single list for the whole .foo build rule. Is this assumption correct?

What am I missing? There must be a way of telling Xcode about file dependencies, right?

Specific questions about .d files:

In a "discovered dependency file" (i.e. a .d file), as I understand it the syntax is <target>: <dep> <dep> <dep>.

  1. Should the target be a full path or just a filename?
  2. Should the target refer to my .foo file (the thing I'm building, inside my source folder), or my .foo.out file (the thing it builds, inside my derived files folder)?
  3. The deps, i.e. the things that need to be built before the target: same question regarding full path, and do they refer to the source or the built output?

I have looked in Xcode's build timeline, and all my .foo files are building in parallel, it doesn't seem to be paying attention to anything I put in the .d files. So I suspect I'm getting the syntax wrong somehow.

I have added my own build rule to Xcode, to compile a custom type of file. Let's call it .foo.

I need to be able to specify that file A should be compiled before file B (since B depends on A). I have already written the logic to calculate these dependencies in a Run Script build phase, which runs before the Compile Sources phase. I can guarantee that there are no cycles (or if there are, it's ok for the build to fail).

How do I tell Xcode about these file dependencies for .foo files, so that it compiles them in the right order?

Things I've tried:

  • outputting a "discovered dependency file" for each .foo file, into the derived sources directory, then adding it to my .foo build rule. I believe the syntax of the file should be B.foo: A.foo (indicating that A must be compiled before B). I've tried it with both just filenames and with full paths. Xcode is finding the file, but does not seem to act upon it.
  • Outputting an xcfilelist for each .foo file. This one I can't get to work -- in the "Input file lists" section of my .foo rule, Xcode doesn't seem to want to expand any build variables that refer to the current file. For example, if I add an item $(DERIVED_SOURCES_DIR)/$(INPUT_FILE_NAME).deps to the "input file lists" section, Xcode will expand "DERIVED_SOURCES_DIR" but will not expand "INPUT_FILE_NAME". From this I conclude that you can't have a per-file input file list, you can only have one single list for the whole .foo build rule. Is this assumption correct?

What am I missing? There must be a way of telling Xcode about file dependencies, right?

Specific questions about .d files:

In a "discovered dependency file" (i.e. a .d file), as I understand it the syntax is <target>: <dep> <dep> <dep>.

  1. Should the target be a full path or just a filename?
  2. Should the target refer to my .foo file (the thing I'm building, inside my source folder), or my .foo.out file (the thing it builds, inside my derived files folder)?
  3. The deps, i.e. the things that need to be built before the target: same question regarding full path, and do they refer to the source or the built output?

I have looked in Xcode's build timeline, and all my .foo files are building in parallel, it doesn't seem to be paying attention to anything I put in the .d files. So I suspect I'm getting the syntax wrong somehow.

Share Improve this question edited Mar 12 at 16:57 Amy Worrall asked Mar 12 at 10:57 Amy WorrallAmy Worrall 15.8k3 gold badges44 silver badges65 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

I’ve dealt with this before when adding a custom build rule in Xcode. Getting the file dependencies to work took some experimenting, but here’s what finally worked for me:

1. Use Absolute Paths in the .d Files

Both the target (the file you’re building) and its dependencies need to have full absolute paths, not just filenames or relative paths.

2. Target Should Be the Output File

In the.d file, the target must refer to the output of your build rule (e.g., A.foo.out), not the source file (A.foo).

Example:

/path/to/DerivedData/B.foo.out: /path/to/DerivedData/A.foo.out

This informs Xcode that B.foo.out is dependent on A.foo.out.

3. Inform Xcode About the.d File

In your build rule settings:

Add the.d file under Output Files

Example: $(DERIVED_SOURCES_DIR)/$(INPUT_FILE_BASE).d

Mark the box that indicates it's a dependency file.

4. Create Clean Build

Do a clean build after having this set up. Xcode caching can conceal problems otherwise.

In Short:

Use absolute paths.

Targets and dependencies are output files, not sources.

Register the.d files correctly in the build rule.

This made Xcode compile my files in the correct order. Hope this helps!

  1. Generate .d Files with Absolute Paths

    • In your Run Script phase, output a .d file for each .foo file using absolute paths to the output files (not source files). For example, if B.foo depends on A.foo:

      CollapseWrapCopy

      /path/to/DerivedData/.../B.foo.out: /path/to/DerivedData/.../A.foo.out

      • Use build variables like $(DERIVED_FILE_DIR) to compute paths dynamically, e.g.:

        bash

        CollapseWrapCopy

        echo "$(DERIVED_FILE_DIR)/B.foo.out: $(DERIVED_FILE_DIR)/A.foo.out" > "$(DERIVED_SOURCES_DIR)/B.d"

  2. Configure the .foo Build Rule

    In your custom build rule for *.foo files:

    • Output Files:

      • Add the compiled output: $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).foo.out

        Add the .d file: $(DERIVED_SOURCES_DIR)/$(INPUT_FILE_BASE).d

      • Check “Use Discovered Dependency File” and set it to $(DERIVED_SOURCES_DIR)/$(INPUT_FILE_BASE).d.

      • Ensure your script compiles $(INPUT_FILE_PATH) to $(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).foo.out.

  3. Ensure Proper Build Order

    Since your Run Script runs before Compile Sources, it should generate the .d files in time for the build rule (which runs during Compile Sources). Verify this in the Build Phases tab.

  4. Clean and Test

    Do a Clean Build Folder (Cmd+Shift+K) to clear caches. Check the build timeline to confirm A.foo compiles before B.foo.

Xcode respects .d files when they’re tied to a build rule’s output and use absolute paths to output files. Previous (e.g., source-to-source deps like B.foo: A.foo) didn’t work because Xcode needs the dependency chain based on compiled outputs.

发布评论

评论列表(0)

  1. 暂无评论