Skip to content

Commit 0c2e25f

Browse files
committed
chore: use nushell as task runner (#256)
ref nRF24/RF24#1038
1 parent bfe795a commit 0c2e25f

1 file changed

Lines changed: 284 additions & 0 deletions

File tree

nurfile

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
2+
3+
def is-windows [] {
4+
$nu.os-info | get "family" | str starts-with "windows"
5+
}
6+
7+
8+
def --wrapped run-cmd [...cmd: string] {
9+
print $"\n(ansi blue)Running(ansi reset) ($cmd | str join ' ')"
10+
let elapsed = timeit {|| ^($cmd | first) ...($cmd | skip 1)}
11+
print $"(ansi magenta)($cmd | first) took ($elapsed)(ansi reset)"
12+
}
13+
14+
15+
def flush-artifacts [
16+
build_dir: string, dirty: bool
17+
] {
18+
if ($build_dir | path exists) {
19+
if $dirty == false {
20+
print $"(ansi yellow)Removing artifacts(ansi reset) ($build_dir)"
21+
rm -r $build_dir
22+
}
23+
}
24+
}
25+
26+
27+
# Build the docs.
28+
#
29+
# Note, there is no check against what
30+
# version of doxygen is used.
31+
def "nur docs" [
32+
--dirty (-d) # Do not flush previous build artifacts
33+
--open (-o) # Open the built docs in your default browser
34+
] {
35+
let build_dir = "docs/html"
36+
flush-artifacts $build_dir $dirty
37+
cd docs
38+
run-cmd doxygen
39+
if $open {
40+
let root_pg = $nur.project-path | path join $"($build_dir)/index.html"
41+
start $root_pg
42+
}
43+
}
44+
45+
46+
def find-built-examples [path: string] {
47+
let len = $nur.project-path | str length
48+
let example_path_len = ($path | str length) + 2
49+
let sources = (
50+
glob $"($path)/**/*.cpp" --exclude [
51+
"**/build/**"
52+
]
53+
| each {$in | str substring ($len + $example_path_len)..-5}
54+
)
55+
let binaries = (
56+
glob $"($path)/build/**/*" --exclude [
57+
"**/CMakeFiles/**"
58+
]
59+
| each {$in | str substring ($len + $example_path_len + 6)..}
60+
| filter {$in in $sources}
61+
)
62+
$binaries
63+
}
64+
65+
66+
# Build the Linux examples.
67+
#
68+
# This task expects the library to be installed.
69+
# CMake will build any ncurses examples if
70+
# the libncurses5-dev package is installed
71+
def "nur examples" [
72+
--dirty (-d) # Reuse previous build env
73+
...cmake_opts: string # additional args passed to cmake when configuring the build env
74+
] {
75+
let src_dir = "examples_RPi"
76+
let build_dir = $"($src_dir)/build"
77+
78+
flush-artifacts $build_dir $dirty
79+
80+
if $dirty == false {
81+
run-cmd cmake -B $build_dir $src_dir ...$cmake_opts
82+
} else if ($build_dir | path exists) == false {
83+
run-cmd cmake -B $build_dir $src_dir ...$cmake_opts
84+
}
85+
run-cmd cmake --build $build_dir
86+
87+
print $"(ansi green)Built the following examples:(ansi reset)"
88+
let binaries = (
89+
find-built-examples $src_dir
90+
| each {$"($build_dir)/($in)"}
91+
)
92+
print $binaries
93+
}
94+
95+
96+
# Build/install the library.
97+
#
98+
# Note, this may ask for the password to
99+
# install the library with super-user privileges.
100+
def --wrapped "nur lib" [
101+
--dirty (-d) # Reuse previous build env
102+
--no-install # Do not install the library (useful for testing compilation)
103+
...cmake_opts: string # additional args passed to cmake when configuring the build env
104+
] {
105+
let build_dir = "build"
106+
flush-artifacts $build_dir $dirty
107+
108+
if $dirty == false {
109+
run-cmd cmake -B build -S . ...$cmake_opts
110+
}
111+
run-cmd cmake --build $build_dir
112+
if $no_install == false {
113+
run-cmd sudo cmake --install $build_dir
114+
}
115+
}
116+
117+
118+
# Build the Pico SDK examples.
119+
#
120+
# If building on Windows, then `-G Ninja` is
121+
# automatically passed to CMake when configuring the
122+
# build environment.
123+
def --wrapped "nur pico" [
124+
--dirty (-d) # Reuse previous build env
125+
...cmake_opts: string # additional args passed to cmake when configuring the build env
126+
] {
127+
let src_dir = "examples_pico"
128+
let build_dir = $"($src_dir)/build"
129+
flush-artifacts $build_dir $dirty
130+
131+
let use_ninja = '-G Ninja'
132+
let opts = if (is-windows) {
133+
$cmake_opts | append $use_ninja
134+
} else { $cmake_opts }
135+
136+
if $dirty == false {
137+
run-cmd cmake -B $build_dir $src_dir ...$opts
138+
} else if ($build_dir | path exists) == false {
139+
run-cmd cmake -B $build_dir $src_dir ...$opts
140+
}
141+
run-cmd cmake --build $build_dir
142+
}
143+
144+
145+
# Install the python wrapper.
146+
#
147+
# Note, this task requires the library
148+
# (& boost.python) to be installed.
149+
def "nur py" [
150+
--dirty (-d) # Reuse previous build env
151+
] {
152+
let src_dir = "RPi/pyRF24Network"
153+
let artifacts = glob $"($src_dir)/{build,*.egg-info}"
154+
if ($artifacts | length) > 0 {
155+
if $dirty == false {
156+
print $"(ansi yellow)Removing artifacts(ansi reset) ($artifacts | str join ' ')"
157+
rm -r ...$artifacts
158+
}
159+
}
160+
run-cmd pip install -v $"./($src_dir)"
161+
}
162+
163+
164+
def changed-files [] {
165+
let status = git status --short | lines
166+
if ($status | length) == 0 {
167+
print $"(ansi red)No file changes detected via (ansi cyan)`git status`(ansi reset)"
168+
print $"Perhaps you want to format all files? (ansi cyan)`nur fmt -a`"
169+
return []
170+
}
171+
let changed = (
172+
$status
173+
| each {$in | str trim | split column --regex '\s+' -n 2}
174+
| flatten
175+
| rename "state" "name"
176+
)
177+
# print $changed
178+
let result = (
179+
$changed
180+
| where {$in.state | split chars | each {$in in ['A' 'M' 'R']} | any {$in}}
181+
| get "name"
182+
| each {
183+
if ($in | str contains " -> ") {
184+
$in | parse "{a} -> {b}" | get "b" | $in.0
185+
} else { $in }
186+
}
187+
)
188+
# print $result
189+
$result
190+
}
191+
192+
193+
def get-clang-format-version [bin_name: string] {
194+
if (which $bin_name | is-empty) {
195+
null
196+
} else {
197+
let version = (
198+
^$bin_name --version
199+
| split column ' '
200+
| values
201+
| flatten
202+
| last
203+
)
204+
print $"($bin_name) --version: ($version)"
205+
$version | parse "{major}.{minor}.{patch}"
206+
}
207+
}
208+
209+
210+
def match-version [
211+
bin_name: string,
212+
expected: string = "14",
213+
--throw
214+
] {
215+
let version = get-clang-format-version $bin_name
216+
if ($version | is-empty) {
217+
if $throw {
218+
error make {
219+
msg: $"($bin_name) not found. Ensure it is installed and added to your PATH."
220+
}
221+
}
222+
false
223+
} else {
224+
if ($version.major.0 == $expected) {
225+
true
226+
} else if $throw {
227+
error make {
228+
msg: $"Failed to find clang-format v($expected).x"
229+
}
230+
} else {
231+
false
232+
}
233+
}
234+
}
235+
236+
237+
# Run clang-format on C++ files.
238+
#
239+
# By default, only changed C++ sources are formatted (uses `git status`).
240+
# The clang-format version is expected to be v14.
241+
# If v14 is not found, then an error is thrown.
242+
def "nur fmt" [
243+
--all (-a) # Format all C++ sources
244+
] {
245+
let all_files = glob "**/*.{h,cpp,c,ino}" --exclude [
246+
"**/build/**"
247+
] | path relative-to $nur.project-path
248+
let files = if $all {
249+
$all_files
250+
} else {
251+
let changes = changed-files
252+
(
253+
$all_files
254+
| where {
255+
($in | path split) in (
256+
$changes | each {$in | path split}
257+
)
258+
}
259+
)
260+
}
261+
262+
let bin_name = if (is-windows) {
263+
let bin_name = "clang-format"
264+
let is_expected = match-version $bin_name --throw
265+
"clang-format"
266+
} else {
267+
let bin_name = "clang-format-14"
268+
let is_expected = match-version $bin_name
269+
if ($is_expected == false) {
270+
let bin_name = "clang-format"
271+
let is_expected = match-version $bin_name --throw
272+
$bin_name
273+
} else {
274+
$bin_name
275+
}
276+
}
277+
278+
if ($files | length) > 0 {
279+
print $files
280+
let elapsed = timeit {|| $files | par-each {|f| ^$bin_name "-i" "--style" "file" $f}}
281+
print $"clang-format took ($elapsed) using parallelism!"
282+
}
283+
print $"(ansi blue)Applied clang-format to ($files | length) files(ansi reset)"
284+
}

0 commit comments

Comments
 (0)