Skip to content

Commit 8b78d49

Browse files
Improve Python helper script (#34)
Fixed a lot of issues with argparse, added option for building in release mode, and documented the new command line arguments. Clippy support has been added back, and we can now run it in CI.
1 parent 2576556 commit 8b78d49

File tree

16 files changed

+124
-59
lines changed

16 files changed

+124
-59
lines changed

.travis.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ install:
1414
- cargo -V
1515
# Required by cargo-xbuild
1616
- rustup component add rust-src
17+
# Required by cargo-xclippy
18+
- rustup component add clippy-preview
1719
# Try installing cargo-xbuild if it's not already installed
1820
- hash cargo-xbuild || cargo install cargo-xbuild
1921
# Download OVMF
@@ -25,7 +27,9 @@ before_script:
2527
- qemu-system-x86_64 --version
2628

2729
script:
28-
- cd uefi-test-runner && ./build.py run --headless
30+
- cd uefi-test-runner
31+
- ./build.py run --headless
32+
- ./build.py clippy
2933

3034
cache:
3135
directories:

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#![no_std]
3131
// Enable some additional warnings and lints.
3232
#![warn(missing_docs, unused)]
33-
#![warn(clippy::all)]
33+
#![deny(clippy::all)]
3434

3535
mod error;
3636
pub use self::error::{Result, Status};

uefi-alloc/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
1111
// Enable additional lints.
1212
#![warn(missing_docs)]
13-
#![cfg_attr(feature = "cargo-clippy", warn(clippy))]
13+
#![deny(clippy::all)]
1414
#![no_std]
1515
// Custom allocators are currently unstable.
1616
#![feature(allocator_api)]
17+
#![feature(tool_lints)]
1718

1819
use core::alloc::{GlobalAlloc, Layout};
1920
use core::ptr;

uefi-logger/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
//! supported by the UEFI console. Don't expect emoji output support.
1414
1515
#![warn(missing_docs)]
16-
#![cfg_attr(feature = "cargo-clippy", warn(clippy))]
16+
#![deny(clippy::all)]
1717
#![no_std]
18+
#![feature(tool_lints)]
1819

1920
extern crate uefi;
2021
use uefi::proto::console::text::Output;

uefi-test-runner/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ Available commands:
2828
- `run`: (re)build and run
2929
- `doc`: generate documentation
3030
- `clippy`: run Clippy
31+
32+
Available options:
33+
34+
- `--verbose`: enables verbose mode, prints commands before running them
35+
- `--headless`: enables headless mode, which runs QEMU without a GUI
36+
- `--release`: builds the code with optimizations enabled

uefi-test-runner/build.py

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,53 +11,80 @@
1111
import sys
1212

1313
## Configurable settings
14-
# Target to build for.
15-
TARGET = 'x86_64-uefi'
16-
# Configuration to build.
17-
CONFIG = 'debug'
18-
19-
# QEMU executable to use
20-
QEMU = 'qemu-system-x86_64'
21-
2214
# Path to workspace directory (which contains the top-level `Cargo.toml`)
2315
WORKSPACE_DIR = Path(__file__).resolve().parents[1]
2416

25-
# Path to directory containing `OVMF_{CODE/VARS}.fd`.
26-
# TODO: use installed OVMF, if available.
27-
OVMF_DIR = WORKSPACE_DIR / 'uefi-test-runner'
28-
29-
# Set to `True` or use the `--verbose` argument to print commands.
30-
VERBOSE = False
17+
# Try changing these with command line flags, where possible
18+
SETTINGS = {
19+
# Print commands before running them.
20+
'verbose': False,
21+
# Run QEMU without showing GUI
22+
'headless': False,
23+
# Target to build for.
24+
'target': 'x86_64-uefi',
25+
# Configuration to build.
26+
'config': 'debug',
27+
# QEMU executable to use
28+
'qemu_binary': 'qemu-system-x86_64',
29+
# Path to directory containing `OVMF_{CODE/VARS}.fd`.
30+
# TODO: use installed OVMF, if available.
31+
'ovmf_dir': WORKSPACE_DIR / 'uefi-test-runner',
32+
}
33+
34+
def build_dir():
35+
'Returns the directory where Cargo places the build artifacts'
36+
return WORKSPACE_DIR / 'target' / SETTINGS['target'] / SETTINGS['config']
37+
38+
def esp_dir():
39+
'Returns the directory where we will build the emulated UEFI system partition'
40+
return build_dir() / 'esp'
41+
42+
def run_xtool(tool, *flags):
43+
'Runs cargo-x<tool> with certain arguments.'
44+
45+
cmd = ['cargo', tool, '--target', SETTINGS['target'], *flags]
46+
47+
if SETTINGS['verbose']:
48+
print(' '.join(cmd))
3149

32-
BUILD_DIR = WORKSPACE_DIR / 'target' / TARGET / CONFIG
33-
ESP_DIR = BUILD_DIR / 'esp'
50+
sp.run(cmd).check_returncode()
3451

3552
def run_xbuild(*flags):
36-
'Runs Cargo XBuild with certain arguments.'
37-
38-
cmd = ['cargo', 'xbuild', '--target', TARGET, *flags]
39-
40-
if VERBOSE:
41-
print(' '.join(cmd))
53+
'Runs cargo-xbuild with certain arguments.'
54+
run_xtool('xbuild', *flags)
4255

43-
sp.run(cmd).check_returncode()
56+
def run_xclippy(*flags):
57+
'Runs cargo-xclippy with certain arguments.'
58+
run_xtool('xclippy', *flags)
4459

4560
def build(*test_flags):
4661
'Builds the tests and examples.'
4762

48-
run_xbuild('--package', 'uefi-test-runner', *test_flags)
49-
run_xbuild('--package', 'uefi', '--examples')
63+
xbuild_args = [
64+
'--package', 'uefi-test-runner',
65+
*test_flags,
66+
]
67+
68+
if SETTINGS['config'] == 'release':
69+
xbuild_args.append('--release')
70+
71+
run_xbuild(*xbuild_args)
5072

5173
# Copy the built test runner file to the right directory for running tests.
52-
built_file = BUILD_DIR / 'uefi-test-runner.efi'
74+
built_file = build_dir() / 'uefi-test-runner.efi'
5375

54-
boot_dir = ESP_DIR / 'EFI' / 'Boot'
76+
boot_dir = esp_dir() / 'EFI' / 'Boot'
5577
boot_dir.mkdir(parents=True, exist_ok=True)
5678

5779
output_file = boot_dir / 'BootX64.efi'
5880

5981
shutil.copy2(built_file, output_file)
6082

83+
def clippy():
84+
'Runs Clippy on all projects'
85+
86+
run_xclippy('--all')
87+
6188
def doc():
6289
'Generates documentation for the library crates.'
6390
sp.run([
@@ -69,18 +96,19 @@ def doc():
6996
'--package', 'uefi-services',
7097
])
7198

72-
def run_qemu(headless):
99+
def run_qemu():
73100
'Runs the code in QEMU.'
74101

75102
# Rebuild all the changes.
76103
build('--features', 'qemu-f4-exit')
77104

78-
ovmf_code, ovmf_vars = OVMF_DIR / 'OVMF_CODE.fd', OVMF_DIR / 'OVMF_VARS.fd'
105+
ovmf_dir = SETTINGS['ovmf_dir']
106+
ovmf_code, ovmf_vars = ovmf_dir / 'OVMF_CODE.fd', ovmf_dir / 'OVMF_VARS.fd'
79107

80108
if not ovmf_code.is_file():
81-
raise FileNotFoundError(f'OVMF_CODE.fd not found in the `{OVMF_DIR}` directory')
109+
raise FileNotFoundError(f'OVMF_CODE.fd not found in the `{ovmf_dir}` directory')
82110

83-
examples_dir = BUILD_DIR / 'examples'
111+
examples_dir = build_dir() / 'examples'
84112

85113
qemu_flags = [
86114
# Disable default devices.
@@ -98,7 +126,7 @@ def run_qemu(headless):
98126
'-drive', f'if=pflash,format=raw,file={ovmf_vars},readonly=on',
99127

100128
# Mount a local directory as a FAT partition.
101-
'-drive', f'format=raw,file=fat:rw:{ESP_DIR}',
129+
'-drive', f'format=raw,file=fat:rw:{esp_dir()}',
102130

103131
# Mount the built examples directory.
104132
'-drive', f'format=raw,file=fat:rw:{examples_dir}',
@@ -111,7 +139,7 @@ def run_qemu(headless):
111139
# When running in headless mode we don't have video, but we can still have
112140
# QEMU emulate a display and take screenshots from it.
113141
qemu_flags.extend(['-vga', 'std'])
114-
if headless:
142+
if SETTINGS['headless']:
115143
# Do not attach a window to QEMU's display
116144
qemu_flags.extend(['-display', 'none'])
117145

@@ -125,9 +153,9 @@ def run_qemu(headless):
125153
#'-debugcon', 'file:debug.log', '-global', 'isa-debugcon.iobase=0x402',
126154
])
127155

