Skip to content

RFC: Deprecate the build= command #610

Closed
@tomaka

Description

@tomaka

The custom build command is a very wonky mechanism. It is not cross-platform, it assumes that the user has certain softwares installed on his system and available in his PATH (usually make/gcc, sometimes curl), it does not support cross-compilation, etc. Basically it is like having a makefile without a configure script.

This is especially problematic on Windows. Because of this command, a lot of Rust libraries depend on the user having MinGW installed (even though rustc no longer requires this), and some libraries simply can't be compiled on Windows, like glfw-rs. I have the sensation that all the efforts spent on improving support for Windows are worthless because of this.

I propose to deprecate the build command. At first, print a warning when compiling a crate that uses it, and in a second time remove support for it entirely.

Replacements

This command should be replaced by two complementary mechanisms.

Binary dependencies

Add a pre-build string entry in Cargo.toml. This string must in the format $package/$bin where $package is the name of a dependency in the dependencies array, and $bin is the name of a binary found in this dependency. The binary will be compiled and then run by Cargo similarly to the current build command.

The binary would have access to the environment variables that the build currently has access to, plus an additional one named COMMAND_CARGO_MANIFEST_DIR which contains the directory of the Cargo manifest of the dependency (instead of the manifest of the package where the command is being run).

Example:
/Cargo.toml:

[package]
name = "whatever"
authors = []
pre-build = "my-compiler/compile"

[dependencies.my-compiler]
path = "my-compiler"

/my-compiler/Cargo.toml:

[package]
name = "my-compiler"
authors = []

[[bin]]
name = "compile"

Why is this better than a regular build command?

  • Instead of having a makefile run curl for example, you can instead write a binary that uses a Rust http library, which is more cross-platform because it does not require the user to have curl in his path.
  • In situations where you would need a very complex pre-build script (for example invoking cmake (which requires determining the list of generators and invoking the right one)), instead of writing a difficult-to-maintain makefile that you copy-paste in multiple projects, you could simply use a Rust library.

Add native

Add a native array in Cargo.toml that specifies a list of non-rust libraries that must be present for this project to compile.

[[native]]
name = "GL"

[[native]]
name = "X11"

[[native]]
name = "Xxf86vm"

Cargo will process each entry in this order:

  • Try to find a pre-compiled version of the library (if X is the library name, try to find libX.* and X.*) in $package_root/native/$target. If it finds a match, copy the file in $(OUT_DIR).
    For example if you are compiling for arm-linux-androideabi and require a library named hello, Cargo will look for native/arm-linux-androideabi/libhello.* and native/arm-linux-androideabi/hello.*.
  • If we are not cross-compiling (ie. no --target option has been passed) and if we didn't find anything in the previous step, try to invoke pkg-config. If a result is found, pass the path of the library to rustc with the -L flag.
  • If we didn't find anything in the previous steps, try to find a pre-compiled version of the library in $(HOME)/.rust. There is no additional step because rustc already looks into $(HOME)/.rust. Cargo must still check if the library is present.
  • If nothing is found, print an error and stop. An additional flag --ignore-missing-native-libs could be added to Cargo in order to bypass this error and print a warning instead.

This system could be improved in the future by adding more entries to native, for example allowing the user to choose whether to link statically or dynamically.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linker issues, dylib, cdylib, shared libraries, soE-hardExperience: HardP-highPriority: High

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions