Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build only the packages needed for the current variant #1408

Merged
merged 4 commits into from
Apr 19, 2021
Merged

build only the packages needed for the current variant #1408

merged 4 commits into from
Apr 19, 2021

Conversation

webern
Copy link
Contributor

@webern webern commented Mar 23, 2021

Issue number:

Closes #1361

Description of changes:

Utilize cargo dependency graph to build only the packages we need for the current variant.

Packages express a dependency on anything that the rpm spec file declares a dependency on. (We already did this for BuildRequires but now we do it for Requires as well.) Additionally, the variant's Cargo.toml needs to express the things the package crates it depends on.

Note: We now rely on a change in behavior in cargo 1.51.0 to allow us to build a package that is a dependency of a workspace, but which is not a workspace member. You will need to rustup update if you have an older version.

    build: refactor os package dependencies

    Signed-off-by: Ben Cressey <[email protected]>

    Change os.spec such that all first party code is installed when the os
    package is installed. Change release.spec such that it requires only the
    os package for first-party code instead of requiring each individual
    first-party package.

    This consolidates the package dependencies for first-party code into
    one place, instead of picking some of the packages in "release" and
    others through the variant definition.

    This is part of #1361. We want to better manage package dependencies
    with cargo so that we can build only the packages needed for a given
    variant, and this change eliminates some one-off first-party package
    dependencies that needed to be expressed at the variant level.
    packages: express installation dependencies in cargo

    Previously we expressed RPM BuildRequires dependencies in Cargo's
    dependency graph to ensure the necessary RPM's exist before we build
    a package. If we add to this RPM Requires dependencies (dependencies
    that are needed when software packages are installed), then we can use
    Cargo to select only the packages that are needed for a set of desired
    install packages.
    build: only build packages for current variant

    Adds the packages that are needed to build a variant to the variant's
    Cargo dependencies. Previously the build-variant makefile target assumed
    that all packages were pre-built. Instead we now tell Cargo to build the
    packages we need for the variant.

    Creates a workspace in the variants directory and removes the workspace
    in the packages directory. Updates the makefile accordingly. Now only
    the packages that are part of the dependency tree starting with the
    variant will be built.

    The build-kmod-kit target previously depended on build-packages, which
    is no longer available. So a new target, build-package, and a
    specialization of it, build-kernel, have been added. These use the same
    workspace context that is used when building variants to ensure that the
    same rpm is used by build-kmod-kit.
    makefile: remove world targets

    cargo make world targets were vestigial. Probably nobody is using them
    so we cleaned them up.

Testing done:

Starting from a clean build state:

  • ran cargo make -e BUILDSYS_VARIANT=aws-k8s-1.18
    • Observed that only k8s 1.18 was built (other k8s versions were not)
    • build succeeded
  • Without cleaning, ran cargo make -e BUILDSYS_VARIANT=aws-k8s-1.19
    • Observed that existing packages (other than os and release) were not rebuilt.
    • Saw that k8s 1.19 was built.
  • Without cleaning, ran cargo make -e BUILDSYS_VARIANT=aws-k8s-1.18 repo
    • Observed nothing was rebuilt.
  • Without cleaning, ran cargo make -e BUILDSYS_VARIANT=aws-k8s-1.19 repo
    • Observed that nothing was rebuilt.
  • find . -type d -name target
    • ./tools/target
    • ./variants/target

Starting from a clean build state:

  • ran cargo make build-kmod-kit
  • Observed the kernel being built.
  • target succeeded
  • find . -type d -name target
    • ./tools/target
    • ./variants/target

Starting from the above kmod-kit build state:

  • Ran an x86_64 aws-k8s-1.17 variant and ran a pod.
  • Ran an aarch64 aws-ecs-1 variant and ran a task.
  • Ran an aarch64 aws-dev variant and logged in.

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

@webern webern marked this pull request as draft March 23, 2021 23:36
@tjkirch tjkirch requested a review from bcressey March 23, 2021 23:43
@webern
Copy link
Contributor Author

webern commented Mar 24, 2021

I'll do some squashing and try to figure out the best thing for the kmod kit target today.

Makefile.toml Outdated Show resolved Hide resolved
@webern
Copy link
Contributor Author

webern commented Mar 24, 2021

webern force-pushed the webern:package-build branch from e428c02 to c49af80

This squashes things into a reasonable set of commits.

TODOs

  • It looks like the above push has an unintentional Cargo.lock change
  • Still need to do the kmod-kit fixme

@webern
Copy link
Contributor Author

webern commented Mar 24, 2021

webern force-pushed the webern:package-build branch from c49af80 to 8779092

Fix an errant lock file.

@webern
Copy link
Contributor Author

webern commented Mar 24, 2021

