Documentation Build Systems
Sublime Text provides build systems to allow users to run external programs. Examples of common uses for build systems include: compiling, transpiling, linting, and executing tests.
Build systems are specified via JSON and saved in a file with the extension .sublime-build. A new build system can be created by the menu item or the Build: New Build System command palette entry.
Build systems have various ways they can associate themselves
with files and projects. Using this information, Sublime Text can
intelligently display only viable build systems to the user. The
built-in exec
target provides common options to get
up and running quickly. For more complex requirements, build systems
can target custom Sublime Text commands written in Python.
Basic Example
The following is a basic example of a build system. This build system will execute the currently-open Python file.
{
"cmd": ["python", "$file"],
"selector": "source.python",
"file_regex": "^\\s*File \"(...*?)\", line ([0-9]*)"
}
The Usage and Options sections will discuss how to use and customize a build system.
Usage
Build systems include the following functionality:
- Automatic selection of a build system based on file type
- Remembering the last used build system
- Navigation of build system results
- Ability to cancel a build
Running a Build
A build can be run by one of the following methods:
Keyboard | Menu | ||
---|---|---|---|
Windows/Linux | Mac | All | |
Ctrl+B | ⌘+B | F7 |
Output will be shown in an output panel displayed at the bottom of the Sublime Text window.
Selecting a Build System
By default, Sublime Text uses automatic selection of build systems. When a user invokes a build, the current file's syntax and filename will be used to pick the appropriate build system.
If more than one build system matches the current file type, the user will be prompted to pick the build system they wish to use. Once a build system has been selected, Sublime Text will remember it until the user changes their selection.
To manually choose a build system, use:
Menu |
---|
To change the build system, within the viable options, use one of the following methods:
Keyboard | Menu | Command Palette | |
---|---|---|---|
Windows/Linux | Mac | Build With: | |
Ctrl+Shift+B | ⇧+⌘+B |
Navigating Results
Build systems allow navigation of files specified in the build output. Typically this is used to jump to the location of errors. Navigation can be performed via:
Command | Keyboard | Menu |
---|---|---|
Next Result | F4 | |
Previous Result | Shift+F4 |
Cancelling a Build
An in-process build can be cancelled via:
Keyboard | Menu | Command Palette | |
---|---|---|---|
Windows/Linux | Mac | Build: Cancel | |
Ctrl+Break | Ctrl+C |
Options
All build systems may use the following top-level keys in the .sublime-build file.
- selector
-
The base scope name of the syntax that this build system
should be enabled for.
Example:"source.python"
. - file_patterns
-
A list of file name patterns the build system should be enabled
for.
Example:["*.py"]
. - keyfiles
-
A list of file names, if present in one of the opened folders,
that will cause the build system to be enabled.
Example:["Makefile"]
. - variants
-
A list of subsidiary build systems that will inherit the options
from the top-level build system. Each variant needs to specify a
name
key, and may override or add options to the top-level build system.
Example:
[ { "name": "Debug Symbols", "cmd": ["my_command", "-D", "$file"] } ]
- cancel
-
A string command name, or a list of string options. If a string
is specified, the command specified will be used to cancel the
build. If a list of strings, the primary
target
will be called, with these options added on. This only needs to be specified when using a customtarget
.
Example:"cancel_my_build"
or{"kill": true}
. - target
-
The command to run when the build system is invoked. The default
value of exec allows use of
the additional options specified in exec
Target Options. If a value other than
exec
is specified, none of the options in exec Target Options will do anything. See the Advanced Example for a complete example.
Example:"my_build"
- windows
-
An object of options to use when the build system is being executed
on a Windows machine.
Example:
{ "cmd": ["my_command.exe", "/D", "$file"] }
- osx
-
An object of options to use when the build system is being executed
on a Mac machine.
Example:
{ "cmd": ["/Applications/MyProgram.app/Contents/MacOS/my_command", "-d", "$file"] }
- linux
-
An object of options to use when the build system is being executed
on a Linux machine.
Example:
{ "cmd": ["/usr/local/bin/my_command", "-d", "$file"] }
exec
Target Options
The default target
of exec
is used by the
majority of build systems. It provides the following options to
control what program to execute, and how to display the results.
- cmd
-
A list of strings specifying the executable to run, plus
any arguments to pass to it. Shell constructs such as piping
and redirection are not supported – see
shell_cmd. May
use variables.
Example:["my_command", "-d", "$file"]
- shell_cmd
-
A string specifying a shell command to execute. Unlike the
cmd option, this does allow
piping and redirection. Will use
bash
on Mac and Linux machine, andcmd.exe
on Windows. May use variables.
Example:"my_command \"$file\" | other_command"
- working_dir
-
A string specifying the directory to execute the
cmd or
shell_cmd within. May
use variables.
Example:"$file_path"
- file_regex
-
A string containing a regular expression to run on the build
output to match file information. The matched file information
is used to enable result navigation. The regex should capture
2, 3 or 4 groups.
The capture groups should be:- filename
- line number
- column number
- message
"^\s*(\\S[^:]*)\\((\\d+):(\\d+)\\): ([^\\n]+)"
- line_regex
-
A string containing a regular expression to run on the build
output to match line information. The matched file information
is used to enable result navigation. The regex should capture
1, 2 or 3 groups.
The groups should capture:- line number
- column number
- error message
Example:"^\s*line (\\d+) col (\\d+): ([^\\n]+)"
- encoding
-
A string specifying the encoding of the build system output. Uses
Python
codec names. Defaults to
"utf-8"
.
Example:"iso-8859-1"
- env
-
An object containing environment variable values to use when
running the cmd or
shell_cmd.
Example:{ "PYTHONIOENCODING": "utf-8" }
- quiet
-
A boolean that reduces the amount of output about the build system
invocation.
Example:true
- word_wrap
-
A boolean that turns on word wrapping in the build system output panel.
Example:true
- syntax
-
A string specifying the syntax file to use to highlight the build
system output panel.
Example:"Packages/JavaScript/JSON.sublime-syntax"
Custom Options
When implementing a command to act as a build system target, the command's keyword arguments are available via options in the .sublime-build file. However, certain parameter names will not work since they conflict with built-in build system functionality.
The following names will not be passed as arguments to
commands. This also applies to other situations, such as
options specified in the cancel
,
linux
, osx
and
windows
options.
cancel
file_patterns
keyfile
keyfiles
linux
osx
save_untitled_files
selector
target
variants
windows
Variables
The following variables will be expanded within any string specified
in the "cmd"
, "shell_cmd"
or
"working_dir"
options.
If a literal $
needs to be specified in one of these
options, it must be escaped with a \
. Since JSON
uses backslashes for escaping also, $
will need to
be written as \\$
.
Please note that this substitution
will occur for any target
. If a custom target is used,
it may implement variable expansion for additional options by using
sublime.expand_variables()
with the result from
self.window.extract_variables()
.
- $packages
- The path to the Packages/ folder
- $platform
-
A string containing the platform Sublime Text is running on:
windows
,osx
orlinux
. - $file
- The full path, including folder, to the file in the active view.
- $file_path
- The path to the folder that contains the file in the active view.
- $file_name
- The file name (sans folder path) of the file in the active view.
- $file_base_name
- The file name, exluding the extension, of the file in the active view.
- $file_extension
- The extension of the file name of the file in the active view.
- $folder
- The full path to the first folder open in the side bar.
- $project
- The full path to the current project file.
- $project_path
- The path to the folder containing the current project file.
- $project_name
- The file name (sans folder path) of the current project file.
- $project_base_name
- The file name, excluding the extension, of the current project file.
- $project_extension
- The extension of the current project file.
Advanced Example
The following example shows a custom target
command,
with the ability to cancel a build and navigate results.
A target
for a build system should be a
sublime.WindowCommand
.
This will provide the instance variable of self.window
to allow interaction with the current project, window and active view.
Please note that the following example is somewhat simplistic in its implementation, and it won't handle many common edge cases.
The following Python can be saved to a file named Package/User/my_example_build.py:
import sublime
import sublime_plugin
import subprocess
import threading
import os
class MyExampleBuildCommand(sublime_plugin.WindowCommand):
encoding = 'utf-8'
killed = False
proc = None
panel = None
panel_lock = threading.Lock()
def is_enabled(self, lint=False, integration=False, kill=False):
# The Cancel build option should only be available
# when the process is still running
if kill:
return self.proc is not None and self.proc.poll() is None
return True
def run(self, lint=False, integration=False, kill=False):
if kill:
if self.proc:
self.killed = True
self.proc.terminate()
return
vars = self.window.extract_variables()
working_dir = vars['file_path']
# A lock is used to ensure only one thread is
# touching the output panel at a time
with self.panel_lock:
# Creating the panel implicitly clears any previous contents
self.panel = self.window.create_output_panel('exec')
# Enable result navigation. The result_file_regex does
# the primary matching, but result_line_regex is used
# when build output includes some entries that only
# contain line/column info beneath a previous line
# listing the file info. The result_base_dir sets the
# path to resolve relative file names against.
settings = self.panel.settings()
settings.set(
'result_file_regex',
r'^File "([^"]+)" line (\d+) col (\d+)'
)
settings.set(
'result_line_regex',
r'^\s+line (\d+) col (\d+)'
)
settings.set('result_base_dir', working_dir)
self.window.run_command('show_panel', {'panel': 'output.exec'})
if self.proc is not None:
self.proc.terminate()
self.proc = None
args = ['my_cli']
if lint:
args.append('-l')
elif integration:
args.append('-i')
args.append(vars['file_name'])
self.proc = subprocess.Popen(
args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=working_dir
)
self.killed = False
threading.Thread(
target=self.read_handle,
args=(self.proc.stdout,)
).start()
def read_handle(self, handle):
chunk_size = 2 ** 13
out = b''
while True:
try:
data = os.read(handle.fileno(), chunk_size)
# If exactly the requested number of bytes was
# read, there may be more data, and the current
# data may contain part of a multibyte char
out += data
if len(data) == chunk_size:
continue
if data == b'' and out == b'':
raise IOError('EOF')
# We pass out to a function to ensure the
# timeout gets the value of out right now,
# rather than a future (mutated) version
self.queue_write(out.decode(self.encoding))
if data == b'':
raise IOError('EOF')
out = b''
except (UnicodeDecodeError) as e:
msg = 'Error decoding output using %s - %s'
self.queue_write(msg % (self.encoding, str(e)))
break
except (IOError):
if self.killed:
msg = 'Cancelled'
else:
msg = 'Finished'
self.queue_write('\n[%s]' % msg)
break
def queue_write(self, text):
sublime.set_timeout(lambda: self.do_write(text), 1)
def do_write(self, text):
with self.panel_lock:
self.panel.run_command('append', {'characters': text})
The custom MyExampleBuildCommand
can be
configured as a build system using the following JSON
saved to a file named
Packages/User/My Example Build.sublime-build:
{
"target": "my_example_build",
"selector": "source.mylang",
"cancel": {"kill": true},
"variants": [
{
"name": "Lint",
"lint": true
},
{
"name": "Integration Tests",
"integration": true
}
]
}