Package Manager Extensible Build Tools

I am assuming you're referring to PackageExtension APIs. They need to be complex because different tools have different requirements and we need to allow the tools to express those requirements. The example in the proposal is a simple one but there are complex build tools. If you're interested, you can look at this CMake module that implements Swift compiler support for building dylibs.

Yes, it will be very easy to extend this API to support tools that don't have executables. We need to integrate llbuild into SwiftPM to support that, which is non-trivial amount of work but highly desirable. This is mentioned in the proposal:

Initially, only executables will be allowed as tools to create build commands,
but we do plan on adding support for defining in-process build tools. This is
dependent on SwiftPM adopting llbuild’s C API, which is a very desirable goal.

We absolutely want the package manifests to be clean. Can you explain why you think introduction of a new class (BuildRule) will make the package manifest unclean?

Your build.swift example looks more like a task runner to me. I think task runners should be part of package workspaces in future. We haven't really had any discussions about task runners but this is a random example:

import PackageWorkspace

let workspace = Workspace(".")

// Defines a task called "publish".
workspace.define(task: "publish") {
    // Clean the workspace.
    try workspace.reset()
    
    // Build the package.
    let builtPackage = try workspace.packages[0].build(config: .release)

    // Upload the binary!
    try Process.execute("upload-script", "--file", buildPackage.binary)
}

// Defines a task called "pull" to update all packages from remote.
workspace.define(task: "pull") { args in
    for package in workspace.packages {
        try Process.execute("git", "pull", "origin", args["branch"] ?? "master")
    }
}

Note: We might want to do something completely different for task runners, this is just a random example.