webern force-pushed the webern:package-build branch from 8779092 to 98a9439

Builds the kernel as a dependency of build-kmod-kits, which previously relied on less specific prerequisites.

@webern webern marked this pull request as ready for review March 24, 2021 23:00
Makefile.toml Outdated Show resolved Hide resolved
Makefile.toml Show resolved Hide resolved
packages/cni-plugins/Cargo.toml Show resolved Hide resolved
packages/release/Cargo.toml Show resolved Hide resolved
variants/aws-dev/Cargo.toml Show resolved Hide resolved
variants/aws-dev/Cargo.toml Outdated Show resolved Hide resolved
@webern
Copy link
Contributor Author

webern commented Mar 25, 2021

webern force-pushed the webern:package-build branch from 98a9439 to c9684e9

Remove os from the variant dependency lists since it is a dependency of release. (Leaning on CI to prove it.)

@webern
Copy link
Contributor Author

webern commented Mar 25, 2021

webern force-pushed the webern:package-build branch from c9684e9 to 2c415ff

Separate package dependencies between build-dependencies and dependencies (to represent RPM BuildRequires and Requires).

@webern
Copy link
Contributor Author

webern commented Mar 25, 2021

webern force-pushed the webern:package-build branch from 2c415ff to 6a000ce

Fix a couple of mistakes in the Requires vs BuildRequires distinctions.

@webern
Copy link
Contributor Author

webern commented Mar 25, 2021

Added a commit to remove cargo make world and cargo make world-variant.

@webern webern requested a review from bcressey March 26, 2021 18:13
@bcressey
Copy link
Contributor

bcressey commented Mar 27, 2021

One of the side effects of this change is that modifying certain packages (systemd) will trigger many more package rebuilds than they previously did. It might be worth exploring the graph with cargo tree to see if this is going to be painful for the developer workflow in common cases.

I'd say we might want to consider removing containerd's dependency on systemd, and the kubelet + docker-engine dependencies on containerd. We know both will end up on the final image by way of the release package, and they aren't needed at build time.

Makefile.toml Outdated Show resolved Hide resolved
@jhaynes jhaynes linked an issue Apr 1, 2021 that may be closed by this pull request
@webern
Copy link
Contributor Author

webern commented Apr 5, 2021

webern force-pushed the webern:package-build branch from 46d1fce to 35e636e

A rebase that git was surprisingly angry about and therefore might need more work. We'll see.

@webern
Copy link
Contributor Author

webern commented Apr 6, 2021

I'm going to switch this back to draft for now since my next push will be somewhat of a proposed solution.

@webern webern marked this pull request as draft April 6, 2021 17:33
@webern
Copy link
Contributor Author

webern commented Apr 6, 2021

After a push that didn't work out, then a revert... this push takes care of a surly rebase over develop

webern force-pushed the webern:package-build branch from 35e636e to ea32575

@webern
Copy link
Contributor Author

webern commented Apr 6, 2021

It seems the GitHub UI doesn't show the fact that I just pushed a new commit: 0caaf138909e83b84a7c264083523f725c133e51

In this commit I combine package and variant workspaces into a single workspace so that they have a shared target directory. This should solve the problems @bcressey detected here #1408 (comment)

There's something no one is going to like... I had to mv packages variants/packages. I tried the following alternate solutions which did not work:

  • A Cargo.toml workspace file in variants that reaches up and over to packages with ../packages/acip. Cargo didn't like this, the error was "workspace member is not hierarchically below the workspace root".
  • I tried creating a symlink at variants/packages that points to packages. Cargo didn't like this because it produced conflicting file paths for its lock file: "error: package collision in the lockfile: packages acpid v0.1.0 (/Users/someone/repos/br/packages/acpid) and acpid v0.1.0 (/Users/someone/repos/br/variants/packages/acpid) are different, but only one can be written to lockfile unambiguously"
  • I tried creating the workspace at the top level of the git repo, i.e. 'above' both variants and packages, but this didn't work because cargo make has a feature that detects workspaces and behaves differently when they are detected: https://sagiegurari.github.io/cargo-make/#usage-workspace-support

So for now what I have pushed is something that would work if we could live with the moving of the packages directory.

@webern
Copy link
Contributor Author

webern commented Apr 7, 2021

webern force-pushed the webern:package-build branch from 0caaf13 to eca1de3

In this version packages are no longer members of a workspace. This allows us to leave the packages directory alone instead of moving it into the variants workspace.

@webern
Copy link
Contributor Author

webern commented Apr 8, 2021

@bcressey this is ready for re-review. I think there might be more you wanted to do with moving some deps from the variant's cargo.toml to common release.spec dependencies. But everything else is done.

