0

I have a project that builds a library. The Xcode setting DSTROOT is set to the default /tmp/$(PROJECT_NAME).dst and Xcode puts the library there. I have a copy phase to add man pages. It has Destination set to "Absolute Path" and Path set to $(DSTROOT)/usr/local/share/man/man3. When I run it, it tries to copy the man pages to "/usr/local/share/man/man3" so I get permission denied. In other words it acts as if DSTROOT is not set. I tried explicitly setting a DSTROOT value instead of using the default. Same thing.

How can I get this Copy Files Build Phase to use the DSTROOT value?

msc
  • 1,549
  • 2
  • 12
  • 19

1 Answers1

1

Don't use Absolute Path. One approach is to select Wrapper as the destination and use "../../usr/local/share/man/man3" as the relative path. This assumes that the wrapper path is /Applications/$(PRODUCT_NAME).app, the default.

Another approach is to not use a Copy Files build phase, at all. Use a Run Script build phase. Set the shell to /bin/bash and use a script like:

set -x
mandir="$DSTROOT/usr/local/share/man/man3"
mkdir -p "$mandir"
i=0
while [$i -lt ${SCRIPT_INPUT_FILE_COUNT}] ; do
    name="SCRIPT_INPUT_FILE_$i"
    cp "${!name}" "$mandir/"
    let i=i+1
done

You might want to chmod and/or chown the files after copying them.

Be sure to add the files you want to copy as inputs to the build phase and the output paths (can be based on ${DSTROOT}) as outputs.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Are you sure Wrapper defaults to /Applications? I thought it pointed at `$(BUILT_PRODUCTS_DIR)/$(Target).app`. I'll try your second suggestion. – msc Apr 28 '19 at 02:14
  • Sorry, you're right that I made a mistake; it defaults to `/Applications/$(PRODUCT_NAME).app`. That's why I put two parent directory references in the relative path. I've tested both approaches and they both work. – Ken Thomases Apr 28 '19 at 02:27
  • I went with using Wrapper and the path ../../$(DSTROOT)/usr/local/share/man/man3. Thanks for the tip. – msc Apr 29 '19 at 23:29
  • You're welcome, but that doesn't make any sense. `$(DSTROOT)` is an absolute path, so putting it inside a relative path doesn't do anything good. Most likely, it's just evaluating to the empty string and having no effect. – Ken Thomases Apr 30 '19 at 01:26
  • No. Stick it in the middle of a relative path and it just extends that relative path. Wrapper + `../..` takes it to root `/`. From there it goes to wherever DSTROOT takes it. Xcode sets DSTROOT by default to `/tmp/$(PROJECT_NAME).dst ` so that's where it goes. The point about including DSTROOT is so you can do a real install with `sudo xcodebuild ... DSTROOT=/`. I'm using the path I showed and it is working for both install to `/tmp/$(PROJECT_NAME).dst ` and to `/`. – msc May 01 '19 at 03:18
  • Did you try it without `$(DSTROOT)` in the relative path? All of the same logic would seem to apply. That is, the wrapper path would be `$(DSTROOT)/Applications/Foo.app`, `../..` takes it to just `$(DSTROOT)`, then the rest of the relative path is applied. I doubt having `$(DSTROOT)` in the relative path matters. I'm dubious it's even working. (You could try a different build setting in there to see what happens.) – Ken Thomases May 01 '19 at 03:28
  • I don't see Wrapper, which I think is the $(WRAPPER_NAME) variable, in the build settings of any of my projects so I can't check, but according to the build settings reference it does not include $(DSTROOT). Therefore without my including $(DSTROOT) in the relative path, the installation path would be fixed to Wrapper+`../../usr/local/share/man/man3`. As I said I tested what I have. Xcode GUI builds go to `/tmp/$(PRODUCT_NAME).dst/usr/local/share/man/man3` and xcodebuild builds with `DSTROOT=/` at the end of the command go the `/usr/local/share/man/man3`. – msc May 06 '19 at 14:50