I've had Visual Studio and MSBuild fail on me multiple times by deciding not to recompile a certain .cpp file, because they got the dependency graph wrong. This results in a running but inconsistent executable that's a bitch to debug.
If you're selling me another tool that duplicates this work, but that has even less context on my project than the build system, I'll pass.
This made debugging so much easier for these issues. They're bound to happen, because we're all human and bugs are a thing. Automatically being able to audit the build as step 1 makes this easy to spot
I have to be honest - MS Build does not scale well. Companies use it because it’s the default.
Doesn't seem fully baked yet though
Earthly is explicit about inputs ( using COPY) and outputs of each build step. This let's it be 100% certain about whether it can cache parts of the build.
If you are familiar with docker layer-based caching and Bazel, you can imagine how Earthly works to eliminate rework in builds.
Here is a small monorepo example: https://github.com/earthly/earthly-solutions
In the end I decided that I couldn’t face the complexity of dealing with someone else’s hosted tooling. Luckily in this case.
RUN gradle build
At least in this case, Earthly has no insight into how repository is organized, and it _will_ recompile the entire repository with every single commit.So what's the real value of it? this basically seems like a better "docker build" alternative, giving nicer inter-layer caching. Maybe will save some time on dependencies if they take some time to install and devs were too lazy to set up own workers and used ephemeral runners instead.
[0] https://docs.earthly.dev/basics/part-1-a-simple-earthfile
build:
COPY build.gradle ./
COPY src src
RUN gradle build
RUN gradle install
SAVE ARTIFACT build/install/java-example/bin /bin
SAVE ARTIFACT build/install/java-example/lib /lib
The COPY phases copy files into the build context. If the files haven't changed, then the commands don't need to be run. In other words, if `build.gradle` and `src` are unchanged, it won't run `gradle build` or `gradle install`, and it'll just give you the artifacts from the previous build.They have a golang example in part three[0], which they redesign to use caching effectively:
build:
# Download deps before copying code.
COPY go.mod go.sum .
RUN go mod download
# Copy and build code.
COPY main.go .
RUN go build -o output/example main.go
SAVE ARTIFACT output/example AS LOCAL local-output/go-example
They copy in go.mod and go.sum and then run `go mod download`. If the mod and sum files haven't changed, then `go mod download` doesn't need to be run.Then they copy `main.go` in, and run `go build`. If the `main.go` file hasn't changed, `go build` doesn't need to be run.
[0] https://docs.earthly.dev/basics/part-3-adding-dependencies-w...
The whole idea with CI doing this is wrong IMO. All I want CI to do is call a couple of commands after setting up the environment (which would include the Gradle cache or whatever to speed up things - no need for your revolutionary CI build system).
Given that it's hard to understand what exactly this is for? Build systems normally try to avoid redundant work for local purposes anyway. Is it some hack for companies that insist on resetting build environments to zero on every single build, and then decide they want caching back? If so, why not just ... let the builds take place in directories containing previous builds, and fix the problems? That's what we do at my company and it works great (using gradle), there are only rarely problems with unclean builds and it's easy to rerun with a clean checkout if that's suspected to be an issue (the bugs are mostly in our own code which does a layer of caching above the build system anyway).
Don't get me wrong, there is definitely value in caching dependencies, and I can see Earthly approach help if you have, say, a Python app, with 10 minutes of dependency install time, 0 build time, and 10 seconds of tests - you'll see huge improvement. But you'll also see almost the same improvement if you use Dockerfile on a persistent host instead, and as a bonus you won't have to learn new system.
One place Earthly might shine are monorepos with multiple independent projects that even use multiple build systems... but I am not sure how many of those exist _and_ don't have some other caching solution already.
Generic CI just simply can't parallelize+cache on a level comparable to systems that understand the build itself (Bazel, sccache, etc).