Skip to content

Commit

Permalink
Convert shell scripts to Rust
Browse files Browse the repository at this point in the history
`cargo.sh` is now a thin wrapper around a new `cargo-zerocopy` tool
located in the `tools` directory. README generation is now done by a
similar `generate-readme` tool. A wrapper script for running
`cargo-zerocopy` on Windows has been added as `win-cargo.bat`,
effectively allowing the test suites to be run on Windows.
  • Loading branch information
djkoloski committed Feb 22, 2024
1 parent 65c080c commit 610a38a
Show file tree
Hide file tree
Showing 13 changed files with 404 additions and 196 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Copyright 2022 The Fuchsia Authors
<!-- Copyright 2024 The Fuchsia Authors
Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
Expand All @@ -7,7 +7,7 @@ This file may not be copied, modified, or distributed except according to
those terms.
WARNING: DO NOT EDIT THIS FILE. It is generated automatically. Edits should be
made in the doc comment on `src/lib.rs` or in `generate-readme.sh`.
made in the doc comment on `src/lib.rs` or in `tools/generate-readme`.
-->

# zerocopy
Expand Down
133 changes: 5 additions & 128 deletions cargo.sh
Original file line number Diff line number Diff line change
@@ -1,135 +1,12 @@
#!/bin/bash
#
# Copyright 2023 The Fuchsia Authors
# Copyright 2024 The Fuchsia Authors
#
# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

# This script is a thin wrapper around Cargo that provides human-friendly
# toolchain names which are automatically translated to the toolchain versions
# we have pinned in CI.
#
# cargo.sh --version <toolchain-name> # looks up the version for the named toolchain
# cargo.sh +<toolchain-name> [...] # runs cargo commands with the named toolchain
# cargo.sh +all [...] # runs cargo commands with each toolchain
#
# The meta-toolchain "all" instructs this script to run the provided command
# once for each "major" toolchain (msrv, stable, nightly). This does not include
# any toolchain which is listed in the `package.metadata.build-rs` Cargo.toml
# section.
#
# A common task that is especially annoying to perform by hand is to update
# trybuild's stderr files. Using this script:
#
# TRYBUILD=overwrite ./cargo.sh +all test --workspace

set -eo pipefail

function print-usage-and-exit {
echo "Usage:" >&2
echo " $0 --version <toolchain-name>" >&2
echo " $0 +<toolchain-name> [...]" >&2
echo " $0 +all [...]" >&2
exit 1
}

[[ $# -gt 0 ]] || print-usage-and-exit

function pkg-meta {
# NOTE(#547): We set `CARGO_TARGET_DIR` here because `cargo metadata`
# sometimes causes the `cargo-metadata` crate to be rebuilt from source using
# the default toolchain. This has the effect of clobbering any existing build
# artifacts from whatever toolchain the user has specified (e.g., `+nightly`),
# causing the subsequent `cargo` invocation to rebuild unnecessarily. By
# specifying a separate build directory here, we ensure that this never
# clobbers the build artifacts used by the later `cargo` invocation.
#
# In CI, make sure to use the default stable toolchain. If we're testing on
# our MSRV, then we also have our MSRV toolchain installed. As of this
# writing, our MSRV is low enough that the correspoding Rust toolchain's Cargo
# doesn't know about the `rust-version` field, and so if we were to use Cargo
# with that toolchain, `pkg-meta` would return `null` when asked to retrieve
# the `rust-version` field. This also requires `RUSTFLAGS=''` to override any
# unstable `RUSTFLAGS` set by the caller.
RUSTFLAGS='' CARGO_TARGET_DIR=target/cargo-sh cargo +stable metadata --format-version 1 | jq -r ".packages[] | select(.name == \"zerocopy\").$1"
}

function lookup-version {
VERSION="$1"
case "$VERSION" in
msrv)
pkg-meta rust_version
;;
stable)
pkg-meta 'metadata.ci."pinned-stable"'
;;
nightly)
pkg-meta 'metadata.ci."pinned-nightly"'
;;
*)
TOOLCHAIN=$(pkg-meta "metadata.\"build-rs\".\"${VERSION}\"")
if [ "$TOOLCHAIN" != "null" ]; then
echo "$TOOLCHAIN"
else
echo "Unrecognized toolchain name: '$VERSION' (options are 'msrv', 'stable', 'nightly', and any value in Cargo.toml's 'metadata.build-rs' table)" >&2
return 1
fi
;;
esac
}

