Skip to content

Commit 7ee61fe

Browse files
committed
Work around a handful of issues in ctest-test
* Tests for C++ can only be run when g++ or another C++ compiler is available. We don't need to test this on all platforms, so make the tests check whether a compiler is available and only run these tests if so. * Statics seem to produce duplicate symbol errors [1]. Comment out the relevant parts of tests for now. * Tests don't work when cross compiling. Gate the `all.rs` test to only run on x86_64. Most of this needs to be removed, but the workarounds get us able to run something in CI. [1]: rust-lang#4365
1 parent 13631b3 commit 7ee61fe

File tree

9 files changed

+103
-57
lines changed

9 files changed

+103
-57
lines changed

ci/docker/x86_64-unknown-linux-gnu/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM ubuntu:24.10
22

33
RUN apt-get update
44
RUN apt-get install -y --no-install-recommends \
5-
gcc libc6-dev ca-certificates linux-headers-generic
5+
gcc g++ libc6-dev ca-certificates linux-headers-generic
66

77
RUN apt search linux-headers
88
RUN ls /usr/src

ctest-test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ctest = { path = "../ctest" }
1111
cc = "1.0"
1212

1313
[dependencies]
14+
cfg-if = "1.0.0"
1415
libc = "0.2"
1516

1617
[lib]

ctest-test/build.rs

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::process::Command;
2+
13
fn main() {
24
use std::env;
35
let opt_level = env::var("OPT_LEVEL")
@@ -48,34 +50,43 @@ fn main() {
4850
.skip_roundtrip(|_| true)
4951
.generate("src/t2.rs", "t2gen.rs");
5052

51-
ctest::TestGenerator::new()
52-
.header("t1.h")
53-
.language(ctest::Lang::CXX)
54-
.include("src")
55-
.fn_cname(|a, b| b.unwrap_or(a).to_string())
56-
.type_name(move |ty, is_struct, is_union| match ty {
57-
"T1Union" => ty.to_string(),
58-
"Transparent" => ty.to_string(),
59-
t if is_struct => format!("struct {}", t),
60-
t if is_union => format!("union {}", t),
61-
t => t.to_string(),
62-
})
63-
.volatile_item(t1_volatile)
64-
.array_arg(t1_arrays)
65-
.skip_roundtrip(|n| n == "Arr")
66-
.generate("src/t1.rs", "t1gen_cxx.rs");
67-
ctest::TestGenerator::new()
68-
.header("t2.h")
69-
.language(ctest::Lang::CXX)
70-
.include("src")
71-
.type_name(move |ty, is_struct, is_union| match ty {
72-
"T2Union" => ty.to_string(),
73-
t if is_struct => format!("struct {}", t),
74-
t if is_union => format!("union {}", t),
75-
t => t.to_string(),
76-
})
77-
.skip_roundtrip(|_| true)
78-
.generate("src/t2.rs", "t2gen_cxx.rs");
53+
println!("cargo::rustc-check-cfg=cfg(has_cxx)");
54+
if !cfg!(unix) || Command::new("c++").arg("v").output().is_ok() {
55+
// A C compiler is always available, but these are only run if a C++ compiler is
56+
// also available.
57+
println!("cargo::rustc-cfg=has_cxx");
58+
59+
ctest::TestGenerator::new()
60+
.header("t1.h")
61+
.language(ctest::Lang::CXX)
62+
.include("src")
63+
.fn_cname(|a, b| b.unwrap_or(a).to_string())
64+
.type_name(move |ty, is_struct, is_union| match ty {
65+
"T1Union" => ty.to_string(),
66+
"Transparent" => ty.to_string(),
67+
t if is_struct => format!("struct {}", t),
68+
t if is_union => format!("union {}", t),
69+
t => t.to_string(),
70+
})
71+
.volatile_item(t1_volatile)
72+
.array_arg(t1_arrays)
73+
.skip_roundtrip(|n| n == "Arr")
74+
.generate("src/t1.rs", "t1gen_cxx.rs");
75+
ctest::TestGenerator::new()
76+
.header("t2.h")
77+
.language(ctest::Lang::CXX)
78+
.include("src")
79+
.type_name(move |ty, is_struct, is_union| match ty {
80+
"T2Union" => ty.to_string(),
81+
t if is_struct => format!("struct {}", t),
82+
t if is_union => format!("union {}", t),
83+
t => t.to_string(),
84+
})
85+
.skip_roundtrip(|_| true)
86+
.generate("src/t2.rs", "t2gen_cxx.rs");
87+
} else {
88+
println!("cargo::warning=skipping C++ tests");
89+
}
7990
}
8091

8192
fn t1_volatile(i: ctest::VolatileItemKind) -> bool {

ctest-test/src/bin/t1_cxx.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#![cfg(not(test))]
2-
#![deny(warnings)]
32

4-
use ctest_test::t1::*;
5-
use libc::*;
3+
cfg_if::cfg_if! {
4+
if #[cfg(has_cxx)] {
5+
use ctest_test::t1::*;
6+
use libc::*;
67

7-
include!(concat!(env!("OUT_DIR"), "/t1gen_cxx.rs"));
8+
include!(concat!(env!("OUT_DIR"), "/t1gen_cxx.rs"));
9+
} else {
10+
fn main() {}
11+
}
12+
}

ctest-test/src/bin/t2_cxx.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#![cfg(not(test))]
2-
#![deny(warnings)]
32

4-
use ctest_test::t2::*;
3+
cfg_if::cfg_if! {
4+
if #[cfg(has_cxx)] {
5+
use ctest_test::t2::*;
56

6-
include!(concat!(env!("OUT_DIR"), "/t2gen_cxx.rs"));
7+
include!(concat!(env!("OUT_DIR"), "/t2gen_cxx.rs"));
8+
} else {
9+
fn main() {}
10+
}
11+
}

