I got pulled into one of those conversations where I end up saying, “Fine, I’ll put up a post about it” and this is the post. Yes, you can test and run command-line apps directly from Xcode but I pretty much never do. It’s a pain with few benefits. That said, here’s how you do it.
Let’s say you need arguments. Open your scheme (⌘<) and select the Run > Arguments tab. Add the arguments you want to pass on launch one at a time. Double-click to edit any argument:
The arguments are vended by
count the array or use
CommandLine.argc to find out how many arguments you’re dealing with.
Counter-intuitively, Xcode does not automatically quote the arguments for you. This produces five arguments, not three, or six if you include the command itself:
["/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug/Test", "first", "second", "third", "fourth", "fifth"] 6
And what do you expect from the following?
You get this if you run directly in Xcode’s console:
["/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug/Test", "first", "several items at once", "third"] 4 Program ended with exit code: 0
But if you set your code to execute using Terminal:
Launching: '/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug/Test' Working directory: '/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug' 3 arguments: argv = '/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug/Test' argv = 'first' argv = 'several' ["/Users/ericasadun/Library/Developer/Xcode/DerivedData/Test-gwehknnihlcsiucsovtbnlrdtfun/Build/Products/Debug/Test", "first", "several"] 3
Xcode’s Crazy Terminal Option
If you’re running anything with direct key input (using POSIX termios/raw mode) or curses, running in the console doesn’t work. So Xcode provides a way to run those utilities in the terminal. Visit Run > Options and scroll all the way down.
This feature is buggy as hell, produces ridiculous amounts of excess text (see this), can take a significant time to launch, and even more time for Xcode to realize the process has finished. It is impossible to use with paths that use spaces (“
warning: working directory doesn't exist: '/Volumes/Kiku/Xcode/Derived'“).
I don’t like it. I don’t use it. But it exists.
Sane Command-Line Execution
Unless you’re dealing with things like automation and such, you can try out your compiled command-line apps by dragging your executable from the Products group onto the terminal. This places the path to your build at the prompt. Type out your arguments and press return:
However, I prefer to use a Copy File build phase. Select your Target > Build Phases, click plus (+) and add the executable. (I use absolute path and disable “only when installing”.) This lets you install directly to standard locations like /usr/local/bin or ~/bin, or if you don’t want to place it there until it is stable and ready for deployment, you can use a development folder:
Assuming your destination is in your shell’s path, start a new shell for the executable to be picked up the first time. After that, you can compile and run as you like.
For writing command line programs in Swift, I recently discovered the Swift Argument Parser package. I can’t recommend it enough.