@webern webern requested a review from bcressey April 8, 2021 00:13
packages/release/Cargo.toml Outdated Show resolved Hide resolved
variants/aws-dev/Cargo.lock Outdated Show resolved Hide resolved
Makefile.toml Show resolved Hide resolved
@webern
Copy link
Contributor Author

webern commented Apr 8, 2021

webern force-pushed the webern:package-build branch from 0d27970 to f684ba7

Remove the individual variant lock files since they are part of a workspace now.

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

webern force-pushed the webern:package-build branch from f684ba7 to 53bda81

  • Remove host-ctr from release's Cargo.toml dependencies since it is obtained through os
  • Note in BUILDING.md that you now need Rust 1.51.0 or higher.

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

webern force-pushed the webern:package-build branch from 53bda81 to 2037bd3

rebase

oops, unsquashed a couple of fixup commits

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

webern force-pushed the webern:package-build branch from 2037bd3 to 5208962

resquash a couple of fixups

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

Failed builds, I guess I need to add host-ctr to os's Cargo.toml.

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

webern force-pushed the webern:package-build branch from 5208962 to bc53009

Add host-ctr to os Cargo.toml 🤞

@webern
Copy link
Contributor Author

webern commented Apr 9, 2021

webern force-pushed the webern:package-build branch from bc53009 to 5fcc3cf

Fix Cargo.lock files in all affected commits 🤞

@webern
Copy link
Contributor Author

webern commented Apr 12, 2021

webern force-pushed the webern:package-build branch from 5fcc3cf to 1ca16f1

Add bootstrap-containers to the os/release package dependency refactor.

Edit: oops bad push

@webern
Copy link
Contributor Author

webern commented Apr 12, 2021

webern force-pushed the webern:package-build branch from 1ca16f1 to 5fcc3cf

undo bad push

@webern
Copy link
Contributor Author

webern commented Apr 12, 2021

webern force-pushed the webern:package-build branch from 5fcc3cf to 4477e17

Add bootstrap-containers to the os/release package dependency refactor (without undoing other work this time).

@webern webern requested a review from tjkirch April 12, 2021 21:34
@webern
Copy link
Contributor Author

webern commented Apr 13, 2021

webern force-pushed the webern:package-build branch from 4477e17 to c0b6d76

Very minor rebase

@webern
Copy link
Contributor Author

webern commented Apr 14, 2021

webern force-pushed the webern:package-build branch from c0b6d76 to 59dd076

Attempt at README correctness.

Copy link
Contributor

@tjkirch tjkirch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great improvement!