128-
cmd = [QEMU] + qemu_flags
156+
cmd = [SETTINGS['qemu_binary']] + qemu_flags
129157

130-
if VERBOSE:
158+
if SETTINGS['verbose']:
131159
print(' '.join(cmd))
132160

133161
# This regex can be used to detect and strip ANSI escape codes when
@@ -167,32 +195,36 @@ def main():
167195

168196
parser = argparse.ArgumentParser(usage=usage, description=desc)
169197

170-
common = argparse.ArgumentParser(add_help=False)
171-
common.add_argument('--verbose', '-v', help='print commands before executing them', action='store_true')
172-
common.add_argument('--headless', help='run QEMU without a GUI', action='store_true')
198+
parser.add_argument('verb', help='command to run', type=str,
199+
choices=['build', 'run', 'doc', 'clippy'])
173200

174-
subparsers = parser.add_subparsers(dest='verb')
201+
parser.add_argument('--verbose', '-v', help='print commands before executing them',
202+
action='store_true')
175203

176-
build_parser = subparsers.add_parser('build', parents=[common])
177-
run_parser = subparsers.add_parser('run', parents=[common])
178-
doc_parser = subparsers.add_parser('doc', parents=[common])
204+
parser.add_argument('--headless', help='run QEMU without a GUI',
205+
action='store_true')
206+
207+
parser.add_argument('--release', help='build in release mode',
208+
action='store_true')
179209

