mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
Big refactor
This commit is contained in:
parent
6655e48513
commit
401f77a297
7
.github/dependabot.yml
vendored
Normal file
7
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: tuesday
|
35
.github/renovate.json5
vendored
Normal file
35
.github/renovate.json5
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"schedule": "every 6 weeks on tuesday",
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"fileMatch": [
|
||||
"Cargo.toml$"
|
||||
],
|
||||
"matchStrings": [
|
||||
"rust-version = \"(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)\""
|
||||
],
|
||||
"depNameTemplate": "rust-version",
|
||||
"packageNameTemplate": "rust-lang/rust",
|
||||
"datasourceTemplate": "github-releases"
|
||||
}
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"commitMessageTopic": "bump rust-version",
|
||||
"matchManagers": [
|
||||
"custom.regex"
|
||||
],
|
||||
"matchPackageNames": [
|
||||
"rust-version"
|
||||
],
|
||||
"extractVersion": "^(?<version>\\d+\\.\\d+)", // drop patch version
|
||||
"schedule": [
|
||||
"* * * * *"
|
||||
],
|
||||
"minimumReleaseAge": "6 months",
|
||||
"internalChecksFilter": "strict"
|
||||
}
|
||||
]
|
||||
}
|
25
.github/workflows/automerge.yaml
vendored
Normal file
25
.github/workflows/automerge.yaml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Auto-merge safe bot PRs
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
dependabot:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Enable auto-merge
|
||||
run: gh pr merge --auto --merge "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{github.event.pull_request.html_url}}
|
||||
|
||||
renovate:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'renovate[bot]'
|
||||
steps:
|
||||
- name: Enable auto-merge
|
||||
run: gh pr merge --auto --merge "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{github.event.pull_request.html_url}}
|
59
.github/workflows/ci.yaml
vendored
Normal file
59
.github/workflows/ci.yaml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: CI
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
toolchain: ["stable", "stable 6 months ago"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
- name: Build tests
|
||||
run: cargo test --workspace --no-run
|
||||
- name: Run tests
|
||||
run: cargo test --workspace
|
||||
|
||||
style:
|
||||
name: Style
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUSTFLAGS: -Dwarnings
|
||||
RUSTDOCFLAGS: -Dwarnings
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@nightly
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
- name: Install cargo-docs-rs
|
||||
uses: dtolnay/install@cargo-docs-rs
|
||||
- name: Check docs
|
||||
run: cargo docs-rs
|
||||
- name: Check lints
|
||||
run: cargo clippy
|
||||
- name: Check fmt
|
||||
run: cargo fmt -- --check
|
||||
|
||||
semver:
|
||||
name: API
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Semver checks
|
||||
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||
with:
|
||||
package: build-rs
|
19
.github/workflows/publish.yaml
vendored
Normal file
19
.github/workflows/publish.yaml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Publish
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Publish
|
||||
run: cargo publish
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}}
|
22
.github/workflows/publish.yml
vendored
22
.github/workflows/publish.yml
vendored
@ -1,22 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Publish
|
||||
run: cargo publish
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{secrets.CRATES_IO_API_TOKEN}}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
|
14
Cargo.lock
generated
Normal file
14
Cargo.lock
generated
Normal file
@ -0,0 +1,14 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "build-rs"
|
||||
version = "0.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "build-rs-test-lib"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"build-rs",
|
||||
]
|
17
Cargo.toml
17
Cargo.toml
@ -1,13 +1,14 @@
|
||||
[package]
|
||||
name = "build-rs"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
publish = false
|
||||
|
||||
description = "Convenience wrapper for cargo buildscript input/output"
|
||||
repository = "https://github.com/cad97/build-rs"
|
||||
license = "MIT OR Apache-2.0 OR 0BSD OR CC0-1.0 OR CDDL-1.0 OR MIT-0 OR Unlicense OR WTFPL"
|
||||
keywords = ["buildscript","build-script","cargo"]
|
||||
categories = ["development-tools::build-utils"]
|
||||
[features]
|
||||
|
||||
[lib]
|
||||
name = "build"
|
||||
## Experimental API. This feature flag is **NOT** semver stable.
|
||||
unstable = []
|
||||
|
||||
[workspace]
|
||||
members = ["test-lib"]
|
||||
|
38
README.md
38
README.md
@ -1,38 +0,0 @@
|
||||
A convenience wrapper for cargo buildscript input/output.
|
||||
|
||||
## Why?
|
||||
|
||||
The cargo buildscript API is (necessarily) stringly-typed. This crate helps you
|
||||
avoid typos, at least in the name of the instruction to cargo or environment
|
||||
variable that you're reading.
|
||||
|
||||
Additionally, [potentially multi-valued variables][irlo] have a subtle footgun,
|
||||
in that when they're a single value, you might match on `target_family="unix"`,
|
||||
whereas `target_family="unix,wasm"` is also a valid variable, and would wrongly
|
||||
be excluded by the naive check. Using this crate forces you to be correct about
|
||||
multi-valued inputs.
|
||||
|
||||
[irlo]: https://internals.rust-lang.org/t/futher-extensions-to-cfg-target-family-and-concerns-about-breakage/16313?u=cad97
|
||||
|
||||
## License
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
If this is insufficient, you may also use this software under any of the following licenses:
|
||||
|
||||
- [MIT License](https://spdx.org/licenses/MIT.html)
|
||||
- [Apache License 2.0](https://spdx.org/licenses/Apache-2.0.html)
|
||||
- [BSD Zero Clause License](https://spdx.org/licenses/0BSD.html)
|
||||
- [Creative Commons Zero v1.0 Universal](https://spdx.org/licenses/CC0-1.0.html)
|
||||
- [Common Development and Distribution License 1.0](https://spdx.org/licenses/CDDL-1.0.html)
|
||||
- [MIT No Attribution](https://spdx.org/licenses/MIT-0.html)
|
||||
- [The Unlicense](https://spdx.org/licenses/Unlicense.html) (the above text)
|
||||
- [Do What The F*ck You Want To Public License](https://spdx.org/licenses/WTFPL.html)
|
||||
|
||||
and if for some reason that is insufficient, open a PR (and maybe ask your lawyer some questions about the other libraries you're using).
|
17
src/allow_use.rs
Normal file
17
src/allow_use.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use std::sync::OnceLock;
|
||||
|
||||
fn rust_version_minor() -> u32 {
|
||||
static VERSION_MINOR: OnceLock<u32> = OnceLock::new();
|
||||
*VERSION_MINOR.get_or_init(|| {
|
||||
crate::input::cargo_pkg_rust_version()
|
||||
.split('.')
|
||||
.nth(1)
|
||||
.unwrap_or("70")
|
||||
.parse()
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn double_colon_directives() -> bool {
|
||||
rust_version_minor() >= 77
|
||||
}
|
654
src/input.rs
654
src/input.rs
@ -1,288 +1,406 @@
|
||||
use std::{env, ffi::OsString, path::PathBuf};
|
||||
//! Inputs from the build system to the build script.
|
||||
//!
|
||||
//! This crate does not do any caching or interpreting of the values provided by
|
||||
//! Cargo beyond the communication protocol itself. It is up to the build script
|
||||
//! to interpret the string values and decide what to do with them.
|
||||
//!
|
||||
//! Reference: <https://doc.rust-lang.org/stable/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
|
||||
|
||||
macro_rules! export {
|
||||
() => {};
|
||||
($(#[$meta:meta])* $f:ident -> String = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> String {
|
||||
env::var_os(stringify!($var))
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
|
||||
.into_string()
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
|
||||
}
|
||||
use std::{
|
||||
env,
|
||||
fmt::Display,
|
||||
path::PathBuf,
|
||||
str::{self, FromStr},
|
||||
};
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> Option<String> = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> Option<String> {
|
||||
env::var_os(stringify!($var)).map(|it| it
|
||||
.into_string()
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
|
||||
)
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> usize = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> usize {
|
||||
env::var_os(stringify!($var))
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
|
||||
.into_string()
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
|
||||
.parse()
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " did not parse as `usize`"))
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> Vec<String> = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> Vec<String> {
|
||||
env::var_os(stringify!($var))
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
|
||||
.into_string()
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " contained invalid UTF-8"))
|
||||
.split(',')
|
||||
.map(Into::into)
|
||||
.collect()
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> bool = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> bool {
|
||||
env::var_os(stringify!($var))
|
||||
.is_some()
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> PathBuf = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> PathBuf {
|
||||
env::var_os(stringify!($var))
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
|
||||
.into()
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> Option<PathBuf> = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> Option<PathBuf> {
|
||||
env::var_os(stringify!($var))
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> OsString = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
$(#[$meta])*
|
||||
pub fn $f() -> OsString {
|
||||
env::var_os(stringify!($var))
|
||||
.expect(concat!("cargo buildscript env var $", stringify!($var), " not found"))
|
||||
}
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
};
|
||||
($(#[$meta:meta])* $f:ident -> $out:ty = $var:ident $(; $($rest:tt)*)? ) => {
|
||||
compile_error!(concat!("Provided unknown output type ", stringify!($out), " to export!"));
|
||||
|
||||
$(export! {
|
||||
$($rest)*
|
||||
})?
|
||||
macro_rules! missing {
|
||||
($key:ident) => {
|
||||
panic!("cargo environment variable `{}` is missing", $key)
|
||||
};
|
||||
}
|
||||
|
||||
export! {
|
||||
/// Path to the `cargo` binary performing the build.
|
||||
cargo -> PathBuf = CARGO;
|
||||
/// The directory containing the manifest for the package being built (the
|
||||
/// package containing the build script). Also note that this is the value
|
||||
/// of the current working directory of the build script when it starts.
|
||||
cargo_manifest_dir -> PathBuf = CARGO_MANIFEST_DIR;
|
||||
/// The manifest links value.
|
||||
cargo_manifest_links -> String = CARGO_MANIFEST_LINKS;
|
||||
/// Contains parameters needed for Cargo's jobserver implementation to
|
||||
/// parallelize subprocesses. Rustc or cargo invocations from build.rs
|
||||
/// can already read CARGO_MAKEFLAGS, but GNU Make requires the flags
|
||||
/// to be specified either directly as arguments, or through the MAKEFLAGS
|
||||
/// environment variable. Currently Cargo doesn't set the MAKEFLAGS
|
||||
/// variable, but it's free for build scripts invoking GNU Make to set it
|
||||
/// to the contents of CARGO_MAKEFLAGS.
|
||||
cargo_makeflags -> OsString = CARGO_MAKEFLAGS;
|
||||
/// Set on [unix-like platforms](https://doc.rust-lang.org/reference/conditional-compilation.html#unix-and-windows).
|
||||
cargo_cfg_unix -> bool = CARGO_CFG_UNIX;
|
||||
/// Set on [windows-like platforms](https://doc.rust-lang.org/reference/conditional-compilation.html#unix-and-windows).
|
||||
cargo_cfg_windows -> bool = CARGO_CFG_WINDOWS;
|
||||
/// The [target family](https://doc.rust-lang.org/reference/conditional-compilation.html#target_family).
|
||||
cargo_cfg_target_family -> Vec<String> = CARGO_CFG_TARGET_FAMILY;
|
||||
/// The [target operating system](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os).
|
||||
cargo_cfg_target_os -> String = CARGO_CFG_TARGET_OS;
|
||||
/// The CPU [target architecture](https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch).
|
||||
cargo_cfg_target_arch -> String = CARGO_CFG_TARGET_ARCH;
|
||||
/// The [target vendor](https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor).
|
||||
cargo_cfg_target_vendor -> String = CARGO_CFG_TARGET_VENDOR;
|
||||
/// The [target environment](https://doc.rust-lang.org/reference/conditional-compilation.html#target_env) ABI.
|
||||
cargo_cfg_target_env -> String = CARGO_CFG_TARGET_ENV;
|
||||
/// The CPU [pointer width](https://doc.rust-lang.org/reference/conditional-compilation.html#target_pointer_width).
|
||||
cargo_cfg_pointer_width -> usize = CARGO_CFG_TARGET_POINTER_WIDTH;
|
||||
/// Teh CPU [target endianness](https://doc.rust-lang.org/reference/conditional-compilation.html#target_endian).
|
||||
cargo_cfg_target_endian -> String = CARGO_CFG_TARGET_ENDIAN;
|
||||
/// List of CPU [target features](https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature) enabled.
|
||||
cargo_cfg_target_feature -> Vec<String> = CARGO_CFG_TARGET_FEATURE;
|
||||
/// The folder in which all output should be placed. This folder is inside
|
||||
/// the build directory for the package being built, and it is unique for
|
||||
/// the package in question.
|
||||
out_dir -> PathBuf = OUT_DIR;
|
||||
/// The target triple that is being compiled for. Native code should be
|
||||
/// compiled for this triple. See the [Target Triple] description for
|
||||
/// more information.
|
||||
///
|
||||
/// [Target Triple]: https://doc.rust-lang.org/cargo/appendix/glossary.html#target
|
||||
target -> String = TARGET;
|
||||
/// The host triple of the Rust compiler.
|
||||
host -> String = HOST;
|
||||
/// The parallelism specified as the top-level parallelism. This can be
|
||||
/// useful to pass a `-j` parameter to a system like `make`. Note that care
|
||||
/// should be taken when interpreting this environment variable. For
|
||||
/// historical purposes this is still provided but recent versions of
|
||||
/// Cargo, for example, do not need to run `make -j`, and instead can set
|
||||
/// the `MAKEFLAGS` env var to the content of `CARGO_MAKEFLAGS` to activate
|
||||
/// the use of Cargo's GNU Make compatible [jobserver] for sub-make
|
||||
/// invocations.
|
||||
///
|
||||
/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html
|
||||
num_jobs -> String = NUM_JOBS;
|
||||
/// Value of the corresponding variable for the profile currently being built.
|
||||
opt_level -> String = OPT_LEVEL;
|
||||
/// Value of the corresponding variable for the profile currently being built.
|
||||
debug -> String = DEBUG;
|
||||
/// `release` for release builds, `debug` for other builds. This is
|
||||
/// determined based on if the profile inherits from the [`dev`] or
|
||||
/// [`release`] profile. Using this environment variable is not
|
||||
/// recommended. Using other environment variables like `OPT_LEVEL`
|
||||
/// provide a more correct view of the actual settings being used.
|
||||
///
|
||||
/// [`dev`]: https://doc.rust-lang.org/cargo/reference/profiles.html#dev
|
||||
/// [`release`]: https://doc.rust-lang.org/cargo/reference/profiles.html#release
|
||||
profile -> String = PROFILE;
|
||||
/// The compiler that Cargo has resolved to use, passed to the build script
|
||||
/// so it might use it as well.
|
||||
rustc -> PathBuf = RUSTC;
|
||||
/// The documentation generator that Cargo has resolved to use, passed to
|
||||
/// the build script so it might use it as well.
|
||||
rustdoc -> PathBuf = RUSTDOC;
|
||||
/// The `rustc` wrapper, if any, that Cargo is using. See
|
||||
/// [`build.rustc-wrapper`](https://doc.rust-lang.org/cargo/reference/config.html#buildrustc-wrapper).
|
||||
rustc_wrapper -> Option<PathBuf> = RUSTC_WRAPPER;
|
||||
/// The `rustc` wrapper, if any, that Cargo is using for workspace members.
|
||||
/// See [`build.rustc-workspace-wrapper`](https://doc.rust-lang.org/cargo/reference/config.html#buildrustc-workspace-wrapper).
|
||||
rustc_workspace_wrapper -> Option<PathBuf> = RUSTC_WORKSPACE_WRAPPER;
|
||||
/// The path to the linker binary that Cargo has resolved to use for the
|
||||
/// current target, if specified.
|
||||
rustc_linker -> Option<PathBuf> = RUSTC_LINKER;
|
||||
/// The full version of your package.
|
||||
cargo_pkg_version -> String = CARGO_PKG_VERSION;
|
||||
/// The major version of your package.
|
||||
cargo_pkg_version_major -> usize = CARGO_PKG_VERSION_MAJOR;
|
||||
/// The minor version of your package.
|
||||
cargo_pkg_version_minor -> usize = CARGO_PKG_VERSION_MINOR;
|
||||
/// The patch version of your package.
|
||||
cargo_pkg_version_patch -> usize = CARGO_PKG_VERSION_PATCH;
|
||||
/// The pre-release of your package.
|
||||
cargo_pkg_version_pre -> String = CARGO_PKG_VERSION_PRE;
|
||||
/// The name of your package.
|
||||
cargo_pkg_name -> String = CARGO_PKG_NAME;
|
||||
/// The description from the manifest of your package.
|
||||
cargo_pkg_description -> String = CARGO_PKG_DESCRIPTION;
|
||||
/// The home page from the manifest of your package.
|
||||
cargo_pkg_homepage -> String = CARGO_PKG_HOMEPAGE;
|
||||
/// The repository from the manifest of your package.
|
||||
cargo_pkg_repository -> String = CARGO_PKG_REPOSITORY;
|
||||
/// The license from the manifest of your package.
|
||||
cargo_pkg_license -> String = CARGO_PKG_LICENSE;
|
||||
/// The license file from the manifest of your package.
|
||||
cargo_pkg_license_file -> String = CARGO_PKG_LICENSE_FILE;
|
||||
macro_rules! invalid {
|
||||
($key:ident, $err:expr) => {
|
||||
panic!("cargo environment variable `{}` is invalid: {}", $key, $err)
|
||||
};
|
||||
}
|
||||
|
||||
/// For each activated feature of the package being built, this will be true.
|
||||
pub fn cargo_feature(name: &str) -> bool {
|
||||
let key = format!("CARGO_FEATURE_{}", name.to_uppercase().replace('-', "_"));
|
||||
#[track_caller]
|
||||
fn get_bool(key: &str) -> bool {
|
||||
env::var_os(key).is_some()
|
||||
}
|
||||
|
||||
/// For each [configuration option] of the package being built, this will
|
||||
/// contain the value of the configuration. Boolean configurations are present
|
||||
/// if they are set, and not present otherwise. This includes values built-in
|
||||
/// to the compiler (which can be seen with `rustc --print=cfg`) and values set
|
||||
/// by build scripts and extra flags passed to `rustc` (such as those defined
|
||||
/// in `RUSTFLAGS`).
|
||||
#[track_caller]
|
||||
fn get_opt_path(key: &str) -> Option<PathBuf> {
|
||||
let var = env::var_os(key)?;
|
||||
Some(PathBuf::from(var))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_path(key: &str) -> PathBuf {
|
||||
get_opt_path(key).unwrap_or_else(|| missing!(key))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_opt_str(key: &str) -> Option<String> {
|
||||
let var = env::var_os(key)?;
|
||||
match str::from_utf8(var.as_encoded_bytes()) {
|
||||
Ok(s) => Some(s.to_owned()),
|
||||
Err(err) => invalid!(key, err),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_str(key: &str) -> String {
|
||||
get_opt_str(key).unwrap_or_else(|| missing!(key))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_num<T: FromStr>(key: &str) -> T
|
||||
where
|
||||
T::Err: Display,
|
||||
{
|
||||
let val = get_str(key);
|
||||
match val.parse() {
|
||||
Ok(num) => num,
|
||||
Err(err) => invalid!(key, err),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_opt_cfg(cfg: &str) -> (String, Option<Vec<String>>) {
|
||||
let cfg = cfg.to_uppercase().replace('-', "_");
|
||||
let key = format!("CARGO_CFG_{cfg}");
|
||||
let Some(var) = env::var_os(&key) else {
|
||||
return (key, None);
|
||||
};
|
||||
let val = str::from_utf8(var.as_encoded_bytes()).unwrap_or_else(|err| invalid!(key, err));
|
||||
(key, Some(val.split(',').map(str::to_owned).collect()))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_cfg(cfg: &str) -> Vec<String> {
|
||||
let (key, val) = get_opt_cfg(cfg);
|
||||
val.unwrap_or_else(|| missing!(key))
|
||||
}
|
||||
|
||||
// docs last updated to match release 1.77.2 reference
|
||||
|
||||
/// Path to the `cargo` binary performing the build.
|
||||
pub fn cargo() -> PathBuf {
|
||||
get_path("CARGO")
|
||||
}
|
||||
|
||||
/// The directory containing the manifest for the package being built (the package
|
||||
/// containing the build script). Also note that this is the value of the current
|
||||
/// working directory of the build script when it starts.
|
||||
pub fn cargo_manifest_dir() -> PathBuf {
|
||||
get_path("CARGO_MANIFEST_DIR")
|
||||
}
|
||||
|
||||
/// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize
|
||||
/// subprocesses. Rustc or cargo invocations from build.rs can already read
|
||||
/// `CARGO_MAKEFLAGS`, but GNU Make requires the flags to be specified either
|
||||
/// directly as arguments, or through the `MAKEFLAGS` environment variable.
|
||||
/// Currently Cargo doesn’t set the `MAKEFLAGS` variable, but it’s free for build
|
||||
/// scripts invoking GNU Make to set it to the contents of `CARGO_MAKEFLAGS`.
|
||||
///
|
||||
/// [configuration option]: https://doc.rust-lang.org/reference/conditional-compilation.html
|
||||
/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html
|
||||
pub fn cargo_manifest_links() -> Option<String> {
|
||||
get_opt_str("CARGO_MANIFEST_LINKS")
|
||||
}
|
||||
|
||||
/// For each activated feature of the package being built, this will be `true`.
|
||||
pub fn cargo_feature(name: &str) -> bool {
|
||||
let name = name.to_uppercase().replace('-', "_");
|
||||
let key = format!("CARGO_FEATURE_{name}");
|
||||
get_bool(&key)
|
||||
}
|
||||
|
||||
/// For each [configuration option] of the package being built, this will contain
|
||||
/// the value of the configuration. This includes values built-in to the compiler
|
||||
/// (which can be seen with `rustc --print=cfg`) and values set by build scripts
|
||||
/// and extra flags passed to rustc (such as those defined in `RUSTFLAGS`).
|
||||
///
|
||||
/// [configuration option]: https://doc.rust-lang.org/stable/reference/conditional-compilation.html
|
||||
pub fn cargo_cfg(cfg: &str) -> Option<Vec<String>> {
|
||||
let key = format!("CARGO_CFG_{}", cfg.to_uppercase().replace('-', "_"));
|
||||
let val = env::var_os(&key)?.into_string().unwrap_or_else(|_| {
|
||||
panic!("cargo buildscript env var ${key} contained invalid UTF-8");
|
||||
});
|
||||
Some(val.split(',').map(Into::into).collect())
|
||||
let (_, val) = get_opt_cfg(cfg);
|
||||
val
|
||||
}
|
||||
|
||||
/// Each build script can generate an arbitrary set of metadata in the form of
|
||||
/// key-value pairs. This metadata is passed to the build scripts of
|
||||
/// **dependent** packages. For example, if the package `bar` depends on `foo`,
|
||||
/// then if `foo` generates `key=value` as part of its build script metadata,
|
||||
/// then the build script of `bar` will have the environment variables
|
||||
/// `DEP_FOO_KEY=value`.
|
||||
pub fn dep(name: &str, key: &str) -> Option<String> {
|
||||
let key = format!(
|
||||
"DEP_{}_{}",
|
||||
name.to_uppercase().replace('-', "_"),
|
||||
key.to_uppercase().replace('-', "_")
|
||||
);
|
||||
let val = env::var_os(&key)?.into_string().unwrap_or_else(|_| {
|
||||
panic!("cargo buildscript env var ${key} contained invalid UTF-8");
|
||||
});
|
||||
Some(val)
|
||||
/// Set on [unix-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).
|
||||
pub fn cargo_cfg_unix() -> bool {
|
||||
get_bool("CARGO_CFG_UNIX")
|
||||
}
|
||||
|
||||
/// Extra flags that Cargo invokes rustc with. See [`build.rustflags`]. Note
|
||||
/// that since Rust 1.55, `RUSTFLAGS` is removed from the environment; scripts
|
||||
/// should use `CARGO_ENCODED_RUSTFLAGS` instead.
|
||||
/// Set on [windows-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).
|
||||
pub fn cargo_cfg_windows() -> bool {
|
||||
get_bool("CARGO_CFG_WINDOWS")
|
||||
}
|
||||
|
||||
/// The [target family](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_family).
|
||||
pub fn cargo_target_family() -> Vec<String> {
|
||||
get_cfg("target_family")
|
||||
}
|
||||
|
||||
/// The [target operating system](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_os).
|
||||
/// This value is similar to the second and third element of the platform's target triple.
|
||||
pub fn cargo_cfg_target_os() -> String {
|
||||
get_str("CARGO_CFG_TARGET_OS")
|
||||
}
|
||||
|
||||
/// The CPU [target architecture](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_arch).
|
||||
/// This is similar to the first element of the platform's target triple, but not identical.
|
||||
pub fn cargo_cfg_target_arch() -> String {
|
||||
get_str("CARGO_CFG_TARGET_ARCH")
|
||||
}
|
||||
|
||||
/// The [target vendor](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_vendor).
|
||||
pub fn cargo_cfg_target_vendor() -> String {
|
||||
get_str("CARGO_CFG_TARGET_VENDOR")
|
||||
}
|
||||
|
||||
/// The [target environment](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_env) ABI.
|
||||
/// This value is similar to the fourth element of the platform's target triple.
|
||||
///
|
||||
/// [`build.rustflags`]: https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags
|
||||
pub fn cargo_encoded_rustflags() -> Vec<String> {
|
||||
let val = env::var_os("CARGO_ENCODED_RUSTFLAGS")
|
||||
.expect("cargo buildscript env var $CARGO_ENCODED_RUSTFLAGS")
|
||||
.into_string()
|
||||
.expect("cargo buildscript env var $CARGO_ENCODED_RUSTFLAGS contained invalid UTF-8");
|
||||
val.split('\x1f').map(Into::into).collect()
|
||||
/// For historical reasons, this value is only defined as not the empty-string when
|
||||
/// actually needed for disambiguation. Thus, for example, on many GNU platforms,
|
||||
/// this value will be empty.
|
||||
pub fn cargo_cfg_target_env() -> String {
|
||||
get_str("CARGO_CFG_TARGET_ENV")
|
||||
}
|
||||
|
||||
/// List of authors from the manifest of your package.
|
||||
pub fn cargo_pkg_authors() -> Vec<String> {
|
||||
let val = env::var_os("CARGO_PKG_AUTHORS")
|
||||
.expect("cargo buildscript env var $CARGO_PKG_AUTHORS")
|
||||
.into_string()
|
||||
.expect("cargo buildscript env var $CARGO_PKG_AUTHORS contained invalid UTF-8");
|
||||
val.split(':').map(Into::into).collect()
|
||||
/// The CPU [pointer width](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_pointer_width).
|
||||
pub fn cargo_cfg_target_pointer_width() -> u32 {
|
||||
get_num("CARGO_CFG_TARGET_POINTER_WIDTH")
|
||||
}
|
||||
|
||||
/// The CPU [target endianness](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_endian).
|
||||
pub fn cargo_cfg_target_endian() -> String {
|
||||
get_str("CARGO_CFG_TARGET_ENDIAN")
|
||||
}
|
||||
|
||||
/// List of CPU [target features](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_feature) enabled.
|
||||
pub fn cargo_cfg_target_feature() -> Vec<String> {
|
||||
get_cfg("target_feature")
|
||||
}
|
||||
|
||||
/// List of CPU [supported atomic widths](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_has_atomic).
|
||||
pub fn cargo_cfg_target_has_atomic() -> Vec<String> {
|
||||
get_cfg("target_has_atomic")
|
||||
}
|
||||
|
||||
/// List of atomic widths that have equal alignment requirements.
|
||||
///
|
||||
#[doc = unstable!(cfg_target_has_atomic_equal_alignment, 93822)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_target_has_atomic_equal_alignment() -> Vec<String> {
|
||||
get_cfg("target_has_atomic_equal_alignment")
|
||||
}
|
||||
|
||||
/// List of atomic widths that have atomic load and store operations.
|
||||
///
|
||||
#[doc = unstable!(cfg_target_has_atomic_load_store, 94039)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_target_has_atomic_load_store() -> Vec<String> {
|
||||
get_cfg("target_has_atomic_load_store")
|
||||
}
|
||||
|
||||
/// If the target supports thread-local storage.
|
||||
///
|
||||
#[doc = unstable!(cfg_target_thread_local, 29594)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_target_thread_local() -> bool {
|
||||
get_bool("CARGO_CFG_TARGET_THREAD_LOCAL")
|
||||
}
|
||||
|
||||
/// The [panic strategy](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#panic).
|
||||
pub fn cargo_cfg_panic() -> String {
|
||||
get_str("CARGO_CFG_PANIC")
|
||||
}
|
||||
|
||||
/// If we are compiling with debug assertions enabled.
|
||||
pub fn cargo_cfg_debug_assertions() -> bool {
|
||||
get_bool("CARGO_CFG_DEBUG_ASSERTIONS")
|
||||
}
|
||||
|
||||
/// If we are compiling with overflow checks enabled.
|
||||
///
|
||||
#[doc = unstable!(cfg_overflow_checks, 111466)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_overflow_checks() -> bool {
|
||||
get_bool("CARGO_CFG_OVERFLOW_CHECKS")
|
||||
}
|
||||
|
||||
/// If we are compiling with UB checks enabled.
|
||||
///
|
||||
#[doc = unstable!(cfg_ub_checks, 123499)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_ub_checks() -> bool {
|
||||
get_bool("CARGO_CFG_UB_CHECKS")
|
||||
}
|
||||
|
||||
/// The target relocation model.
|
||||
///
|
||||
#[doc = unstable!(cfg_relocation_model, 114929)]
|
||||
#[cfg(feature = "unstable")]
|
||||
pub fn cargo_cfg_relocation_model() -> String {
|
||||
get_str("CARGO_CFG_RELOCATION_MODEL")
|
||||
}
|
||||
|
||||
/// The folder in which all output and intermediate artifacts should be placed.
|
||||
/// This folder is inside the build directory for the package being built, and
|
||||
/// it is unique for the package in question.
|
||||
pub fn out_dir() -> PathBuf {
|
||||
get_path("OUT_DIR")
|
||||
}
|
||||
|
||||
/// The [target triple] that is being compiled for. Native code should be compiled
|
||||
/// for this triple.
|
||||
///
|
||||
/// [target triple]: https://doc.rust-lang.org/stable/cargo/appendix/glossary.html#target
|
||||
pub fn target() -> String {
|
||||
get_str("TARGET")
|
||||
}
|
||||
|
||||
/// The host triple of the Rust compiler.
|
||||
pub fn host() -> String {
|
||||
get_str("HOST")
|
||||
}
|
||||
|
||||
/// The parallelism specified as the top-level parallelism. This can be useful to
|
||||
/// pass a `-j` parameter to a system like `make`. Note that care should be taken
|
||||
/// when interpreting this value. For historical purposes this is still provided
|
||||
/// but Cargo, for example, does not need to run `make -j`, and instead can set the
|
||||
/// `MAKEFLAGS` env var to the content of `CARGO_MAKEFLAGS` to activate the use of
|
||||
/// Cargo’s GNU Make compatible [jobserver] for sub-make invocations.
|
||||
///
|
||||
/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html
|
||||
pub fn num_jobs() -> u32 {
|
||||
get_num("NUM_JOBS")
|
||||
}
|
||||
|
||||
/// The [level of optimization](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#opt-level).
|
||||
pub fn opt_level() -> String {
|
||||
get_str("OPT_LEVEL")
|
||||
}
|
||||
|
||||
/// The amount of [debug information](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#debug) included.
|
||||
pub fn debug() -> String {
|
||||
get_str("DEBUG")
|
||||
}
|
||||
|
||||
/// `release` for release builds, `debug` for other builds. This is determined based
|
||||
/// on if the [profile] inherits from the [`dev`] or [`release`] profile. Using this
|
||||
/// function is not recommended. Using other functions like [`opt_level`] provides
|
||||
/// a more correct view of the actual settings being used.
|
||||
///
|
||||
/// [profile]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html
|
||||
/// [`dev`]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html#dev
|
||||
/// [`release`]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html#release
|
||||
pub fn profile() -> String {
|
||||
get_str("PROFILE")
|
||||
}
|
||||
|
||||
/// [Metadata] set by dependencies. For more information, see build script
|
||||
/// documentation about [the `links` manifest key][links].
|
||||
///
|
||||
/// [metadata]: crate::output::metadata
|
||||
/// [links]: https://doc.rust-lang.org/stable/cargo/reference/build-scripts.html#the-links-manifest-key
|
||||
pub fn dep(name: &str, key: &str) -> Option<String> {
|
||||
let name = name.to_uppercase().replace('-', "_");
|
||||
let key = key.to_uppercase().replace('-', "_");
|
||||
let key = format!("DEP_{name}_{key}");
|
||||
get_opt_str(&key)
|
||||
}
|
||||
|
||||
/// The compiler that Cargo has resolved to use.
|
||||
pub fn rustc() -> PathBuf {
|
||||
get_path("RUSTC")
|
||||
}
|
||||
|
||||
/// The documentation generator that Cargo has resolved to use.
|
||||
pub fn rustdoc() -> PathBuf {
|
||||
get_path("RUSTDOC")
|
||||
}
|
||||
|
||||
/// The rustc wrapper, if any, that Cargo is using. See [`build.rustc-wrapper`].
|
||||
///
|
||||
/// [`build.rustc-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-wrapper
|
||||
pub fn rustc_wrapper() -> Option<PathBuf> {
|
||||
get_opt_path("RUSTC_WRAPPER")
|
||||
}
|
||||
|
||||
/// The rustc wrapper, if any, that Cargo is using for workspace members. See
|
||||
/// [`build.rustc-workspace-wrapper`].
|
||||
///
|
||||
/// [`build.rustc-workspace-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-workspace-wrapper
|
||||
pub fn rustc_workspace_wrapper() -> Option<PathBuf> {
|
||||
get_opt_path("RUSTC_WORKSPACE_WRAPPER")
|
||||
}
|
||||
|
||||
/// The linker that Cargo has resolved to use for the current target, if specified.
|
||||
///
|
||||
/// [`target.*.linker`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#targettriplelinker
|
||||
pub fn rustc_linker() -> Option<PathBuf> {
|
||||
get_opt_path("RUSTC_LINKER")
|
||||
}
|
||||
|
||||
/// Extra flags that Cargo invokes rustc with. See [`build.rustflags`].
|
||||
///
|
||||
/// [`build.rustflags`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustflags
|
||||
pub fn cargo_encoded_rustflags() -> Vec<String> {
|
||||
get_str("CARGO_ENCODED_RUSTFLAGS")
|
||||
.split('\x1f')
|
||||
.map(str::to_owned)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// The full version of your package.
|
||||
pub fn cargo_pkg_version() -> String {
|
||||
get_str("CARGO_PKG_VERSION")
|
||||
}
|
||||
|
||||
/// The major version of your package.
|
||||
pub fn cargo_pkg_version_major() -> u64 {
|
||||
get_num("CARGO_PKG_VERSION_MAJOR")
|
||||
}
|
||||
|
||||
/// The minor version of your package.
|
||||
pub fn cargo_pkg_version_minor() -> u64 {
|
||||
get_num("CARGO_PKG_VERSION_MINOR")
|
||||
}
|
||||
|
||||
/// The patch version of your package.
|
||||
pub fn cargo_pkg_version_patch() -> u64 {
|
||||
get_num("CARGO_PKG_VERSION_PATCH")
|
||||
}
|
||||
|
||||
/// The pre-release version of your package.
|
||||
pub fn cargo_pkg_version_pre() -> String {
|
||||
get_str("CARGO_PKG_VERSION_PRE")
|
||||
}
|
||||
|
||||
/// Colon separated list of authors from the manifest of your package.
|
||||
pub fn cargo_pkg_authors() -> Vec<String> {
|
||||
get_str("CARGO_PKG_AUTHORS")
|
||||
.split(':')
|
||||
.map(str::to_owned)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// The name of your package.
|
||||
pub fn cargo_pkg_name() -> String {
|
||||
get_str("CARGO_PKG_NAME")
|
||||
}
|
||||
|
||||
/// The description from the manifest of your package.
|
||||
pub fn cargo_pkg_description() -> String {
|
||||
get_str("CARGO_PKG_DESCRIPTION")
|
||||
}
|
||||
|
||||
/// The Rust version from the manifest of your package. Note that this is the
|
||||
/// minimum Rust version supported by the package, not the current Rust version.
|
||||
pub fn cargo_pkg_rust_version() -> String {
|
||||
get_str("CARGO_PKG_RUST_VERSION")
|
||||
}
|
||||
|
41
src/lib.rs
41
src/lib.rs
@ -1,21 +1,26 @@
|
||||
//! Convenience wrappers for cargo buildscript input/output.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! build::rerun_if_changed("build.rs"); // only rerun for buildscript changes
|
||||
//! build::rustc_cfg("has_buildrs"); // set #[cfg(has_buildrs)]
|
||||
//! dbg!(build::cargo()); // path to the cargo executable
|
||||
//! dbg!(build::cargo_manifest_dir()); // the directory of the build manifest
|
||||
//! ```
|
||||
//! build-rs provides a strongly typed interface around the Cargo build script
|
||||
//! protocol. Cargo provides inputs to the build script by environment variable
|
||||
//! and accepts commands by printing to stdout.
|
||||
#![cfg_attr(all(doc, feature = "unstable"), feature(doc_auto_cfg, doc_cfg))]
|
||||
|
||||
/// Inputs to the build script, in the form of environment variables.
|
||||
#[cfg(feature = "unstable")]
|
||||
macro_rules! unstable {
|
||||
($feature:ident, $issue:literal) => {
|
||||
concat!(
|
||||
r#"<div class="stab unstable">"#,
|
||||
r#"<span class="emoji">🔬</span>"#,
|
||||
r#"<span>This is a nightly-only experimental API. (<code>"#,
|
||||
stringify!($feature),
|
||||
r#"</code> <a href="https://github.com/rust-lang/rust/issues/"#,
|
||||
$issue,
|
||||
r#"">#"#,
|
||||
$issue,
|
||||
r#"</a>)</span>"#,
|
||||
r#"</div>"#
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
mod allow_use;
|
||||
pub mod input;
|
||||
/// Outputs from the build script, in the form of `cargo:` printed lines.
|
||||
///
|
||||
/// _Does not print a leading newline._ Thus, if you ever write to stdout and
|
||||
/// don't lock until a trailing newline, these instructions will likely fail.
|
||||
pub mod output;
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use crate::{input::*, output::*};
|
||||
|
387
src/output.rs
387
src/output.rs
@ -1,188 +1,315 @@
|
||||
use std::{ffi::OsStr, path::Path};
|
||||
//! Outputs from the build script to the build system.
|
||||
//!
|
||||
//! This crate assumes that stdout is at a new line whenever an output directive
|
||||
//! is called. Printing to stdout without a terminating newline (i.e. not using
|
||||
//! [`println!`]) may lead to surprising behavior.
|
||||
//!
|
||||
//! Reference: <https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script>
|
||||
|
||||
/// The rustc-link-arg instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option](https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg)
|
||||
/// to the compiler, but only when building supported targets (benchmarks,
|
||||
/// binaries, cdylib crates, examples, and tests). Its usage is highly platform
|
||||
/// specific. It is useful to set the shared library version or linker script.
|
||||
use crate::allow_use;
|
||||
use std::{ffi::OsStr, fmt::Display, path::Path, str};
|
||||
|
||||
fn emit(directive: &str, value: impl Display) {
|
||||
if allow_use::double_colon_directives() {
|
||||
println!("cargo::{}={}", directive, value);
|
||||
} else {
|
||||
println!("cargo:{}={}", directive, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// The `rerun-if-changed` instruction tells Cargo to re-run the build script if the
|
||||
/// file at the given path has changed. Currently, Cargo only uses the filesystem
|
||||
/// last-modified “mtime” timestamp to determine if the file has changed. It
|
||||
/// compares against an internal cached timestamp of when the build script last ran.
|
||||
///
|
||||
/// If the path points to a directory, it will scan the entire directory for any
|
||||
/// modifications.
|
||||
///
|
||||
/// If the build script inherently does not need to re-run under any circumstance,
|
||||
/// then calling `rerun_if_changed("build.rs")` is a simple way to prevent it from
|
||||
/// being re-run (otherwise, the default if no `rerun-if` instructions are emitted
|
||||
/// is to scan the entire package directory for changes). Cargo automatically
|
||||
/// handles whether or not the script itself needs to be recompiled, and of course
|
||||
/// the script will be re-run after it has been recompiled. Otherwise, specifying
|
||||
/// `build.rs` is redundant and unnecessary.
|
||||
pub fn rerun_if_changed(path: impl AsRef<Path>) {
|
||||
let Some(path) = path.as_ref().to_str() else {
|
||||
panic!("cannot emit rerun-if-changed: path is not UTF-8");
|
||||
};
|
||||
if path.contains('\n') {
|
||||
panic!("cannot emit rerun-if-changed: path contains newline");
|
||||
}
|
||||
emit("rerun-if-changed", path);
|
||||
}
|
||||
|
||||
/// The `rerun-if-env-changed` instruction tells Cargo to re-run the build script
|
||||
/// if the value of an environment variable of the given name has changed.
|
||||
///
|
||||
/// Note that the environment variables here are intended for global environment
|
||||
/// variables like `CC` and such, it is not possible to use this for environment
|
||||
/// variables like `TARGET` that [Cargo sets for build scripts][build-env]. The
|
||||
/// environment variables in use are those received by cargo invocations, not
|
||||
/// those received by the executable of the build script.
|
||||
///
|
||||
/// [build-env]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
|
||||
pub fn rerun_if_env_changed(key: impl AsRef<OsStr>) {
|
||||
let Some(key) = key.as_ref().to_str() else {
|
||||
panic!("cannot emit rerun-if-env-changed: key is not UTF-8");
|
||||
};
|
||||
if key.contains('\n') {
|
||||
panic!("cannot emit rerun-if-env-changed: key contains newline");
|
||||
}
|
||||
emit("rerun-if-env-changed", key);
|
||||
}
|
||||
|
||||
/// The `rustc-link-arg` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// supported targets (benchmarks, binaries, cdylib crates, examples, and tests).
|
||||
/// Its usage is highly platform specific. It is useful to set the shared library
|
||||
/// version or linker script.
|
||||
///
|
||||
/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg
|
||||
pub fn rustc_link_arg(flag: &str) {
|
||||
println!("cargo:rustc-link-arg={flag}");
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-link-arg: invalid flag");
|
||||
}
|
||||
emit("rustc-link-arg", flag);
|
||||
}
|
||||
|
||||
/// The `rustc-link-arg-bin` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option](https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg)
|
||||
/// to the compiler, but only when building the binary target with name `BIN`.
|
||||
/// Its usage is highly platform specific. It is useful to set a linker script
|
||||
/// or other linker options.
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// the binary target with name `BIN`. Its usage is highly platform specific. It
|
||||
/// is useful to set a linker script or other linker options.
|
||||
///
|
||||
/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg
|
||||
pub fn rustc_link_arg_bin(bin: &str, flag: &str) {
|
||||
println!("cargo:rustc-link-arg-bin={bin}={flag}");
|
||||
if bin.contains(['=', '\n']) {
|
||||
panic!("cannot emit rustc-link-arg-bin: invalid bin name");
|
||||
}
|
||||
emit("rustc-link-arg-bin", format_args!("{}={}", bin, flag));
|
||||
}
|
||||
|
||||
/// The `rustc-link-arg-bins` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option](https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg)
|
||||
/// to the compiler, but only when building a binary target. Its usage is
|
||||
/// highly platform specific. It is useful to set a linker script or other
|
||||
/// linker options.
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// the binary target. Its usage is highly platform specific. It is useful to set
|
||||
/// a linker script or other linker options.
|
||||
///
|
||||
/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg
|
||||
pub fn rustc_link_arg_bins(flag: &str) {
|
||||
println!("cargo:rustc-link-arg-bins={flag}");
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-link-arg-bins: invalid flag");
|
||||
}
|
||||
emit("rustc-link-arg-bins", flag);
|
||||
}
|
||||
|
||||
/// The `rustc-link-lib` instruction tells Cargo to link the given library
|
||||
/// using the compiler's [`-l` flag]. This is typically used to link a native
|
||||
/// library using [`FFI`].
|
||||
///
|
||||
/// The `-l` flag is only passed to the library target of the package, unless
|
||||
/// there is no library target, in which case it is passed to all targets. This
|
||||
/// is done because all other targets have an implicit dependency on the
|
||||
/// library target, and the given library to link should only be included once.
|
||||
/// This means that if a package has both a library and a binary target, the
|
||||
/// _library_ has access to the symbols from the given lib, and the binary
|
||||
/// should access them through the library target's public API.
|
||||
///
|
||||
/// The optional `KIND` may be one of `dylib`, `static`, or `framework`.
|
||||
/// See the [rustc book] for more detail.
|
||||
///
|
||||
/// [`-l` flag]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-l-link-lib
|
||||
/// [rustc book]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-l-link-lib
|
||||
pub fn rustc_link_lib(name: &str) {
|
||||
println!("cargo:rustc-link-lib={name}");
|
||||
/// The `rustc-link-arg-tests` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// a tests target.
|
||||
pub fn rustc_link_arg_tests(flag: &str) {
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-link-arg-tests: invalid flag");
|
||||
}
|
||||
emit("rustc-link-arg-tests", flag);
|
||||
}
|
||||
|
||||
/// See [`rustc_link_lib`].
|
||||
pub fn rustc_link_lib_kind(kind: &str, name: &str) {
|
||||
println!("cargo:rustc-link-lib={kind}={name}");
|
||||
/// The `rustc-link-arg-examples` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// an examples target.
|
||||
pub fn rustc_link_arg_examples(flag: &str) {
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-link-arg-examples: invalid flag");
|
||||
}
|
||||
emit("rustc-link-arg-examples", flag);
|
||||
}
|
||||
|
||||
/// The `rustc-link-search` instruction tells Cargo to pass the [`-L flag`] to
|
||||
/// the compiler to add a directory to the library search path.
|
||||
/// The `rustc-link-arg-benches` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// a benchmark target.
|
||||
pub fn rustc_link_arg_benches(flag: &str) {
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-link-arg-benches: invalid flag");
|
||||
}
|
||||
emit("rustc-link-arg-benches", flag);
|
||||
}
|
||||
|
||||
/// The `rustc-link-lib` instruction tells Cargo to link the given library using
|
||||
/// the compiler’s [`-l` flag][-l]. This is typically used to link a native library
|
||||
/// using [FFI].
|
||||
///
|
||||
/// The optional `KIND` may be one of `dependency`, `crate`, `native`,
|
||||
/// `framework`, or `all`. See the [rustc book] for more detail.
|
||||
/// The `LIB` string is passed directly to rustc, so it supports any syntax that
|
||||
/// `-l` does. Currently the full supported syntax for `LIB` is
|
||||
/// `[KIND[:MODIFIERS]=]NAME[:RENAME]`.
|
||||
///
|
||||
/// The `-l` flag is only passed to the library target of the package, unless there
|
||||
/// is no library target, in which case it is passed to all targets. This is done
|
||||
/// because all other targets have an implicit dependency on the library target,
|
||||
/// and the given library to link should only be included once. This means that
|
||||
/// if a package has both a library and a binary target, the library has access
|
||||
/// to the symbols from the given lib, and the binary should access them through
|
||||
/// the library target’s public API.
|
||||
///
|
||||
/// The optional `KIND` may be one of dylib, static, or framework. See the
|
||||
/// [rustc book][-l] for more detail.
|
||||
///
|
||||
/// [-l]: https://doc.rust-lang.org/stable/rustc/command-line-arguments.html#option-l-link-lib
|
||||
/// [FFI]: https://doc.rust-lang.org/stable/nomicon/ffi.html
|
||||
pub fn rustc_link_lib(lib: &str) {
|
||||
if lib.contains('\n') {
|
||||
panic!("cannot emit rustc-link-lib: invalid lib");
|
||||
}
|
||||
emit("rustc-link-lib", lib);
|
||||
}
|
||||
|
||||
/// Like [`rustc_link_lib`], but with KIND specified separately.
|
||||
pub fn rustc_link_lib_kind(kind: &str, lib: &str) {
|
||||
if kind.contains(['=', '\n']) {
|
||||
panic!("cannot emit rustc-link-lib: invalid kind");
|
||||
}
|
||||
if lib.contains('\n') {
|
||||
panic!("cannot emit rustc-link-lib: invalid lib");
|
||||
}
|
||||
emit("rustc-link-lib", format_args!("{kind}={lib}"));
|
||||
}
|
||||
|
||||
/// The `rustc-link-search` instruction tells Cargo to pass the [`-L` flag] to the
|
||||
/// compiler to add a directory to the library search path.
|
||||
///
|
||||
/// The optional `KIND` may be one of `dependency`, `crate`, `native`, `framework`,
|
||||
/// or `all`. See the [rustc book][-L] for more detail.
|
||||
///
|
||||
/// These paths are also added to the
|
||||
/// [dynamic library search path environment variable] if they are within the
|
||||
/// `OUT_DIR`. Depending on this behavior is discouraged since this makes it
|
||||
/// difficult to use the resulting binary. In general, it is best to avoid
|
||||
/// creating dynamic libraries in a build script (using existing system
|
||||
/// [dynamic library search path environment variable][search-path] if they are
|
||||
/// within the `OUT_DIR`. Depending on this behavior is discouraged since this
|
||||
/// makes it difficult to use the resulting binary. In general, it is best to
|
||||
/// avoid creating dynamic libraries in a build script (using existing system
|
||||
/// libraries is fine).
|
||||
///
|
||||
/// [`-L flag`]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-l-search-path
|
||||
/// [rustc book]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-l-search-path
|
||||
/// [dynamic library search path environment variable]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#dynamic-library-paths
|
||||
/// [-L]: https://doc.rust-lang.org/stable/rustc/command-line-arguments.html#option-l-search-path
|
||||
/// [search-path]: https://doc.rust-lang.org/stable/cargo/reference/environment-variables.html#dynamic-library-paths
|
||||
pub fn rustc_link_search(path: impl AsRef<Path>) {
|
||||
let path = path
|
||||
.as_ref()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.expect("cannot print non-UTF8 path");
|
||||
println!("cargo:rustc-link-search={path}");
|
||||
let Some(path) = path.as_ref().to_str() else {
|
||||
panic!("cannot emit rustc-link-search: path is not UTF-8");
|
||||
};
|
||||
if path.contains('\n') {
|
||||
panic!("cannot emit rustc-link-search: path contains newline");
|
||||
}
|
||||
emit("rustc-link-search", path);
|
||||
}
|
||||
|
||||
/// See [`rustc_link_search`].
|
||||
/// Like [`rustc_link_search`], but with KIND specified separately.
|
||||
pub fn rustc_link_search_kind(kind: &str, path: impl AsRef<Path>) {
|
||||
let path = path
|
||||
.as_ref()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.expect("cannot print non-UTF8 path");
|
||||
println!("cargo:rustc-link-search={kind}={path}");
|
||||
if kind.contains(['=', '\n']) {
|
||||
panic!("cannot emit rustc-link-search: invalid kind");
|
||||
}
|
||||
let Some(path) = path.as_ref().to_str() else {
|
||||
panic!("cannot emit rustc-link-search: path is not UTF-8");
|
||||
};
|
||||
if path.contains('\n') {
|
||||
panic!("cannot emit rustc-link-search: path contains newline");
|
||||
}
|
||||
emit("rustc-link-search", format_args!("{kind}={path}"));
|
||||
}
|
||||
|
||||
/// The `rustc-flags` instruction tells Cargo to pass the given space-separated
|
||||
/// flags to the compiler. This only allows the `-l` and `-L` flags, and is
|
||||
/// equivalent to using `rustc-link-lib` and `rustc-link-search`.
|
||||
/// equivalent to using [`rustc_link_lib`] and [`rustc_link_search`].
|
||||
pub fn rustc_flags(flags: &str) {
|
||||
println!("cargo:rustc-flags={flags}");
|
||||
if flags.contains('\n') {
|
||||
panic!("cannot emit rustc-flags: invalid flags");
|
||||
}
|
||||
emit("rustc-flags", flags);
|
||||
}
|
||||
|
||||
/// The `rustc-cfg` instruction tells Cargo to pass the given value to the
|
||||
/// [`--cfg` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html#option-cfg)
|
||||
/// to the compiler. This may be used for compile-time detection of features to
|
||||
/// enable [conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html).
|
||||
/// [`--cfg` flag][--cfg] to the compiler. This may be used for compile-time
|
||||
/// detection of features to enable conditional compilation.
|
||||
///
|
||||
/// Note that this does not affect Cargo's dependency resolution. This cannot
|
||||
/// Note that this does not affect Cargo’s dependency resolution. This cannot
|
||||
/// be used to enable an optional dependency, or enable other Cargo features.
|
||||
///
|
||||
/// Be aware that Cargo features use the form `feature="foo"`. `cfg` values
|
||||
/// Be aware that [Cargo features] use the form `feature="foo"`. `cfg` values
|
||||
/// passed with this flag are not restricted to that form, and may provide just
|
||||
/// a single identifier, or any arbitrary key/value pair. For example, emitting
|
||||
/// `cargo:rustc-cfg=abc` will then allow code to use `#[cfg(abc)]` (note the
|
||||
/// lack of `feature=`). Or an arbitrary key/value pair may be used with an `=`
|
||||
/// symbol like `cargo:rustc-cfg=my_component="foo"`. The key should be a Rust
|
||||
/// identifier, the value should be a string.
|
||||
/// `rustc_cfg("abc")` will then allow code to use `#[cfg(abc)]` (note the lack
|
||||
/// of `feature=`). Or an arbitrary key/value pair may be used with an `=` symbol
|
||||
/// like `rustc_cfg(r#"my_component="foo""#)`. The key should be a Rust identifier,
|
||||
/// the value should be a string.
|
||||
///
|
||||
/// [--cfg]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-cfg
|
||||
/// [Cargo features]: https://doc.rust-lang.org/cargo/reference/features.html
|
||||
pub fn rustc_cfg(key: &str) {
|
||||
println!("cargo:rustc-cfg={key}")
|
||||
if key.contains('\n') {
|
||||
panic!("cannot emit rustc-cfg: invalid key");
|
||||
}
|
||||
emit("rustc-cfg", key);
|
||||
}
|
||||
|
||||
/// See [`rustc_cfg`].
|
||||
/// Like [`rustc_cfg`], but with the value specified separately.
|
||||
pub fn rustc_cfg_value(key: &str, value: &str) {
|
||||
println!("cargo:rustc-cfg={key}={value}");
|
||||
let value = value.escape_default();
|
||||
if key.contains(['=', '\n']) {
|
||||
panic!("cannot emit rustc-cfg-value: invalid key");
|
||||
}
|
||||
emit("rustc-cfg", format_args!("{key}=\"{value}\""));
|
||||
}
|
||||
|
||||
/// The `rustc-env` instruction tells Cargo to set the given environment
|
||||
/// variable when compiling the package. The value can be then retrieved by the
|
||||
/// [`env! macro`](env!) in the compiled crate. This is useful for embedding
|
||||
/// additional metadata in crate's code, such as the hash of git HEAD or the
|
||||
/// The `rustc-env` instruction tells Cargo to set the given environment variable
|
||||
/// when compiling the package. The value can be then retrieved by the
|
||||
/// [`env!` macro][env!] in the compiled crate. This is useful for embedding
|
||||
/// additional metadata in crate’s code, such as the hash of git HEAD or the
|
||||
/// unique identifier of a continuous integration server.
|
||||
pub fn rustc_env(var: &str, value: &str) {
|
||||
println!("cargo:rustc-env={var}={value}");
|
||||
///
|
||||
/// See also the [environment variables automatically included by Cargo][cargo-env].
|
||||
///
|
||||
/// [cargo-env]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
|
||||
pub fn rustc_env(key: &str, value: &str) {
|
||||
if key.contains(['=', '\n']) {
|
||||
panic!("cannot emit rustc-env: invalid key");
|
||||
}
|
||||
if value.contains('\n') {
|
||||
panic!("cannot emit rustc-env: invalid value");
|
||||
}
|
||||
emit("rustc-env", format_args!("{key}={value}"));
|
||||
}
|
||||
|
||||
/// The `rustc-cdylib-link-arg` instruction tells Cargo to pass the
|
||||
/// [`-C link-arg=FLAG` option](https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg)
|
||||
/// to the compiler, but only when building a cdylib library target. Its usage
|
||||
/// is highly platform specific. It is useful to set the shared library version
|
||||
/// or the runtime-path.
|
||||
/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building
|
||||
/// a `cdylib` library target. Its usage is highly platform specific. It is useful
|
||||
/// to set the shared library version or the runtime-path.
|
||||
///
|
||||
/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg
|
||||
pub fn rustc_cdylib_link_arg(flag: &str) {
|
||||
println!("cargo:rustc-cdylib-link-arg={flag}");
|
||||
if flag.contains('\n') {
|
||||
panic!("cannot emit rustc-cdylib-link-arg: invalid flag");
|
||||
}
|
||||
emit("rustc-cdylib-link-arg", flag);
|
||||
}
|
||||
|
||||
/// The `warning` instruction tells Cargo to display a warning after the build
|
||||
/// script has finished running. Warnings are only shown for path dependencies
|
||||
/// (that is, those you're working on locally), so for example warnings printed
|
||||
/// out in crates.io crates are not emitted by default. The `-vv` "very verbose"
|
||||
/// (that is, those you’re working on locally), so for example warnings printed
|
||||
/// out in [crates.io] crates are not emitted by default. The `-vv` “very verbose”
|
||||
/// flag may be used to have Cargo display warnings for all crates.
|
||||
///
|
||||
/// [crates.io]: https://crates.io/
|
||||
pub fn warning(message: &str) {
|
||||
println!("cargo:warning={message}");
|
||||
if message.contains('\n') {
|
||||
panic!("cannot emit warning: message contains newline");
|
||||
}
|
||||
emit("warning", message);
|
||||
}
|
||||
|
||||
/// The `rerun-if-changed` instruction tells Cargo to re-run the build script
|
||||
/// if the file at the given path has changed. Currently, Cargo only uses the
|
||||
/// filesystem last-modified "mtime" timestamp to determine if the file has
|
||||
/// changed. It compares against an internal cached timestamp of when the build
|
||||
/// script last ran.
|
||||
///
|
||||
/// If the path points to a directory, it will scan the entire directory for
|
||||
/// any modifications.
|
||||
///
|
||||
/// If the build script inherently does not need to re-run under any
|
||||
/// circumstance, then emitting `cargo:rerun-if-changed=build.rs` is a simple
|
||||
/// way to prevent it from being re-run (otherwise, the default if no
|
||||
/// `rerun-if` instructions are emitted is to scan the entire package
|
||||
/// directory for changes). Cargo automatically handles whether or not the
|
||||
/// script itself needs to be recompiled, and of course the script will be
|
||||
/// re-run after it has been recompiled. Otherwise, specifying build.rs is
|
||||
/// redundant and unnecessary.
|
||||
pub fn rerun_if_changed(path: impl AsRef<Path>) {
|
||||
let path = path
|
||||
.as_ref()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.expect("cannot print non-UTF8 path");
|
||||
println!("cargo:rerun-if-changed={path}");
|
||||
}
|
||||
|
||||
/// The `rerun-if-env-changed` instruction tells Cargo to re-run the build
|
||||
/// script if the value of an environment variable of the given name has
|
||||
/// changed.
|
||||
///
|
||||
/// Note that the environment variables here are intended for global
|
||||
/// environment variables like `CC` and such, it is not necessary to use this
|
||||
/// for environment variables like `TARGET` that Cargo sets.
|
||||
pub fn rerun_if_env_changed(name: impl AsRef<OsStr>) {
|
||||
let name = name
|
||||
.as_ref()
|
||||
.to_str()
|
||||
.expect("cannot print non-UTF8 env key");
|
||||
println!("cargo:rerun-if-env-changed={name}");
|
||||
/// Metadata, used by `links` scripts.
|
||||
pub fn metadata(key: &str, val: &str) {
|
||||
if key.contains(['=', '\n']) {
|
||||
panic!("cannot emit metadata: invalid key");
|
||||
}
|
||||
if val.contains('\n') {
|
||||
panic!("cannot emit metadata: invalid value");
|
||||
}
|
||||
if allow_use::double_colon_directives() {
|
||||
emit("metadata", format_args!("{}={}", key, val));
|
||||
} else {
|
||||
emit(key, val);
|
||||
}
|
||||
}
|
||||
|
9
test-lib/Cargo.toml
Normal file
9
test-lib/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "build-rs-test-lib"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
publish = false
|
||||
|
||||
[build-dependencies]
|
||||
build-rs = { path = ".." }
|
4
test-lib/build.rs
Normal file
4
test-lib/build.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
build_rs::output::rerun_if_changed("build.rs");
|
||||
build_rs::output::rustc_cfg("did_run_build_script");
|
||||
}
|
4
test-lib/src/lib.rs
Normal file
4
test-lib/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[test]
|
||||
fn test() {
|
||||
assert!(cfg!(did_run_build_script));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user