SublimeText + Vagrant: the perfect workflow for cross-platform development

I have a workstation on Windows, but my work implies writing C++ software that compiles with GCC, Clang and Visual Studio, and runs on Windows, Linux, FreeBSD and OS X.

If you ever try to do cross platform development like this, you know it's a pain.

Nevertheless, I found a comfortable and efficient workflow that helps me be productive every day. It revolves around the following tools:

  1. Sublime Text 3
  2. SFTP plugin for Sublime Text
  3. Hightlight Build Error plugin for Sublime Text
  4. Vagrant
  5. PuTTY

Here is a step by step presentation of the workflow. I'll show the example of ArduinoJson because the compilation process is simple.

Step 1: Vagrant

Vagrant is a free tool that allows to create virtual machines in minutes. It sits on top of third party virtualization technologies, like VirtualBox.

Here how we create a VM with vagrant:

mkdir ubuntu15
cd ubuntu15
vagrant init ubuntu/vivid64
vagrant up

It'll take a few minutes to download the image ane spin it.
When it's done, we can open a SSH session with

vagrant ssh

We can now install the tools, clone the repository and create the Makefile:

sudo apt-get install g++ cmake git
git clone https://github.com/bblanchon/ArduinoJson.git
cd ArduinoJson
cmake .

That's it, our VM is ready to compile ArduinoJson.

Step 2: Sublime SFTP

Now we'll use the SFTP plugin for SublimeText. It allows to upload and download files through SSH directly from Sublime Text.

Note: this is a commercial (ie non-free) plugin. It cost $30 but it's definetly worth it. Moreover it's one of the few plugins written by Will Bond, the guy who created (for free) the Package Manager, he really deserves these thirty bucks!

We first need to clone ArduinoJson locally. We'll work on local files and synchronize them with the virtual machine thanks to the plugin.

Open the folder in Sublime Text. Right click on the folder an click SFTP / Map to remote....

It will create a sftp-config.json in the local folder. This file configures the synchronization between the local folder and a remote folder. In our case, the remote folder is in the virtual machine.

The important settings in sftp-config.json are:

{
    // we set this to true so that we don't have to 
    // manualy synchronize the files
    "upload_on_save": true, 

    // these are the default for all Vagrant VMs:
    "host": "127.0.0.1",
    "user": "vagrant",
    "password": "password",
    "port": "2222",

    // the path to the remote clone of the repo
    "remote_path": "/home/vagrant/ArduinoJson"
}

This is basically it. But there is one more detail.

When the SFTP synchronize files, it opens a window for a few seconds to show what's going on and then close it. This is usually OK, but unfortunately it also closes the Build Results window. So I prefer to disable this feature.

In Sublime SFTP preference file, we have to set (not in sftp-config.json):

{
    "hide_output_panel": true
}

Step 3: setup build system

Right now we have a perfect copy of our source tree in the virtual machine. Every time we save a file, it's instantly copied into the VM.

We could stop here and build from the SSH console, but would it be better to compile from inside Sublime Text, doesn't it?

To do that, we first create a Sublime Text project with our local folder and edit the project file. We'll add a build system:

{
  "build_systems": [
    {
      "name": "Build on Linux",
      "shell_cmd": "plink -l vagrant -pw vagrant -P 2222 127.0.0.1 make -C /home/vagrant/ArduinoJson"
    }
  ]
}

As you can see, this will invoke make on the virtual machine using plink.exe. plink comes with PuTTY and allow to run commands on a remote host.

That's it, now you just have to press Ctrl/Cmd+B to build. The compiler output is directly written in the Build Results window.

Step 4: error highlighting

We need to add a regex to help Sublime Text find the errors in the compiler's output. We must take special precautions about paths because /home/vagrant means nothing on the Windows host.

{
  "build_systems": [
    {
      // ... same as before...
      "working_dir": "$project_path",
      "file_regex": "/home/vagrant/ArduinoJson/(.*):(\\d+):(\\d+):(.*)"
    }
  ]
}

This regex will capture the relative file path, the line number and the column. We set the working_dir so that the relative folder path will be resolved correctly on the host.

The very last thing to do is to install my Hightlight Build Error plugin for SublimeText and that's it!