Build systems can’t have more than one command in them (so far as I am aware, anyway), so doing things this way would require a few build systems, which would be a pain in the butt as you have to switch and trigger each one.
A better way to do this would be to use a tool that’s made specifically for this purpose. There are many such tools, but the one that I use most often is make
, so I’ll show you how to do this with that one. If your Linux box has gcc
installed, then it should have make
as well.
Warning: Long post ahead; get a pillow ready in case you fall asleep
As a simple synopsis, make is a system for creating software by specifying rules that show what files depend on other files and what commands bring everything up to date. Below is a simple example based on what you posted above. I’ll go over what the file is doing for you, but I would recommend a tutorial or more reading on Make if you decide to use it (for example this one, which was the first hit in google when I checked).
NOTE: Make is very particular about using tabs instead of spaces to indent things; the indented lines in the below file have to be tabs or make will yak on you. When you edit a Makefile in Sublime, sublime takes care of making sure that tabs are used for indenting. You may need to modify the file if you just copy/paste this example, though.
Sample Makefile
# The location where SFML is installed
SFML_DIR=/Volumes/DATA/SFML
# Location where SFML libraries are located
LIBDIR=$(SFML_DIR)/lib
# Arguments to pass to the compiler
CFLAGS=-I$(SFML_DIR)/include
# SFML (and other) libraries that need to be linked with
LIBS=-lsfml-graphics -lsfml-window -lsfml-system
# Set the rule that links the executable as the default
# This is the default because it is *first* in the file,
# not because of it's name!
default: sfml
# Create the executable file
sfml: main.o
g++ -o sfml -L$(LIBDIR) $(LIBS) main.o
# Compile the source file
main.o: main.cpp
g++ -c main.cpp $(CFLAGS) -o main.o
# For running
run: sfml
LD_LIBRARY_PATH=$(LIBDIR) sfml
You would save this in a file named Makefile
in the same directory as the one that contains your source file. Sublime knows about building via Make, so you should just need to press Ctrl+B in order to build everything, although you may need to set the build system back to Automatic
or Make
from the Tools > Build System
menu if you’ve been using a custom build system. Since Make is a supported build system out of the box, you can double click on any compiler errors in the build output and sublime will jump to the appropriate location for you.
The first few lines of the Makefile set up simple variables that are later expanded in the rules; this isn’t really necessary but I find it makes the rest of the file easier to read; plus it makes changes easier. For example, if you change where SFML is installed, you only have to fix one thing and everything else will Just Work™.
The rest of the file consists of various make rules or targets that specify what to do. The general format is:
target: dependencies
shell commands to create/update target
The idea is that each rule specifies something that needs to be made (the target), what things are needed to make it (the dependencies) and what commands are used to do that. Using these rules, make will deduce what order to perform the steps in (e.g. it tries to compile the source files to an object file before it tries to link the object file into an executable).
So, reading from the top down in the sample file:
- By default (i.e. when you just type
make
and nothing more), try to bring sfml
up to date
- since there is no file named
default
, this rule will always trigger, and so make will always try to bring sfml
up to date
- what makes this rule the default rule is not it’s name, but that it is the first rule in the file
- The output file
sfml
requires a file named main.o
; once main.o
exists, execute the following shell commands to make sfml
- if
main.o
does not exist, make will first go find the rule that tells it how to build that file before it will execute this rule
- The output file
main.o
depends on a file named main.cpp
; once main.cpp
exists, execute the following shell commands to make main.o
- The assumption here is that
main.cpp
always exists. So really, this rule is saying "any time main.cpp
changes, you need to rebuild main.o
, which will in turn cause sfml
to be recreated.
The last rule (run
) is not really needed in the general case. You can probably tell from it’s name and the shell command that is part of the rule that the idea is that it runs the actual program. From the command line, you would enter the command make run
, which tells make that it should try to bring the run
target up to date, which it will try to do by actually running the executable.
Bonus marks
Although Sublime has support for Make built in, there’s no direct built in way to run your program from sublime after you’ve built it. You can drop to a terminal and run it from there, or you could create a specific key binding that would run your executable for you.
You might also recognize that if you put the run
rule as the first rule in the Makefile
, it would become the default rule, and so when you build it will automatically compile everything for you and then run the result. That’s certainly a thing you can do, but it takes away your ability to build the binary without running it.
What I tend to do is take advantage of how the Makefile has a run
target in it that is not the default target. I add the following to my .sublime-project
files where I’m working with C/C++ to override the built in Make build system (You could also just override the build system in general so it works everywhere, of course):
"build_systems" :
[
{
"name": "Make",
"shell_cmd": "make",
"file_regex": "^(..[^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
"working_dir": "${folder:${project_path:${file_path}}}",
"selector": "source.makefile",
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
"keyfiles": ["Makefile", "makefile"],
"variants":
[
{
"name": "Clean",
"shell_cmd": "make clean"
},
{
"name": "Run",
"shell_cmd": "make run"
}
]
}
]
The bulk of this is a direct copy of the built in Make build system which has been enhanced with the variants
listed above. Along with this key binding:
{
"keys": ["ctrl+alt+shift+r"],
"command": "build" ,
"args":
{
"variant": "Run"
}
}
Pressing Ctrl+Alt+Shift+R will invoke make run
for you, which will run the executable. Even better, since the run
rule in the Makefile
depends on the executable, if your sublime has Tools > Save All On Build
turned on, you can make some changes, hit the key, and Make will compile your code before it runs it.
You might notice that my build system specification also lists a Clean
variant, but there is no such target anywhere in the sample Makefile
. Usually a target like that would be the list of commands that remove all of the files that the Makefile is creating for you (in this case, main.o
and sfml
).
That kind of rule can be handy to “clean” the project, for example to force everything to rebuild no matter what the next time you build.
If you’re still awake, congratulations on making it all the way to the bottom of this post!