Skip to content

Commit 0a76510

Browse files
authored
Merge pull request #33 from roleroz/master
Allow for multiple platformio_project() entries in a single BUILD file
2 parents 2d2808f + ea627e7 commit 0a76510

File tree

8 files changed

+138
-39
lines changed

8 files changed

+138
-39
lines changed

platformio/platformio.bzl

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ _COPY_COMMAND="cp {source} {destination}"
3939

4040

4141
# Command that zips files recursively. It enters the output directory first so
42-
# that the zipped path starts at lib/.
43-
_ZIP_COMMAND="cd {output_dir} && zip -qq -r -u {zip_filename} lib/"
42+
# that the zipped path starts at lib/. It will return to the original directory
43+
# when finishing the command.
44+
_ZIP_COMMAND="cd {output_dir} && zip -qq -r -u {zip_filename} lib/; cd -"
4445

4546

46-
# Command that unzips a zip archive into the specified directory.
47-
_UNZIP_COMMAND="unzip -qq -o -d {project_dir} {zip_filename}"
47+
# Command that unzips a zip archive into the specified directory. It will create
48+
# the destination directory if it doesn't exist.
49+
_UNZIP_COMMAND="mkdir -p {project_dir} && unzip -qq -o -d {project_dir} {zip_filename}"
4850

4951

5052
# Command that executes the PlatformIO build system and builds the project in
@@ -130,11 +132,31 @@ def _platformio_library_impl(ctx):
130132
)
131133

132134

133-
def _emit_ini_file_action(ctx):
135+
def _declare_outputs(ctx):
136+
"""Declares the output files needed by the platformio_project rule.
137+
138+
Args:
139+
ctx: The Starlark context.
140+
141+
Returns:
142+
List of output files declared by ctx.actions.declare_file().
143+
"""
144+
dirname = "%s_workdir" % ctx.attr.name
145+
platformio_ini = ctx.actions.declare_file("%s/platformio.ini" % dirname)
146+
main_cpp = ctx.actions.declare_file("%s/src/main.cpp" % dirname)
147+
firmware_elf = ctx.actions.declare_file("%s/.pio/build/%s/firmware.elf" % (dirname, ctx.attr.board))
148+
return struct(
149+
main_cpp=main_cpp,
150+
platformio_ini=platformio_ini,
151+
firmware_elf=firmware_elf)
152+
153+
154+
def _emit_ini_file_action(ctx, output_files):
134155
"""Emits a Bazel action that generates the PlatformIO configuration file.
135156
136157
Args:
137158
ctx: The Starlark context.
159+
output_files: List of output files declared by ctx.actions.declare_file().
138160
"""
139161
environment_kwargs = []
140162
if ctx.attr.environment_kwargs:
@@ -158,38 +180,40 @@ def _emit_ini_file_action(ctx):
158180
build_flags=build_flags,
159181
).to_json()
160182
ctx.actions.run(
161-
outputs=[ctx.outputs.platformio_ini],
183+
outputs=[output_files.platformio_ini],
162184
inputs=[ctx.file._platformio_ini_tmpl],
163185
executable=ctx.executable._template_renderer,
164186
arguments=[
165187
ctx.file._platformio_ini_tmpl.path,
166-
ctx.outputs.platformio_ini.path,
188+
output_files.platformio_ini.path,
167189
substitutions
168190
],
169191
)
170192

171193

172-
def _emit_main_file_action(ctx):
194+
def _emit_main_file_action(ctx, output_files):
173195
"""Emits a Bazel action that outputs the project main C++ file.
174196
175197
Args:
176198
ctx: The Starlark context.
199+
output_files: List of output files declared by ctx.actions.declare_file().
177200
"""
178201
ctx.actions.run_shell(
179202
inputs=[ctx.file.src],
180-
outputs=[ctx.outputs.main_cpp],
203+
outputs=[output_files.main_cpp],
181204
command=_COPY_COMMAND.format(
182-
source=ctx.file.src.path, destination=ctx.outputs.main_cpp.path),
205+
source=ctx.file.src.path, destination=output_files.main_cpp.path),
183206
)
184207

185208