packages/README.md Outdated Show resolved Hide resolved
packages/README.md Outdated Show resolved Hide resolved
packages/README.md Outdated Show resolved Hide resolved
packages/README.md Outdated Show resolved Hide resolved
```

The [package.metadata](https://doc.rust-lang.org/cargo/reference/manifest.html#the-metadata-table-optional) table is ignored by Cargo and interpreted by our `buildsys` tool.

It contains an `included-packages` list which specifies the packages to install when building the image.
In the `[build-dependencies]` section, we specify the packages that need to be built, which is sometimes slightly different than `included-packages`.
This populates the Cargo build graph with all of the RPM packages that need to be built before the variant can be constructed.
Copy link
Contributor

@tjkirch tjkirch Apr 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding these new sentences a bit confusing. build-dependencies are rather different than package.metadata, but they're stuck in the middle of that paragraph - can we separate it? (Unless they're always intended to match, in which we should probably make less of a distinction.) It also has the effect of making it unclear whether the sentence just after this about including the release package applies to included-packages, build-dependencies, or both. (Either way... why?)

And I have to ask... if they need to match, can we get rid of included-packages and have buildsys read the names of the build-dependencies instead? I see there are a couple package names that differ, but I bet we can come up with a solution for that rather than entirely duplicating it. For example, I just tested and found that you can add extra keys to dependencies for your own purposes; we could do something like chrony = { path = "../../packages/chrony", included_rpms = "chrony-tools" } for those special cases.

I'm not sure we need the technical wording here about the build graph, unless it's important to explain the difference between included-packages and build-dependencies. I think the audience for this doc is someone trying to build a variant, not work on the build system.

Copy link
Contributor Author

@webern webern Apr 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by satisfied by the current package

For example os.spec Requires: apiserver, but os.spec defines/builds the apiserver package, so there is nothing to add to [dependencies].

if they need to match, can we get rid of included-packages and have buildsys read the names of the build-dependencies instead

That seems like a reasonable enhancement to consider. I think it should be outside of the scope of this PR, but we could open an issue.

With build-dependencies (`BuildRequires:`) it's important that they be built *before* the current package is built.
Runtime dependencies (`Requires`) can be built at any time.
The separation between `build-dependencies` and `dependencies` in Cargo.toml is not necessary but helps us distinguish between the two dependency types.
Note that we do not include `Requires:` dependencies if they are already satisfied by either the current package, or the build-dependencies.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this. What do you mean by satisfied by the current package?

I think the biggest potential confusion we have is from someone adding or updating a package who doesn't understand what needs to go in Requires vs. dependencies, BuildRequires vs. build-dependencies, and dependencies vs. build-dependencies. Several comments here imply that dependencies = Requires, then we walk it back a bit here; I think it could be clearer to remove the "# RPM Requires" comments in the Cargo.toml files (since they're not really true) and have people read this doc instead, and in this doc, also remove the equivalence statements above, and have one section that clearly explains what [dependencies] should be and how/when they differ from Requires.

Part of the confusion is that we don't list all of the Requires as dependencies, even if they're not satisfied by build-dependencies, in special cases where we just know it'll cause problems. (unnecessary systemd rebuilds, glibc, etc.) If that's always going to be a small set, we could just list them, but either way it's probably worth mentioning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it could be clearer to remove the "# RPM Requires" comments in the Cargo.toml

The closest thing we have to a mapping is: Requires: -> dependencies and BuildRequires: -> build-dependencies. The mapping is true even if some are omitted.

I definitely think it's more helpful than not to have the # RPM Requires comment in Cargo.toml even if you need the README to fully understand what's going on.

I'll take another stab at explaining it better in the README.

[dependencies]
cni-plugins = { path = "../cni-plugins" }
runc = { path = "../runc" }
systemd = { path = "../systemd" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having a hard time following the discussion at the top level of the PR, but are we sure we still want to include "global" [dependencies] like systemd that would be unnecessarily rebuilt? Per #1408 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we sure we still want to include "global" [dependencies] like systemd that would be unnecessarily rebuilt?

My preference would be to go ahead with the current version which does not have the global dependency removal optimization. It's a two-way door, but it seems better to me to start with fewer exceptions.

Makefile.toml Show resolved Hide resolved
Makefile.toml Outdated Show resolved Hide resolved
@webern
Copy link
Contributor Author

webern commented Apr 15, 2021

webern force-pushed the webern:package-build branch from 59dd076 to 07a1b1e

Fixes to readmes and missing dependencies.

@webern
Copy link
Contributor Author

webern commented Apr 15, 2021

webern force-pushed the webern:package-build branch from 07a1b1e to 172c298

rebase

@webern
Copy link
Contributor Author

webern commented Apr 15, 2021

webern force-pushed the webern:package-build branch from 172c298 to f72a018

Remove k8s-1.15 from variants workspace.

Signed-off-by: Ben Cressey <[email protected]>

Change os.spec such that all first party code is installed when the os
package is installed. Change release.spec such that it requires only the
os package for first-party code instead of requiring each individual
first-party package.

This consolidates the package dependencies for first-party code into
one place, instead of picking some of the packages in "release" and
others through the variant definition.

This is part of #1361. We want to better manage package dependencies
with cargo so that we can build only the packages needed for a given
variant, and this change eliminates some one-off first-party package
dependencies that needed to be expressed at the variant level.
@webern
Copy link
Contributor Author

webern commented Apr 16, 2021

webern force-pushed the webern:package-build branch from f72a018 to e42c238

rebase (k8s 1.15 package removal)

Previously we expressed RPM BuildRequires dependencies in Cargo's
dependency graph to ensure the necessary RPM's exist before we build
a package. If we add to this RPM Requires dependencies (dependencies
that are needed when software packages are installed), then we can use
Cargo to select only the packages that are needed for a set of desired
install packages.
Adds the packages that are needed to build a variant to the variant's
Cargo dependencies. Previously the build-variant makefile target assumed
that all packages were pre-built. Instead we now tell Cargo to build the
packages we need for the variant.

Creates a workspace in the variants directory and removes the workspace
in the packages directory. Updates the makefile accordingly. Now only
the packages that are part of the dependency tree starting with the
variant will be built.

The build-kmod-kit target previously depended on build-packages, which
is no longer available. So a new target, build-package, and a
specialization of it, build-kernel, have been added. These use the same
workspace context that is used when building variants to ensure that the
same rpm is used by build-kmod-kit.
cargo make world targets were vestigial. Probably nobody is using them
so we cleaned them up.
@webern
Copy link
Contributor Author

webern commented Apr 16, 2021

webern force-pushed the webern:package-build branch from e42c238 to 26c140a

Another stab at explaining dependencies in packages/README

@webern webern merged commit c3a73ca into bottlerocket-os:develop Apr 19, 2021
@webern webern deleted the package-build branch April 20, 2021 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

only build the packages needed for the current variant
3 participants