@@ -39,12 +39,14 @@ _COPY_COMMAND="cp {source} {destination}"
39
39
40
40
41
41
# 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 -"
44
45
45
46
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}"
48
50
49
51
50
52
# Command that executes the PlatformIO build system and builds the project in
@@ -130,11 +132,31 @@ def _platformio_library_impl(ctx):
130
132
)
131
133
132
134
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 ):
134
155
"""Emits a Bazel action that generates the PlatformIO configuration file.
135
156
136
157
Args:
137
158
ctx: The Starlark context.
159
+ output_files: List of output files declared by ctx.actions.declare_file().
138
160
"""
139
161
environment_kwargs = []
140
162
if ctx .attr .environment_kwargs :
@@ -158,38 +180,40 @@ def _emit_ini_file_action(ctx):
158
180
build_flags = build_flags ,
159
181
).to_json ()
160
182
ctx .actions .run (
161
- outputs = [ctx . outputs .platformio_ini ],
183
+ outputs = [output_files .platformio_ini ],
162
184
inputs = [ctx .file ._platformio_ini_tmpl ],
163
185
executable = ctx .executable ._template_renderer ,
164
186
arguments = [
165
187
ctx .file ._platformio_ini_tmpl .path ,
166
- ctx . outputs .platformio_ini .path ,
188
+ output_files .platformio_ini .path ,
167
189
substitutions
168
190
],
169
191
)
170
192
171
193
172
- def _emit_main_file_action (ctx ):
194
+ def _emit_main_file_action (ctx , output_files ):
173
195
"""Emits a Bazel action that outputs the project main C++ file.
174
196
175
197
Args:
176
198
ctx: The Starlark context.
199
+ output_files: List of output files declared by ctx.actions.declare_file().
177
200
"""
178
201
ctx .actions .run_shell (
179
202
inputs = [ctx .file .src ],
180
- outputs = [ctx . outputs .main_cpp ],
203
+ outputs = [output_files .main_cpp ],
181
204
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 ),
183
206
)
184
207
185
208
186
- def _emit_build_action (ctx , project_dir ):
209
+ def _emit_build_action (ctx , project_dir , output_files ):
187
210
"""Emits a Bazel action that unzips the libraries and builds the project.
188
211
189
212
Args:
190
213
ctx: The Starlark context.
191
214
project_dir: A string, the main directory of the PlatformIO project.
192
215
This is where the zip files will be extracted.
216
+ output_files: List of output files declared by ctx.actions.declare_file().
193
217
"""
194
218
transitive_zip_files = depset (
195
219
transitive = [
@@ -204,12 +228,12 @@ def _emit_build_action(ctx, project_dir):
204
228
205
229
# The PlatformIO build system needs the project configuration file, the main
206
230
# 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 ]
208
232
for zip_file in transitive_zip_files .to_list ():
209
233
inputs .append (zip_file )
210
234
ctx .actions .run_shell (
211
235
inputs = inputs ,
212
- outputs = [ctx . outputs .firmware_elf ],
236
+ outputs = [output_files .firmware_elf ],
213
237
command = "\n " .join (commands ),
214
238
env = {
215
239
# The PlatformIO binary assumes that the build tools are in the path.
@@ -227,22 +251,33 @@ def _emit_build_action(ctx, project_dir):
227
251
)
228
252
229
253
230
- def _emit_executable_action (ctx ):
254
+ def _emit_executable_action (ctx , project_dir ):
231
255
"""Emits a Bazel action that produces executable script.
232
256
233
257
When the script is executed, the compiled firmware gets uploaded to the
234
258
Arduino device.
235
259
236
260
Args:
237
261
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.
238
264
"""
239
265
# TODO(mum4k): Make this script smarter, when executed via Bazel, the current
240
266
# directory is project_name.runfiles/__main__ so we need to go two dirs up.
241
267
# 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 ))
243
278
ctx .actions .write (
244
279
output = ctx .outputs .executable ,
245
- content = "\n " .join (content ),
280
+ content = "\n " .join (commands ),
246
281
is_executable = True ,
247
282
)
248
283
@@ -258,14 +293,31 @@ def _platformio_project_impl(ctx):
258
293
Args:
259
294
ctx: The Starlark context.
260
295
"""
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 )
263
299
264
300
# Determine the build directory used by Bazel, that is the directory where
265
301
# 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
+ )
269
321
270
322
271
323
platformio_library = rule (
@@ -352,11 +404,6 @@ expected by PlatformIO.
352
404
platformio_project = rule (
353
405
implementation = _platformio_project_impl ,
354
406
executable = True ,
355
- outputs = {
356
- "main_cpp" : "src/main.cpp" ,
357
- "platformio_ini" : "platformio.ini" ,
358
- "firmware_elf" : ".pio/build/%{board}/firmware.elf" ,
359
- },
360
407
attrs = {
361
408
"_platformio_ini_tmpl" : attr .label (
362
409
default = Label ("//platformio:platformio_ini_tmpl" ),
0 commit comments