180210
opts = parser.parse_args()
181211

182212
# Check if we need to enable verbose mode
183-
global VERBOSE
184-
VERBOSE = VERBOSE or opts.verbose
185-
headless = opts.headless
213+
SETTINGS['verbose'] = opts.verbose
214+
SETTINGS['headless'] = opts.headless
215+
SETTINGS['config'] = 'release' if opts.release else 'debug'
216+
217+
verb = opts.verb
186218

187-
if opts.verb == 'build':
219+
if verb == 'build':
188220
build()
189-
elif opts.verb == 'run':
190-
run_qemu(headless)
191-
elif opts.verb == 'doc':
221+
elif verb == 'clippy':
222+
clippy()
223+
elif verb == 'doc':
192224
doc()
193-
elif opts.verb is None or opts.verb == '':
225+
elif verb == 'run' or verb is None or opts.verb == '':
194226
# Run the program, by default.
195-
run_qemu(headless)
227+
run_qemu()
196228
else:
197229
raise ValueError(f'Unknown verb {opts.verb}')
198230

uefi-test-runner/src/boot/memory.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use core::mem;
44
use crate::alloc::vec::Vec;
55

66
pub fn test(bt: &BootServices) {
7+
info!("Testing memory functions");
8+
79
allocate_pages(bt);
810
vec_alloc();
911
memmove(bt);
@@ -12,6 +14,8 @@ pub fn test(bt: &BootServices) {
1214
}
1315

1416
fn allocate_pages(bt: &BootServices) {
17+
info!("Allocating some pages of memory");
18+
1519
let ty = AllocateType::AnyPages;
1620
let mem_ty = MemoryType::LoaderData;
1721
let pgs = bt
@@ -38,6 +42,8 @@ fn allocate_pages(bt: &BootServices) {
3842

3943
// Simple test to ensure our custom allocator works with the `alloc` crate.
4044
fn vec_alloc() {
45+
info!("Allocating a vector through the `alloc` crate");
46+
4147
let mut values = vec![-5, 16, 23, 4, 0];
4248

4349
values.sort();
@@ -47,6 +53,8 @@ fn vec_alloc() {
4753

4854
// Test that the `memmove` / `memset` functions work.
4955
fn memmove(bt: &BootServices) {
56+
info!("Testing the `memmove` / `memset` functions");
57+
5058
let src = [1, 2, 3, 4];
5159
let mut dest = [0u8; 4];
5260

@@ -66,6 +74,8 @@ fn memmove(bt: &BootServices) {
6674
}
6775

6876
fn memory_map(bt: &BootServices) {
77+
info!("Testing memory map functions");
78+
6979
// Get an estimate of the memory map size.
7080
let map_sz = bt.memory_map_size();
7181

uefi-test-runner/src/boot/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use uefi::table::boot::BootServices;
22

33
pub fn test(bt: &BootServices) {
4+
info!("Testing boot services");
45
memory::test(bt);
56
misc::test(bt);
67
}

uefi-test-runner/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub extern "C" fn uefi_start(_handle: uefi::Handle, st: &'static SystemTable) ->
1919
// Initialize logging.
2020
uefi_services::init(st);
2121

22+
// Reset the console before running all the other tests.
23+
st.stdout().reset(false).expect("Failed to reset stdout");
24+
2225
// Ensure the tests are run on a version of UEFI we support.
2326
check_revision(st.uefi_revision());
2427

@@ -38,7 +41,7 @@ pub extern "C" fn uefi_start(_handle: uefi::Handle, st: &'static SystemTable) ->
3841
fn check_revision(rev: uefi::table::Revision) {
3942
let (major, minor) = (rev.major(), rev.minor());
4043

41-
info!("UEFI {}.{}", major, minor);
44+
info!("UEFI {}.{}", major, minor / 10);
4245

4346
assert!(major >= 2, "Running on an old, unsupported version of UEFI");
4447
assert!(

uefi-test-runner/src/proto/console/gop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use uefi::table::boot::BootServices;
33
use uefi_exts::BootServicesExt;
44

55
pub fn test(bt: &BootServices) {
6+
info!("Running graphics output protocol test");
67
if let Some(mut gop_proto) = bt.find_protocol::<GraphicsOutput>() {
78
let gop = unsafe { gop_proto.as_mut() };
89

0 commit comments

Comments
 (0)