Following the instructions from the last lab, be sure to have installed VirtualBox and Vagrant and downloaded the box 'khoury/CentOS-7.6'
Everyone will be submitting their complete projects through a series of scripts hosted on login-student, collectively known as the 'turnin system.' To access them you need to be ssh'd into login-student, which can be accomplished with the following command in a Terminal on Linux and Mac OS, and PowerShell on Windows:
$ ssh <Your Khoury Username>@login.ccs.neu.edu
The scripts are located in the folder /course/cs3700sp20/bin/
. To
be able to use the turnin system, you must first register for the course with:
$ /course/cs3700sp20/bin/register-student <Your NEU ID here>
You can only run register-student
once. If you enter an incorrect
NEU ID when registering, you must contact your instructor to request a change,
otherwise we will not be able to include your projects when calculating your
final grades!
Make can best be described as the original build tool. Originally written in the late 1980s by Richard Stallman and Roland McGrath, make is by far the single most available build tool, being the defacto default on Linux and available on both Windows and Mac OS.
For languages that can be interpreted naively by the machine (eg. Python, Ruby, Bash, Racket) make serves little purpose. Ensuring that the correct interpreter is referred to and that the file is executable (see note below) is sufficient. However, As part of this class, always provide a Makefile, even if it is empty.
In linux, every plain-text executable file requires the magic sequence "#!" followed by the fully qualified path of the interpreter to be called. Eg:
#!/bin/bash #!/usr/bin/env python3 #!/usr/bin/env ruby ...
If you don't do so, the shell will attempt to interpret the file natively, resulting in errors that look like the following:
$ ./script.py ./script.py: line 3: syntax error near unexpected token `(' ./script.py: line 3: `def print_example():'
If you have a shebang and it's not working, eg:
$ ./script.py bash: ./script.py: Permission denied
Check that the script is marked as executable:
$ ls -l ./script.py -rw-rw-r-- 1 tsachleben tsachleben 99 Jan 14 22:08 script.py
And make it executable as necessary:
$ chmod +x script.py
# Makefile (Example 1) # This line is a Comment target: prerequisit(s) "\t" recipe_step1 "\t" recipe_step2 "\t" ... # In total, the above three pieces form a "rule"
Makefiles consist of one or more comments and one or more 'rules', of which, the first is the default recipe. When executing make without any arguments (as we will when building your projects) make will assume you want the default recipe.
For languages that come with their own build tool(s) (Golang, Rust's Cargo) your makefile bridges the gap to let make know what on the build tool to call. Eg.
# Makefile (Example 2) client: go build cmd/client
# Makefile (Example 3) client: cargo build
Java and other JVM languages are unusual, in that they must be compiled yet are interpretated at runtime. As such, Java projects that need to be executable at a command-line can have a Makefile and a script that calls the java VM. Eg.
# Makefile (Example 4) all: main.class main.class: main.java javac main.java
#!/bin/bash # example java -classpath $(pwd) main
In addition to comments and recipes (described above) make has several other faculties that extend the very basic functionality.
Make allows you to make your life easier when having to type something multiple times through the use of variables
# Makefile (Example 5) SRC_DIR = ./src CLASS_DIR = ./class all: $(CLASS_DIR)/main.class $(CLASS_DIR)/main.class: $(SRC_DIR)/main.java
Make allows for defining a rule on a class of files through the use of the
%
token. The %
token acts as a glob expression (ie the
regex .*
) for matching classes of file names in a rule. Eg. the
target %.o
matches all files ending in the .o
extension. To enable meaningful use of the %
token, make provides a
set of special variables that are dynamically defined per-rule. Some of the most
frequently used are listed below.
$@ # Name of the matched target $< # Name of the _first_ prerequisite $? # All prerequisites that are newer than the target $^ # All prerequisites
Let's apply these to our java example from before:
# Makefile (Example 6) SRC_DIR = ./src CLASS_DIR = ./cls all: $(CLASS_DIR)/main.class $(CLASS_DIR)/include.class jar cvfm example.jar Manifest.mf $? $(CLASS_DIR)/%.class: $(SRC_DIR)/%.java javac -d $(CLASS_DIR) $< .PHONY: all
Several 'directives' exist to change how make executes. Some affect the how make interprets the Makefile as a whole, while others change the behavior of individual recipes
.DEFAULT
:
Overrides the default recipe to be the one indicated by the directive.
.PHONY
Tells make always make indicated recipe(s) when requested.
.SILENT
Make will hide the output of all commands executed by the recipe.
Make is a very clever tool, and can build/move/funge/acquire just about any artifact you want it to. If we feel your Makefile is doing something off-color, we may review your project for academic integrity. If you are doing anything unusual, please clear it with a Professor or Lead TA before submitting!