ctest-test/src/t1.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@ void* T1_vol0(volatile void* x, void* a) { return a? a: (void*)x; }
7272
volatile void* T1_vol1(void* x, void* b) { return b? (volatile void*)x : (volatile void*)x; }
7373
volatile void* T1_vol2(void* c, volatile void* x) { return c? x : x; }
7474

75+
/* FIXME(#4365): duplicate symbol errors when enabled
7576
uint8_t (* volatile T1_fn_ptr_vol)(uint8_t, uint8_t) = foo;
77+
*/

ctest-test/src/t1.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,17 @@ void T1v(const Arr* a);
6262

6363
extern uint32_t T1static;
6464
extern const uint8_t T1_static_u8;
65-
uint8_t T1_static_mut_u8;
66-
uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
65+
/* FIXME(#4365): duplicate symbol errors when enabled
66+
// uint8_t T1_static_mut_u8;
67+
// uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
6768
extern uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t);
69+
*/
6870
extern void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t);
6971
extern void (*const T1_static_const_fn_ptr_unsafe3)(void);
7072

7173
extern const uint8_t T1_static_right;
72-
uint8_t (*T1_static_right2)(uint8_t, uint8_t);
74+
/* FIXME(#4365): duplicate symbol errors when enabled
75+
// uint8_t (*T1_static_right2)(uint8_t, uint8_t);
7376
7477
// T1_fn_ptr_nested: function pointer to a function, taking a uint8_t, and
7578
// returning a function pointer to a function taking a uint16_t and returning a
@@ -80,6 +83,7 @@ uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t);
8083
// uint8_t -> uint8_t, and returning a function pointer to a function taking a
8184
// uint16_t and returning a uint32_t
8285
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
86+
*/
8387

8488
extern const int32_t T1_arr0[2];
8589
extern const int32_t T1_arr1[2][3];
@@ -98,8 +102,10 @@ extern int32_t* T1_mut_opt_mut_ref;
98102
extern const int32_t* T1_const_opt_const_ref;
99103