function get-rustflags {
[ "$1" == nightly ] && echo "--cfg __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS"
}

function prompt {
PROMPT="$1"
YES="$2"
while true; do
read -p "$PROMPT " yn
case "$yn" in
[Yy]) $YES; return $?; ;;
[Nn]) return 1; ;;
*) break; ;;
esac
done
}

case "$1" in
# cargo.sh --version <toolchain-name>
--version)
[[ $# -eq 2 ]] || print-usage-and-exit
lookup-version "$2"
;;
# cargo.sh +all [...]
+all)
echo "[cargo.sh] warning: running the same command for each toolchain (msrv, stable, nightly)" >&2
for toolchain in msrv stable nightly; do
echo "[cargo.sh] running with toolchain: $toolchain" >&2
$0 "+$toolchain" ${@:2}
done
exit 0
;;
# cargo.sh +<toolchain-name> [...]
+*)
TOOLCHAIN="$(lookup-version ${1:1})"

cargo "+$TOOLCHAIN" version &>/dev/null && \
rustup "+$TOOLCHAIN" component list | grep '^rust-src (installed)$' >/dev/null || {
echo "[cargo.sh] missing either toolchain '$TOOLCHAIN' or component 'rust-src'" >&2
# If we're running in a GitHub action, then it's better to bail than to
# hang waiting for input we're never going to get.
[ -z ${GITHUB_RUN_ID+x} ] || exit 1
prompt "[cargo.sh] would you like to install toolchain '$TOOLCHAIN' and component 'rust-src' via 'rustup'?" \
"rustup toolchain install $TOOLCHAIN -c rust-src"
} || exit 1

RUSTFLAGS="$(get-rustflags ${1:1}) $RUSTFLAGS" cargo "+$TOOLCHAIN" ${@:2}
;;
*)
print-usage-and-exit
;;
esac
# Build `cargo-zerocopy` without any RUSTFLAGS set in the environment
env -u RUSTFLAGS cargo +stable build --manifest-path tools/Cargo.toml -p cargo-zerocopy -q
# Thin wrapper around the `cargo-zerocopy` binary in `tools/cargo-zerocopy`
./tools/target/debug/cargo-zerocopy $@
2 changes: 1 addition & 1 deletion ci/check_readme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ set -eo pipefail
# suppress all errors from it.
cargo install cargo-readme --version 3.2.0 -q

diff <(./generate-readme.sh) README.md
diff <(cargo -q run --manifest-path tools/Cargo.toml -p generate-readme) README.md
exit $?
50 changes: 0 additions & 50 deletions generate-readme.sh

This file was deleted.

12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// After updating the following doc comment, make sure to run the following
// command to update `README.md` based on its contents:
//
// ./generate-readme.sh > README.md
// cargo -q run --manifest-path tools/Cargo.toml -p generate-readme > README.md

//! *<span style="font-size: 100%; color:grey;">Need more out of zerocopy?
//! Submit a [customer request issue][customer-request-issue]!</span>*
Expand Down Expand Up @@ -164,7 +164,7 @@
variant_size_differences
)]
#![cfg_attr(
__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS,
__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
deny(fuzzy_provenance_casts, lossy_provenance_casts)
)]
#![deny(
Expand Down Expand Up @@ -233,7 +233,7 @@
)]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(
__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS,
__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
feature(layout_for_ptr, strict_provenance)
)]

Expand Down Expand Up @@ -318,9 +318,9 @@ pub use crate::pointer::{Maybe, MaybeAligned, Ptr};
use crate::util::polyfills::NonNullExt as _;

