-
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This covers the general background of build systems concepts, before jumping into any one build system. Upcoming chapters: * Make as a build tool * Caching * Cross-user caching * Bazel as a build tool * Removing undeclared dependencies: toolchains * Remote execution * Optimising critical paths
- Loading branch information
1 parent
865a6a5
commit e5c549c
Showing
20 changed files
with
3,131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/out | ||
/gen/constants.h | ||
*.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
run: out | ||
./out | ||
|
||
clean: | ||
rm -f out | ||
find . -name '*.o' -exec rm {} \; | ||
|
||
out: main.o formatting/formatting.o | ||
clang++ main.o formatting/formatting.o -o out | ||
|
||
formatting/formatting.o: formatting/formatting.cpp | ||
clang++ formatting/formatting.cpp -I "." -c -o formatting/formatting.o | ||
|
||
main.o: main.cpp gen/constants.h formatting/formatting.h | ||
clang++ main.cpp -std=c++11 -I "." -c -o main.o | ||
|
||
gen/constants.h: scripts/generate_constants.sh | ||
./scripts/generate_constants.sh "Daniel" "Laura" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include "formatting/formatting.h" | ||
|
||
#include <sstream> | ||
#include <string> | ||
#include <vector> | ||
|
||
std::string JoinWithCommas(std::vector<std::string> parts) { | ||
std::stringstream out; | ||
if (parts.size() == 0) { | ||
return out.str(); | ||
} | ||
out << parts[0]; | ||
for (size_t i = 1; i < parts.size(); ++i) { | ||
out << ", " << parts[i]; | ||
} | ||
return out.str(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#include <string> | ||
#include <vector> | ||
|
||
std::string JoinWithCommas(std::vector<std::string> parts); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include <iostream> | ||
|
||
#include "formatting/formatting.h" | ||
#include "gen/constants.h" | ||
|
||
int main(void) { | ||
std::cout << "Hello " << JoinWithCommas(constants::names) << "!" << std::endl; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/bin/bash | ||
|
||
set -euo pipefail | ||
|
||
mkdir -p gen | ||
|
||
cat >gen/constants.h <<EOF | ||
#include <string> | ||
#include <vector> | ||
namespace constants { | ||
static std::vector<std::string> names = { | ||
EOF | ||
|
||
for name in "$@"; do | ||
echo " \"${name}\"," >> gen/constants.h | ||
done | ||
|
||
cat >>gen/constants.h <<EOF | ||
}; | ||
} | ||
EOF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.class | ||
*.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
run: com/example/Main.class | ||
java -cp .:third_party/guava-33.2.1-jre.jar com.example.Main | ||
|
||
clean: | ||
find . -name '*.class' -exec rm {} \; | ||
rm -rf third_party com/example/gen/Constants.java: | ||
|
||
com/example/Main.class: com/example/gen/Constants.class com/example/fmt/Formatting.class | ||
javac com/example/Main.java | ||
|
||
com/example/gen/Constants.java: scripts/generate_constants.sh | ||
./scripts/generate_constants.sh "Daniel" "Laura" | ||
|
||
com/example/gen/Constants.class: com/example/gen/Constants.java | ||
javac com/example/gen/Constants.java | ||
|
||
com/example/fmt/Formatting.class: third_party/guava-33.2.1-jre.jar | ||
javac -cp third_party/guava-33.2.1-jre.jar com/example/fmt/Formatting.java | ||
|
||
third_party/guava-33.2.1-jre.jar: | ||
mkdir -p third_party | ||
curl -o third_party/guava-33.2.1-jre.jar https://repo1.maven.org/maven2/com/google/guava/guava/33.2.1-jre/guava-33.2.1-jre.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.example; | ||
|
||
import com.example.fmt.Formatting; | ||
import com.example.gen.Constants; | ||
|
||
class Main { | ||
public static void main(String[] args) { | ||
System.out.printf("Hello %s!%n", Formatting.joinWithCommas(Constants.names())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.example.fmt; | ||
|
||
import com.google.common.base.Joiner; | ||
|
||
public class Formatting { | ||
public static String joinWithCommas(Iterable<String> names) { | ||
return Joiner.on(", ").join(names); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.example.gen; | ||
|
||
import java.util.ArrayList; | ||
|
||
public class Constants { | ||
public static Iterable<String> names() { | ||
ArrayList<String> names = new ArrayList<>(); | ||
names.add("Daniel"); | ||
names.add("Laura"); | ||
return names; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/bin/bash | ||
|
||
set -euo pipefail | ||
|
||
mkdir -p com/example/gen | ||
|
||
cat >com/example/gen/Constants.java <<EOF | ||
package com.example.gen; | ||
import java.util.ArrayList; | ||
public class Constants { | ||
public static Iterable<String> names() { | ||
ArrayList<String> names = new ArrayList<>(); | ||
EOF | ||
|
||
for name in "$@"; do | ||
echo " names.add(\"${name}\");" >>com/example/gen/Constants.java | ||
done | ||
|
||
cat >>com/example/gen/Constants.java <<EOF | ||
return names; | ||
} | ||
} | ||
EOF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
+++ | ||
title="1. What is a build system?" | ||
+++ | ||
|
||
# 1. What is a build system? | ||
|
||
## What is building software? | ||
|
||
"Building software" can refer to many things. One example is a software engineer may describe themself as "building software" when they write code. | ||
|
||
In this primer we're specifically concerned with one idea of building software: Converting some input file (typically source code) into some useful output (often executables or bundles ready to run or deploy, or test results). Most programming languages have some kind of build process, but different languages require more or less building. | ||
|
||
If you have written complex JavaScript, you have probably seen `package.json` files, and interacted with `npm` or `yarn`. These are tools used to build JavaScript. Here is an example `package.json` file: | ||
|
||
```json | ||
{ | ||
"name": "fancy-project", | ||
"type": "module", | ||
"scripts": { | ||
"build": "mkdir -p dist && webpack", | ||
"test": "jest test" | ||
}, | ||
"dependencies": { | ||
"dotenv": "^16.4.5" | ||
}, | ||
"devDependencies": { | ||
"jest": "^29.7.0", | ||
"webpack": "^5.91.0", | ||
"webpack-cli": "^5.1.4" | ||
} | ||
} | ||
``` | ||
|
||
Some of the actions these tools are used to do are: | ||
* Fetch all of the dependencies a project needs into a `node_modules` folder. | ||
* Run all of the tests in a project. | ||
* Combine a source file and everything it imports into a single file, and minify that file. | ||
|
||
These kind of actions are all related to building the software. Building software is concerned with analysing dependencies between different pieces of code, and running some commands to take source code and convert it to something useful. | ||
|
||
## What is a build tool? | ||
|
||
A "build system" or "build tool" is a tool which is aware of the relationships between different pieces of code, and performs actions to transform code from one form to another. A good build tool is **correct** (it always produces the correct output when you run it) and **fast** (i.e. it performs its actions as quickly as possible). We will use the terms "build tool" and "build system" interchangeably. | ||
|
||
## Why do we automate builds? | ||
|
||
A lot of the time we could perform the actions a build tool performs ourselves manually. | ||
|
||
To fetch dependencies, we could look in a `package.json` file and, for each dependency, work out what URL can be used to fetch it, download that URL, and unpack the files into the correctly named directory in the `node_modules` directory. And then do the same for each of its dependencies too. | ||
|
||
To run tests, we could manually find the `jest` tool in our `node_modules` directory, and run it to run our tests. | ||
|
||
We automate these processes with build tools for a few reasons: | ||
1. It avoids us needing to know things. What URL can a dependency be found at? What should its directory in `node_modules` be named? While we could find these things out, the build tool knows them, so we don't need to. | ||
2. It avoids us needing to work out the order we need to do things. The build tool knows which actions need to happen before which other actions, and will make sure they're done in the right order. | ||
3. It avoids us needing to think about what's already been done, and what needs to be re-done. Imagine we had already manually downloaded `dotenv` and `jest`. Then we changed the version of `dotenv` in the `package.json`. We can delete and re-download both `dotenv` and `jest` (which ensures we're doing the _correct_ thing), but this would be slower than it could be. If the version of `jest` hasn't changed, maybe we don't need to delete it and download it again. By just leaving the downloaded `jest` as-is, we can be _faster_. But manually analysing what we can skip and what we need to re-do is complicated and error-prone (what if changing the version of `dotenv` actually _does_ mean we need to re-download `jest`? Skipping it would mean our build was not _correct_!) |
Oops, something went wrong.