Skip to content

Commit be24a36

Browse files
committed
Fix build error with targets that do not have atomic CAS
Some no-std targets do not have atomic CAS and cannot use Arc, etc. This patch detects those targets using the TARGET environment variables provided by cargo for the build script, and a list of targets that do not have atomic CAS. This is a port of rust-lang/futures-rs#2400. See that PR for more.
1 parent 5a8c1a6 commit be24a36

File tree

9 files changed

+99
-3
lines changed

9 files changed

+99
-3
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ jobs:
2525
strategy:
2626
matrix:
2727
target:
28-
# TODO: Currently, valuable cannot build with targets that do not have atomic CAS.
29-
# We should port https://github.com/rust-lang/futures-rs/pull/2400.
30-
# - thumbv6m-none-eabi
28+
- thumbv6m-none-eabi
3129
- thumbv7m-none-eabi
3230
runs-on: ubuntu-latest
3331
steps:
@@ -58,6 +56,19 @@ jobs:
5856
# run: cargo install cargo-hack
5957
# - run: cargo hack build --workspace --feature-powerset --no-dev-deps
6058

59+
# When this job failed, run ci/no_atomic_cas.sh and commit result changes.
60+
# TODO(taiki-e): Ideally, this should be automated using a bot that creates
61+
# PR when failed, but there is no bandwidth to implement it
62+
# right now...
63+
codegen:
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v2
67+
- name: Install Rust
68+
run: rustup update nightly && rustup default nightly
69+
- run: ci/no_atomic_cas.sh
70+
- run: git diff --exit-code
71+
6172
fmt:
6273
runs-on: ubuntu-latest
6374
steps:

ci/no_atomic_cas.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
# Update the list of targets that do not have atomic CAS (compare-and-swap).
4+
#
5+
# Usage:
6+
# ./ci/no_atomic_cas.sh
7+
8+
set -euo pipefail
9+
IFS=$'\n\t'
10+
11+
cd "$(cd "$(dirname "$0")" && pwd)"/..
12+
13+
file="valuable/no_atomic_cas.rs"
14+
15+
{
16+
echo "// This file is @generated by $(basename "$0")."
17+
echo "// It is not intended for manual editing."
18+
echo ""
19+
echo "const NO_ATOMIC_CAS_TARGETS: &[&str] = &["
20+
} >"$file"
21+
22+
for target in $(rustc --print target-list); do
23+
res=$(rustc --print target-spec-json -Z unstable-options --target "$target" \
24+
| jq -r "select(.\"atomic-cas\" == false)")
25+
[[ -z "$res" ]] || echo " \"$target\"," >>"$file"
26+
done
27+
28+
echo "];" >>"$file"

valuable/build.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![warn(rust_2018_idioms, single_use_lifetimes)]
2+
3+
use std::env;
4+
5+
include!("no_atomic_cas.rs");
6+
7+
// The rustc-cfg listed below are considered public API, but it is *unstable*
8+
// and outside of the normal semver guarantees:
9+
//
10+
// - `valuable_no_atomic_cas`
11+
// Assume the target does not have atomic CAS (compare-and-swap).
12+
// This is usually detected automatically by the build script, but you may
13+
// need to enable it manually when building for custom targets or using
14+
// non-cargo build systems that don't run the build script.
15+
//
16+
// With the exceptions mentioned above, the rustc-cfg strings below are
17+
// *not* public API. Please let us know by opening a GitHub issue if your build
18+
// environment requires some way to enable these cfgs other than by executing
19+
// our build script.
20+
fn main() {
21+
let target = match env::var("TARGET") {
22+
Ok(target) => target,
23+
Err(e) => {
24+
println!(
25+
"cargo:warning=valuable: unable to get TARGET environment variable: {}",
26+
e
27+
);
28+
return;
29+
}
30+
};
31+
32+
// Note that this is `no_*`, not `has_*`. This allows treating
33+
// `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
34+
// run. This is needed for compatibility with non-cargo build systems that
35+
// don't run the build script.
36+
if NO_ATOMIC_CAS_TARGETS.contains(&&*target) {
37+
println!("cargo:rustc-cfg=valuable_no_atomic_cas");
38+
}
39+
40+
println!("cargo:rerun-if-changed=no_atomic_cas.rs");
41+
}

valuable/no_atomic_cas.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This file is @generated by no_atomic_cas.sh.
2+
// It is not intended for manual editing.
3+
4+
const NO_ATOMIC_CAS_TARGETS: &[&str] = &[
5+
"avr-unknown-gnu-atmega328",
6+
"msp430-none-elf",
7+
"riscv32i-unknown-none-elf",
8+
"riscv32imc-unknown-none-elf",
9+
"thumbv4t-none-eabi",
10+
"thumbv6m-none-eabi",
11+
];

valuable/src/enumerable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ impl<E: ?Sized + Enumerable> Enumerable for alloc::rc::Rc<E> {
164164
}
165165
}
166166

167+
#[cfg(not(valuable_no_atomic_cas))]
167168
#[cfg(feature = "alloc")]
168169
impl<E: ?Sized + Enumerable> Enumerable for alloc::sync::Arc<E> {
169170
fn definition(&self) -> EnumDef<'_> {

valuable/src/listable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl<L: ?Sized + Listable> Listable for alloc::rc::Rc<L> {
2626
}
2727
}
2828

29+
#[cfg(not(valuable_no_atomic_cas))]
2930
#[cfg(feature = "alloc")]
3031
impl<L: ?Sized + Listable> Listable for alloc::sync::Arc<L> {
3132
fn size_hint(&self) -> (usize, Option<usize>) {

valuable/src/mappable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl<M: ?Sized + Mappable> Mappable for alloc::rc::Rc<M> {
2626
}
2727
}
2828

29+
#[cfg(not(valuable_no_atomic_cas))]
2930
#[cfg(feature = "alloc")]
3031
impl<M: ?Sized + Mappable> Mappable for alloc::sync::Arc<M> {
3132
fn size_hint(&self) -> (usize, Option<usize>) {

valuable/src/structable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ impl<S: ?Sized + Structable> Structable for alloc::rc::Rc<S> {
108108
}
109109
}
110110

111+
#[cfg(not(valuable_no_atomic_cas))]
111112
#[cfg(feature = "alloc")]
112113
impl<S: ?Sized + Structable> Structable for alloc::sync::Arc<S> {
113114
fn definition(&self) -> StructDef<'_> {

valuable/src/valuable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl<V: ?Sized + Valuable> Valuable for alloc::rc::Rc<V> {
6969
}
7070
}
7171

72+
#[cfg(not(valuable_no_atomic_cas))]
7273
#[cfg(feature = "alloc")]
7374
impl<V: ?Sized + Valuable> Valuable for alloc::sync::Arc<V> {
7475
fn as_value(&self) -> Value<'_> {

0 commit comments

Comments
 (0)