186-
def _emit_build_action(ctx, project_dir):
209+
def _emit_build_action(ctx, project_dir, output_files):
187210
"""Emits a Bazel action that unzips the libraries and builds the project.
188211
189212
Args:
190213
ctx: The Starlark context.
191214
project_dir: A string, the main directory of the PlatformIO project.
192215
This is where the zip files will be extracted.
216+
output_files: List of output files declared by ctx.actions.declare_file().
193217
"""
194218
transitive_zip_files=depset(
195219
transitive=[
@@ -204,12 +228,12 @@ def _emit_build_action(ctx, project_dir):
204228

205229
# The PlatformIO build system needs the project configuration file, the main
206230
# file and all the transitive dependancies.
207-
inputs=[ctx.outputs.platformio_ini, ctx.outputs.main_cpp]
231+
inputs=[output_files.platformio_ini, output_files.main_cpp]
208232
for zip_file in transitive_zip_files.to_list():
209233
inputs.append(zip_file)
210234
ctx.actions.run_shell(
211235
inputs=inputs,
212-
outputs=[ctx.outputs.firmware_elf],
236+
outputs=[output_files.firmware_elf],
213237
command="\n".join(commands),
214238
env={
215239
# The PlatformIO binary assumes that the build tools are in the path.
@@ -227,22 +251,33 @@ def _emit_build_action(ctx, project_dir):
227251
)
228252

229253

230-
def _emit_executable_action(ctx):
254+
def _emit_executable_action(ctx, project_dir):
231255
"""Emits a Bazel action that produces executable script.
232256
233257
When the script is executed, the compiled firmware gets uploaded to the
234258
Arduino device.
235259
236260
Args:
237261
ctx: The Starlark context.
262+
project_dir: A string, the main directory of the PlatformIO project.
263+
This is where the zip files will be extracted.
238264
"""
239265
# TODO(mum4k): Make this script smarter, when executed via Bazel, the current
240266
# directory is project_name.runfiles/__main__ so we need to go two dirs up.
241267
# This however won't work when executed directly.
242-
content=[_SHELL_HEADER, _UPLOAD_COMMAND.format(project_dir="../..")]
268+
transitive_zip_files=depset(
269+
transitive=[
270+
dep[DefaultInfo].default_runfiles.files for dep in ctx.attr.deps
271+
])
272+
273+
commands = [_SHELL_HEADER]
274+
for zip_file in transitive_zip_files.to_list():
275+
commands.append(_UNZIP_COMMAND.format(
276+
project_dir=project_dir, zip_filename=zip_file.short_path))
277+
commands.append(_UPLOAD_COMMAND.format(project_dir=project_dir))
243278
ctx.actions.write(
244279
output=ctx.outputs.executable,
245-
content="\n".join(content),
280+
content="\n".join(commands),
246281
is_executable=True,
247282
)
248283

@@ -258,14 +293,31 @@ def _platformio_project_impl(ctx):
258293
Args:
259294
ctx: The Starlark context.
260295
"""
261-
_emit_ini_file_action(ctx)
262-
_emit_main_file_action(ctx)
296+
output_files = _declare_outputs(ctx)
297+
_emit_ini_file_action(ctx, output_files)
298+
_emit_main_file_action(ctx, output_files)
263299

264300
# Determine the build directory used by Bazel, that is the directory where
265301
# our output files will be placed.
266-
project_dir = ctx.outputs.platformio_ini.dirname
267-
_emit_build_action(ctx, project_dir)
268-
_emit_executable_action(ctx)
302+
project_build_dir = output_files.platformio_ini.dirname
303+
_emit_build_action(ctx, project_build_dir, output_files)
304+
# Determine the run directory used by Bazel, that is the directory where our
305+
# output files will be placed.
306+
project_run_dir = "./%s" % project_build_dir[len(output_files.platformio_ini.root.path)+1:]
307+
_emit_executable_action(ctx, project_run_dir)
308+
309+
return DefaultInfo(
310+
default_runfiles=ctx.runfiles(files=[
311+
ctx.outputs.executable,
312+
output_files.main_cpp,
313+
output_files.platformio_ini,
314+
output_files.firmware_elf,
315+
] + depset(
316+
transitive=[
317+
dep[DefaultInfo].default_runfiles.files for dep in ctx.attr.deps
318+
]).to_list()
319+
)
320+
)
269321

270322

271323
platformio_library = rule(
@@ -352,11 +404,6 @@ expected by PlatformIO.
352404
platformio_project = rule(
353405
implementation=_platformio_project_impl,
354406
executable=True,
355-
outputs = {
356-
"main_cpp": "src/main.cpp",
357-
"platformio_ini": "platformio.ini",
358-
"firmware_elf": ".pio/build/%{board}/firmware.elf",
359-
},
360407
attrs={
361408
"_platformio_ini_tmpl": attr.label(
362409
default=Label("//platformio:platformio_ini_tmpl"),

tests/binary_counter/BUILD

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,44 @@
1414

1515
load("//platformio:platformio.bzl", "platformio_project")
1616

17-
platformio_project(
18-
name = "binary_counter",
17+
configs = [
18+
{
19+
"name": "mega",
20+
"board": "megaatmega2560",
21+
"build_flags": [
22+
"-DRED_LED_PIN=44",
23+
"-DORANGE_LED_PIN=46",
24+
"-DGREEN_LED_PIN=48",
25+
"-DBLUE_LED_PIN=50",
26+
"-DYELLOW_LED_PIN=52",
27+
"-DBUTTON_PIN=2",
28+
],
29+
},
30+
{
31+
"name": "nano",
32+
"board": "nanoatmega328",
33+
"build_flags": [
34+
"-DRED_LED_PIN=3",
35+
"-DORANGE_LED_PIN=4",
36+
"-DGREEN_LED_PIN=5",
37+
"-DBLUE_LED_PIN=6",
38+
"-DYELLOW_LED_PIN=7",
39+
"-DBUTTON_PIN=2",
40+
],
41+
},
42+
]
43+
44+
[platformio_project(
45+
name = "binary_counter_%s" % config["name"],
1946
src = "binary_counter.cc",
20-
board = "megaatmega2560",
47+
board = config["board"],
2148
framework = "arduino",
2249
platform = "atmelavr",
50+
build_flags = config["build_flags"],
2351
deps = [
2452
"//tests/arduino:Arduino_impl",
2553
"//tests/arduino:Arduino_interface",
2654
"//tests/binary_counter/button_presses:Button_presses",
2755
"//tests/binary_counter/led_display:Led_display",
2856
],
29-
)
57+
) for config in configs]

tests/binary_counter/README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@ count will be displayed in binary form using the Leds.
3131

3232
### The breadboard
3333

34-
![The binary counter breadboard](doc/binary_counter_bb.png)
34+
#### On Arduino Mega
35+
![The binary counter breadboard](doc/binary_counter_mega_bb.png)
3536

36-
### Fritzing circuit
37+
The [Fritzing](http://fritzing.org) circuit is stored in file
38+
[binary_counter.fzz](doc/binary_counter_mega.fzz).
39+
40+
#### On Arduino Nano
41+
![The binary counter breadboard](doc/binary_counter_nano_bb.png)
3742

3843
The [Fritzing](http://fritzing.org) circuit is stored in file
39-
[binary_counter.fzz](doc/binary_counter.fzz).
44+
[binary_counter.fzz](doc/binary_counter_nano.fzz).

tests/binary_counter/binary_counter.cc

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,42 @@ using binary_counter::kDefaultTimeoutMs;
3232
using binary_counter::LedDisplay;
3333
using binary_counter::LedPins;
3434

35+
#ifndef RED_LED_PIN
36+
#error RED_LED_PIN needs to be defined
37+
#endif
38+
#ifndef ORANGE_LED_PIN
39+
#error ORANGE_LED_PIN needs to be defined
40+
#endif
41+
#ifndef GREEN_LED_PIN
42+
#error GREEN_LED_PIN needs to be defined
43+
#endif
44+
#ifndef BLUE_LED_PIN
45+
#error BLUE_LED_PIN needs to be defined
46+
#endif
47+
#ifndef YELLOW_LED_PIN
48+
#error YELLOW_LED_PIN needs to be defined
49+
#endif
50+
#ifndef BUTTON_PIN
51+
#error BUTTON_PIN needs to be defined
52+
#endif
53+
3554
// Arduino hardware layer.
3655
const ArduinoImpl ino = ArduinoImpl();
3756

3857
// Pin numbers where the Leds are wired.
39-
const int kRedLedPin = 44;
40-
const int kOrangeLedPin = 46;
41-
const int kGreenLedPin = 48;
42-
const int kBlueLedPin = 50;
43-
const int kYellowLedPin = 52;
58+
const int kRedLedPin = RED_LED_PIN;
59+
const int kOrangeLedPin = ORANGE_LED_PIN;
60+
const int kGreenLedPin = GREEN_LED_PIN;
61+
const int kBlueLedPin = BLUE_LED_PIN;
62+
const int kYellowLedPin = YELLOW_LED_PIN;
4463
const LedPins led_pins(kYellowLedPin, kBlueLedPin, kGreenLedPin, kOrangeLedPin,
4564
kRedLedPin);
4665

4766
// Class that can display binary numbers using Leds.
4867
const LedDisplay led = LedDisplay(ino, led_pins);
4968

5069
// Pin where the button is wired.
51-
const int kButtonPin = 2;
70+
const int kButtonPin = BUTTON_PIN;
5271

5372
// Remains in the intro mode until this gets set to false.
5473
volatile bool intro = true;
File renamed without changes.
File renamed without changes.
8.01 KB
Binary file not shown.
311 KB
Loading

0 commit comments

Comments
 (0)