The builder pattern is not an alternative for named arguments. It's just too verbose, and it handles non-optional arguments poorly. There are libraries for generating a builder with the typestate pattern that can ensure that .finish() can't be called before all non-optional values were provided, but I don't like pulling in a dependency for this.
To avoid the boilerplate, I usually crate an Options struct instead:
#[derive(Default)]
pub struct CompileOptions {
foo: Foo,
bar: Bar,
baz: Baz,
}
So people can call compile(CompileOptions { foo: Foo, ..Default::default() }). But this is still boilerplate, and also can't handle non-optional arguments, if the struct implements Default. It's also more cumbersome to use because the user has to import the Options type.