XcodeGen
XcodeGen copied to clipboard
Enhancement: copyFiles buildPhase using Products
First thing first, let me show you concept:
Note that this is just a concept and is not a valid syntax
targets:
Sample Application:
type: application
platform: macOS
sources:
target: Helper
optional: true
buildPhase:
copyFiles:
destination: wrapper
subpath: $(CONTENTS_FOLDER_PATH)/Library/LoginItems
Helper:
type: application
platform: macOS
- Here I'm creating
Sample Application
which is the main application target, and the helper applicationHelper
.Helper
application will be used to toggleLaunch on Login
feature which is seen in many applications. To make it work, a helper application must be included in the main app bundle, in this case it's:Sample Application.app/Contents/Library/LoginItems/Helper.app
.- This is the latest and valid way to achieve the feature as of today.
- Reference: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLoginItems.html
Back to xcodegen, if I'm correct, this is not possible as of v2.18.0
(Please correct me if I'm missing something).
The above is just an example to explain the usefulness if it's possible. And this is not specific to the LoginItem thing, there may be other cases that can use this approach, I guess.
Thus, "copyFiles buildPhase using Products". (I'm not sure if sources
is the suitable location to put them, this is just a concept)
What do you think?
I'd love to do something similar in my app where I want to have a helper CLI embedded in my app package, I'm just not sure how to do it yet. If this is possible with XcodeGen as it is today I'd love to learn it. To my mind having this be in the sources
object feels really weird because it's not part of the sources of my target. I was looking more for a specific copyFiles
object separate from the sources
object.
I would like to reference files from the product directory in my build phases as well. 👍
My current workaround for login items contains a post-build shell script, but there is probably a better solution.
LOGIN_ITEMS_DIR="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/Contents/Library/LoginItems"
rm -rf "$LOGIN_ITEMS_DIR"
mkdir -p "$LOGIN_ITEMS_DIR"
cp -a "$BUILT_PRODUCTS_DIR/Helper.app" "$LOGIN_ITEMS_DIR"
I'm using post-script to workaround this too.
However I've been thinking that I've had mischosen the repo to open this issue as XcodeGen
relies on tuist/XcodeProj
to parse project files.
Did some research before and if I remember correctly, XcodeProj
doesn't support treating a product as a file to use it to like, very this issue's situation.
I've gotten this working by doing 2 things: 1) add embed: false
to the app's dependency on the CLI, and 2) this build phase:
postBuildScripts:
- script: "ditto \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\""
name: Copy CLI Helper
inputFiles:
- ${BUILT_PRODUCTS_DIR}/bindlewriter
outputFiles:
- ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/Contents/Helpers/bindlewriter
Where in this case bindlewriter
is the name of the CLI product that's being embedded inside of my app's bundle at Contents/Helpers
. It's helpful for me when I run into situations like this to write the script in my generated project and then copy it in to the right spot in my manifest.
That's elegant! I like it. What I've reached in the end is far more verbose:
dependencies: # This assures you the app will be copied into Resources dir
- target: TARGET NAME OF THE HELPER APP
postBuildScripts:
- script: |
set -Ceux
HELPER_PRODUCT_NAME="TARGET NAME OF THE HELPER APP"
CONTENTS_PATH="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}"
RESOURCES_DIR="${CONTENTS_PATH}/Resources"
LOGIN_ITEMS_DIR="${CONTENTS_PATH}/Library/LoginItems"
ORIGIN_HELPER_PATH="${RESOURCES_DIR}/${HELPER_PRODUCT_NAME}.app"
[[ -d $LOGIN_ITEMS_DIR ]] && rm -rfv "$LOGIN_ITEMS_DIR"
mkdir -p "$LOGIN_ITEMS_DIR"
mv -v "$ORIGIN_HELPER_PATH" "$LOGIN_ITEMS_DIR"
[[ $(ls -A "$RESOURCES_DIR") ]] || rm -rfv "${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources"
name: Move Helper.app to LoginItems
Then, create two main targets: One with the dependency and the script above, and the other without any dependency (for debugging). The benefit of this is you don't have to manually build helper app because it is a dependency.
Yeah I really just mimicked how XcodeGen does other copy files stages and adopted that for my own need! :joy:
Hope this helps the future:
dependencies:
- target: LanchAtLoginHelper
embed: true
codeSign: false
copy:
destination: wrapper
subpath: Contents/Library/LoginItems