#[rustversion::nightly]
#[cfg(all(test, not(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)))]
#[cfg(all(test, not(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)))]
const _: () = {
#[deprecated = "some tests may be skipped due to missing RUSTFLAGS=\"--cfg __INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS\""]
#[deprecated = "some tests may be skipped due to missing RUSTFLAGS=\"--cfg __INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS\""]
const _WARNING: () = ();
#[warn(deprecated)]
_WARNING
Expand Down Expand Up @@ -6243,7 +6243,7 @@ mod tests {
}

#[test]
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
fn test_validate_rust_layout() {
use core::ptr::NonNull;

Expand Down
14 changes: 7 additions & 7 deletions src/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use core::{marker::PhantomData, mem::ManuallyDrop};

// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
use core::ptr::{self, NonNull};

/// A compile-time check that should be one particular value.
Expand Down Expand Up @@ -70,7 +70,7 @@ const _64K: usize = 1 << 16;

// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[repr(C, align(65536))]
struct Aligned64kAllocation([u8; _64K]);

Expand All @@ -82,7 +82,7 @@ struct Aligned64kAllocation([u8; _64K]);
/// allocation with size and alignment 2^16, and to have valid provenance.
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = {
const REF: &Aligned64kAllocation = &Aligned64kAllocation([0; _64K]);
let ptr: *const Aligned64kAllocation = REF;
Expand Down Expand Up @@ -111,7 +111,7 @@ pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = {
/// `trailing_field_offset!` produces code which is valid in a `const` context.
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
#[macro_export]
macro_rules! trailing_field_offset {
Expand Down Expand Up @@ -211,7 +211,7 @@ macro_rules! trailing_field_offset {
/// `align_of!` produces code which is valid in a `const` context.
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this
// `cfg` when `size_of_val_raw` is stabilized.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
#[macro_export]
macro_rules! align_of {
Expand Down Expand Up @@ -477,7 +477,7 @@ mod tests {
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove
// this `cfg` when `size_of_val_raw` is stabilized.
#[allow(clippy::decimal_literal_representation)]
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[test]
fn test_trailing_field_offset() {
assert_eq!(mem::align_of::<Aligned64kAllocation>(), _64K);
Expand Down Expand Up @@ -579,7 +579,7 @@ mod tests {
// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove
// this `cfg` when `size_of_val_raw` is stabilized.
#[allow(clippy::decimal_literal_representation)]
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[test]
fn test_align_of_dst() {
// Test that `align_of!` correctly computes the alignment of DSTs.
Expand Down
4 changes: 2 additions & 2 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl<T: ?Sized> AsAddress for *const T {
// `.addr()` instead of `as usize` once it's stable, and get rid of this
// `allow`. Currently, `as usize` is the only way to accomplish this.
#[allow(clippy::as_conversions)]
#[cfg_attr(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS, allow(lossy_provenance_casts))]
#[cfg_attr(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, allow(lossy_provenance_casts))]
return self.cast::<()>() as usize;
}
}
Expand Down Expand Up @@ -311,7 +311,7 @@ mod proofs {

// Restricted to nightly since we use the unstable `usize::next_multiple_of`
// in our model implementation.
#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)]
#[cfg(__INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)]
#[kani::proof]
fn prove_padding_needed_for() {
fn model_impl(len: usize, align: NonZeroUsize) -> usize {
Expand Down
25 changes: 25 additions & 0 deletions tools/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2018 The Fuchsia Authors
#
# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

[workspace]
members = [
"cargo-zerocopy",
"generate-readme",
]
resolver = "2"

[workspace.package]
edition = "2021"
version = "0.0.0"
authors = ["Joshua Liebow-Feeser <[email protected]>"]
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
publish = false

[workspace.dependencies]
regex = "1"
serde_json = "1"
18 changes: 18 additions & 0 deletions tools/cargo-zerocopy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2024 The Fuchsia Authors
#
# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

[package]
edition.workspace = true
name = "cargo-zerocopy"
version.workspace = true
authors.workspace = true
license.workspace = true
publish.workspace = true

[dependencies]
serde_json.workspace = true
Loading

0 comments on commit 610a38a

Please sign in to comment.