xkick brings Golang support to Xcode 11

October 8, 2019

Contents

Overview

Hands down, Xcode is possibly the best IDE (integrated development environment) for macOS. It's got a clean user interface, it feels snappy, and it's easy to organize and navigate through large coding projects. There are many IDEs available for the macOS, but perhaps not as performant as Xcode.

Since Xcode happens to be Apple's flagship IDE, it makes sense that it comes with first-class support to develop Apple-specific technologies (iOS, macOS, tvOS, watchOS, etc). But what if you wanted lightweight support for the Go programming language (Golang) on Xcode? Well, unfortunately, there's been no recent efforts to provide Golang support for Xcode. Until now.

We created our newest tool, xkick, to bring limited Golang support to the latest version of Xcode, Xcode 11.

Features

xkick comes with basic syntax highlighting support, the ability to jump to type/method/function definitions, automatic Go code formatting, and automatic Go imports completion.

Syntax Highlighting

xkick provides basic syntax highlighting for Golang by adding "Golang" as an option to the "Syntax Coloring" sub-menu found in Xcode's "Editor" menu.

Jump to type/method/function definitions

xkick provides the capability to jump to type/method/function definitions.

Automatic Go code formatting

Go code is automatically formatted upon saving the file.

Automatic completion of Go imports

Go imports are automatically completed upon saving the file.

How does it work?

The xkick product consists of two items: The xkick installer package and the xkick command line interface (CLI) tool.

The xkick installer package is responsible for installing the required files to make Xcode aware of Golang, and it also installs the xkick CLI tool at /usr/local/bin.

The xkick CLI tool watches a set of Go source files for changes in a Go project folder (and its subfolders). When a change is detected to a Go source file, xkick ensures that the changed Go source file is automatically formatted and that it's Go imports are automatically updated as well.

Usage

Xcode Workflow

Using Workspaces

Use Workspaces for organizing and navigating through large Go codebases.

To get started, in the Xcode menu, choose File -> New -> Workspace. Give your workspace a name, and select a folder to save it in.

Open a Finder window and navigate to your Go project. Drag your Go project's folder into the Xcode Workspace's files pane.

When Xcode prompts you to choose options for adding the files, select the option "Create folder references for any added folders". Make sure that the "Copy items into destination's group folder" option is not checked. Click the Finish button when done.

Some benefits of Xcode

Searching through the codebase

With Xcode, searching through your Go codebase is super fast. You can search through multiple files using the following key combination: ⌘ + Shift + F

Opening a source file in a new window.

Double-clicking the source file will open it up in a new window.

Xcode remembers your windows

When you turn your Mac off, and then when you turn it back on again, you get to start off in Xcode from where you left off. All your open source file windows are remembered by Xcode.

Full-screen mode

Because of it's tight integration with macOS, Xcode provides excellent support for full-screen mode.

Quick Workspace Access

Xcode provies quick access to your workspace. Just right click on the Xcode icon in the dock, and you can easily open recent workspaces.

xkick CLI tool

The xkick CLI tool is responsible for watching a Go project folder and ensuring that the Go source file gets automatic formatting and automatic imports completion applied anytime the source file is updated.

To use the xkick CLI tool, open the terminal app and enter the directory containing your Go project, for example:

$ cd $GOPATH/src/MyGoProject
$ xkick

In this example, we didn't specify a directory for xkick to watch so xkick will watch the current working directory.

Specify a directory to watch

If you want to watch some other directory, you can specify a directory for xkick to watch using the -directory flag:

$ xkick -directory=$GOPATH/src/github.com/EngineerKamesh/gofullstack/volume2/section7/gopherfaceq

Skipping vendor directories