100104
extern void (*const T1_opt_fn1)(void);
101-
uint32_t (*(*T1_opt_fn2)(uint8_t))(uint16_t);
102-
uint32_t (*(*T1_opt_fn3)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
105+
/* FIXME(#4365): duplicate symbol errors when enabled
106+
// uint32_t (*(*T1_opt_fn2)(uint8_t))(uint16_t);
107+
// uint32_t (*(*T1_opt_fn3)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
108+
*/
103109

104110

105111
struct Q {
@@ -153,8 +159,10 @@ void* T1_vol0(volatile void*, void*);
153159
volatile void* T1_vol1(void*, void*);
154160
volatile void* T1_vol2(void*, volatile void*);
155161

162+
/* FIXME(#4365): duplicate symbol errors when enabled
156163
// volatile function pointers:
157164
uint8_t (*volatile T1_fn_ptr_vol)(uint8_t, uint8_t);
165+
*/
158166

159167
#define LOG_MAX_LINE_LENGTH (1400)
160168

ctest-test/src/t1.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,26 @@ pub fn foo() {
9393

9494
extern "C" {
9595
pub static T1_static_u8: u8;
96-
pub static mut T1_static_mut_u8: u8;
97-
pub static mut T1_static_mut_fn_ptr: extern "C" fn(u8, u8) -> u8;
96+
/* FIXME(#4365): duplicate symbol errors when enabled
97+
// pub static mut T1_static_mut_u8: u8;
98+
// pub static mut T1_static_mut_fn_ptr: extern "C" fn(u8, u8) -> u8;
9899
pub static T1_static_const_fn_ptr_unsafe: unsafe extern "C" fn(u8, u8) -> u8;
100+
*/
99101
pub static T1_static_const_fn_ptr_unsafe2: unsafe extern "C" fn(u8) -> ();
100102
pub static T1_static_const_fn_ptr_unsafe3: unsafe extern "C" fn() -> ();
101103

102104
#[link_name = "T1_static_right"]
103105
pub static T1_static_wrong: u8;
104-
#[link_name = "T1_static_right2"]
105-
pub static mut T1_static_wrong2: extern "C" fn(u8, u8) -> u8;
106+
/* FIXME(#4365): duplicate symbol errors when enabled
107+
// #[link_name = "T1_static_right2"]
108+
// pub static mut T1_static_wrong2: extern "C" fn(u8, u8) -> u8;
106109
107110
pub static T1_fn_ptr_s: unsafe extern "C" fn(u8) -> extern "C" fn(u16) -> u32;
108111
pub static T1_fn_ptr_s2: unsafe extern "C" fn(
109112
extern "C" fn(u8) -> u8,
110113
extern "C" fn(u16) -> u16,
111114
) -> extern "C" fn(u16) -> u32;
115+
*/
112116

113117
pub static T1_arr0: [i32; 2];
114118
pub static T1_arr1: [[i32; 3]; 2];
@@ -128,13 +132,15 @@ extern "C" {
128132
pub static T1_const_opt_const_ref: Option<&'static i32>;
129133

130134
pub static T1_opt_fn1: Option<unsafe extern "C" fn() -> ()>;
135+
/* FIXME(#4365): duplicate symbol errors when enabled
131136
pub static T1_opt_fn2: Option<unsafe extern "C" fn(u8) -> extern "C" fn(u16) -> u32>;
132137
pub static T1_opt_fn3: Option<
133138
unsafe extern "C" fn(
134139
extern "C" fn(u8) -> u8,
135140
extern "C" fn(u16) -> u16,
136141
) -> extern "C" fn(u16) -> u32,
137142
>;
143+
*/
138144
}
139145

140146
#[repr(C)]
@@ -176,7 +182,9 @@ extern "C" {
176182
pub fn T1_vol0(arg0: *mut c_void, arg1: *mut c_void) -> *mut c_void;
177183
pub fn T1_vol1(arg0: *mut c_void, arg1: *mut c_void) -> *mut c_void;
178184
pub fn T1_vol2(arg0: *mut c_void, arg1: *mut c_void) -> *mut c_void;
185+
/* FIXME(#4365): duplicate symbol errors when enabled
179186
pub static T1_fn_ptr_vol: Option<unsafe extern "C" fn(u8, u8) -> u8>;
187+
*/
180188
}
181189

182190
pub const LOG_MAX_LINE_LENGTH: usize = 1400;

ctest-test/tests/all.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// FIXME(ctest): this test doesn't work when cross compiling.
2+
#![cfg(target_arch = "x86_64")]
3+
14
use std::collections::HashSet;
25
use std::env;
36
use std::process::{Command, ExitStatus};
@@ -12,25 +15,35 @@ fn cmd(name: &str) -> Command {
1215
Command::new(p)
1316
}
1417

18+
fn output(cmd: &mut Command) -> (String, ExitStatus) {
19+
eprintln!("command: {cmd:?}");
20+
let output = cmd.output().unwrap();
21+
let stdout = String::from_utf8(output.stdout).unwrap();
22+
let stderr = String::from_utf8(output.stderr).unwrap();
23+
24+
(stdout + &stderr, output.status)
25+
}
26+
1527
#[test]
1628
fn t1() {
1729
let (o, status) = output(&mut cmd("t1"));
18-
assert!(status.success(), "{}", o);
30+
assert!(status.success(), "output: {o}");
1931
assert!(!o.contains("bad "), "{}", o);
2032
eprintln!("o: {}", o);
2133
}
2234

2335
#[test]
36+
#[cfg(has_cxx)]
2437
fn t1_cxx() {
2538
let (o, status) = output(&mut cmd("t1_cxx"));
26-
assert!(status.success(), "{}", o);
39+
assert!(status.success(), "output: {o}");
2740
assert!(!o.contains("bad "), "{}", o);
2841
}
2942

3043
#[test]
3144
fn t2() {
3245
let (o, status) = output(&mut cmd("t2"));
33-
assert!(!status.success(), "{}", o);
46+
assert!(!status.success(), "output: {o}");
3447
let errors = [
3548
"bad T2Foo signed",
3649
"bad T2TypedefFoo signed",
@@ -72,9 +85,10 @@ fn t2() {
7285
}
7386

7487
#[test]
88+
#[cfg(has_cxx)]
7589
fn t2_cxx() {
7690
let (o, status) = output(&mut cmd("t2_cxx"));
77-
assert!(!status.success(), "{}", o);
91+
assert!(!status.success(), "output: {o}");
7892
let errors = [
7993
"bad T2Foo signed",
8094
"bad T2TypedefFoo signed",
@@ -114,11 +128,3 @@ fn t2_cxx() {
114128
panic!();
115129
}
116130
}
117-
118-
fn output(cmd: &mut Command) -> (String, ExitStatus) {
119-
let output = cmd.output().unwrap();
120-
let stdout = String::from_utf8(output.stdout).unwrap();
121-
let stderr = String::from_utf8(output.stderr).unwrap();
122-
123-
(stdout + &stderr, output.status)
124-
}

0 commit comments

Comments
 (0)