By default, vendor directories are skipped over (you should have a pretty good reason for editing code in vendored packages). If you really want xkick to watch for changes in Go source files that live in vendor directories, set the -skip-vendor flag to false (it's true by default):

$ xkick -skip-vendor=false

Verbose Mode

By default, verbose mode is turned off. When verbose mode is turned on, xkick will print out the name of the Go source file when a change is detected to the file. You can turn on verbose mode like so:

$ xkick -verbose=true

Syntax errors show up in the xkick output:

If there are syntax errors in your Go code, they'll show up in the xkick output, upon saving the file. The auto formatting and auto imports completion steps will fail and will display the error that was encountered. The errors you see here, will be the errors that are reported directly from the gofmt and goimports commands:

gofmt error: exit status 2 /Users/kamesh/go/src/github.com/EngineerKamesh/gofullstack/volume2/section7/gopherfaceq/common/asyncq/asyncq.go:6:1: expected declaration, found foobar

goimports error: exit status 2 /Users/kamesh/go/src/github.com/EngineerKamesh/gofullstack/volume2/section7/gopherfaceq/common/asyncq/asyncq.go:6:1: expected declaration, found 'IDENT' foobar

Limitations and Known Issues

Limitations

With the introduction of System Integrity Protection in 2016, Xcode no longer supports writing custom plugins. That means, at the current time, plugins are not possible (e.g for Go code completion and building/running/debugging Go projects within Xcode).

Known Issue: "The file has been changed by another application" Dialog

Remedy 1: Hit the "Save Anyway" button, and the Go source file will undergo the automatic formatting and automatic imports completion steps in one or more subsequent cycles.

Remedy 2: Specify a higher writes delay value. The writes delay value specifies the delay (in milliseconds) of how long each source code formatting operation should take. The default writes delay value is 999 milliseconds. You can change this value by including the -writes-delay flag when running xkick:

$ xkick -writes-delay=1800

Installation Instructions

System Requirements

  • macOS Catalina or Mojave
  • Xcode (v11.0)
  • Go (v1.12+)
  • gofmt (included with Go)
  • goimports
  • High maxfiles limit

Prerequisites

Prior to running the xkick installer package, the following prerequisites must be met:

macOS

We recommend running xkick on macOS Catalina or Mojave. Both the xkick installer package and the xkick CLI tool have been codesigned and notarized.

Xcode 11

We recommend running xkick on Xcode 11. xkick isn't designed to work for older versions of Xcode.

Go, gofmt, and goimports

You can grab the latest version of Go for macOS from the Go website's Downloads page. The Go distribution includes the gofmt tool.

You can install goimports by issuing the following command:

$ go get golang.org/x/tools/cmd/goimports

Using the Terminal app, you should now be able to issue the goimports --help command.

If the command was not found, make sure that you've set the GOPATH environment variable, and that you've added the /bin subdirectory to your PATH, as described in the GOPATH environment variable section of the How to Write Go Code document.

High maxfiles limit

You need to increase the system's default max open files limit. You can see what your current limit is by issuing the folowing command:

$ launchctl limit maxfiles

We recommend setting the max open files limit to 262144. Note: If your Go project has more files than this, you will need to set this to a higher value accordingly.

Create a file called limit.maxfiles.plist, located at /Library/LaunchDaemons. Enter the following contents in the limit.maxfiles.plist file:

 <?xml version="1.0" encoding="UTF-8"?> 
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
 <plist version="1.0"> 
   <dict> 
     <key>Label</key> 
     <string>limit.maxfiles</string> 
     <key>ProgramArguments</key> 
     <array> 
       <string>launchctl</string> 
       <string>limit</string> 
       <string>maxfiles</string> 
       <string>262144</string> 
       <string>524288</string> 
     </array> 
     <key>RunAtLoad</key> 
     <true/> 
   </dict> 
 </plist> 

Once you've saved the limit.maxfiles.plist file, issue the following command, to change the file's ownership:

$ sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist

Issue the following command, to reload the Launch Daemon with the updated maxfiles limits:

$ sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist

Confirm that the new max files limit have been set, by issuing the following command:

$ launchctl limit maxfiles

Installing xkick

Note: Make sure you've exited the Xcode app prior to running the xkick installer package

Once you've downloaded xkick from 2Checkout (our payment processor), double-click the xkick installer package file (with extension .pkg), click the "Continue" button and follow the on screen prompts.

Once the installer has finished installing xkick, run the following command:

 $ defaults write ~/Library/Developer/Xcode/Plug-ins/Golang.ideplugin/Contents/Info DVTPlugInCompatibilityUUIDs -array-add $(defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID) 

Note: Anytime you update Xcode, you will need to run the defaults write command.

Launch Xcode. You will get an "Unexpected code bundle - Golang.ideplugin" dialog. Select "Load Bundle".

You should now be able to see "Golang" in the "Syntax Coloring" sub-menu of Xcode's "Editor" menu.

See the Usage section to learn how to use xkick.

Uninstall xkick

To uninstall xkick, issue the following command:

$ /Library/Application\ Support/xkick/uninstall.sh