arduino_ci 0.2.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +49 -20
  3. data/REFERENCE.md +636 -0
  4. data/cpp/arduino/Arduino.h +1 -1
  5. data/cpp/arduino/AvrMath.h +117 -17
  6. data/cpp/arduino/Client.h +27 -0
  7. data/cpp/arduino/EEPROM.h +64 -0
  8. data/cpp/arduino/Godmode.cpp +11 -0
  9. data/cpp/arduino/Godmode.h +58 -9
  10. data/cpp/arduino/HardwareSerial.h +9 -28
  11. data/cpp/arduino/IPAddress.h +59 -0
  12. data/cpp/arduino/Print.h +9 -12
  13. data/cpp/arduino/Printable.h +8 -0
  14. data/cpp/arduino/SPI.h +11 -3
  15. data/cpp/arduino/Server.h +5 -0
  16. data/cpp/arduino/Udp.h +27 -0
  17. data/cpp/arduino/Wire.h +234 -0
  18. data/cpp/arduino/avr/io.h +10 -1
  19. data/cpp/arduino/avr/pgmspace.h +76 -46
  20. data/cpp/arduino/ci/StreamTape.h +36 -0
  21. data/cpp/unittest/OstreamHelpers.h +4 -0
  22. data/exe/arduino_ci.rb +427 -0
  23. data/exe/arduino_ci_remote.rb +2 -385
  24. data/exe/arduino_library_location.rb +2 -2
  25. data/exe/ensure_arduino_installation.rb +7 -1
  26. data/lib/arduino_ci.rb +1 -0
  27. data/lib/arduino_ci/arduino_backend.rb +222 -0
  28. data/lib/arduino_ci/arduino_downloader.rb +43 -73
  29. data/lib/arduino_ci/arduino_downloader_linux.rb +17 -55
  30. data/lib/arduino_ci/arduino_downloader_osx.rb +21 -33
  31. data/lib/arduino_ci/arduino_downloader_windows.rb +11 -53
  32. data/lib/arduino_ci/arduino_installation.rb +18 -80
  33. data/lib/arduino_ci/ci_config.rb +15 -9
  34. data/lib/arduino_ci/cpp_library.rb +266 -48
  35. data/lib/arduino_ci/host.rb +59 -4
  36. data/lib/arduino_ci/library_properties.rb +96 -0
  37. data/lib/arduino_ci/version.rb +1 -1
  38. data/misc/default.yml +55 -4
  39. metadata +21 -87
  40. data/cpp/arduino/Arduino.h.orig +0 -143
  41. data/exe/libasan.rb +0 -29
  42. data/lib/arduino_ci/arduino_cmd.rb +0 -328
  43. data/lib/arduino_ci/arduino_cmd_linux.rb +0 -17
  44. data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -19
  45. data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
  46. data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
@@ -1,143 +0,0 @@
1
- #pragma once
2
- /*
3
- Mock Arduino.h library.
4
-
5
- Where possible, variable names from the Arduino library are used to avoid conflicts
6
-
7
- */
8
- // Chars and strings
9
-
10
- #include "ArduinoDefines.h"
11
-
12
- #include "WCharacter.h"
13
- #include "WString.h"
14
- #include "Print.h"
15
- #include "Stream.h"
16
- #include "HardwareSerial.h"
17
- #include "SPI.h"
18
- #include "Nullptr.h"
19
-
20
- typedef bool boolean;
21
- typedef uint8_t byte;
22
-
23
- #include "binary.h"
24
-
25
- // Math and Trig
26
- #include "AvrMath.h"
27
-
28
- #include "Godmode.h"
29
-
30
-
31
- // Bits and Bytes
32
- #define bit(b) (1UL << (b))
33
- #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
34
- #define bitRead(value, bit) (((value) >> (bit)) & 0x01)
35
- #define bitSet(value, bit) ((value) |= (1UL << (bit)))
36
- #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
37
- #define highByte(w) ((uint8_t) ((w) >> 8))
38
- #define lowByte(w) ((uint8_t) ((w) & 0xff))
39
-
40
- // Arduino defines this
41
- #define _NOP() do { 0; } while (0)
42
-
43
- // might as well use that NO-op macro for these, while unit testing
44
- // you need interrupts? interrupt yourself
45
- #define yield() _NOP()
46
- #define interrupts() _NOP()
47
- #define noInterrupts() _NOP()
48
-
49
- // TODO: correctly establish this per-board!
50
- #define F_CPU 1000000UL
51
- #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
52
- #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
53
- #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
54
-
55
- typedef unsigned int word;
56
-
57
- #define bit(b) (1UL << (b))
58
-
59
-
60
-
61
- /*
62
- unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
63
- unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
64
-
65
- void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
66
- uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
67
-
68
- */
69
-
70
- // Get the bit location within the hardware port of the given virtual pin.
71
- // This comes from the pins_*.c file for the active board configuration.
72
-
73
- #define analogInPinToBit(P) (P)
74
- #define digitalPinToInterrupt(P) (P)
75
-
76
- /*
77
- // On the ATmega1280, the addresses of some of the port registers are
78
- // greater than 255, so we can't store them in uint8_t's.
79
- extern const uint16_t PROGMEM port_to_mode_PGM[];
80
- extern const uint16_t PROGMEM port_to_input_PGM[];
81
- extern const uint16_t PROGMEM port_to_output_PGM[];
82
-
83
- extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
84
- // extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
85
- extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
86
- extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
87
-
88
- // Get the bit location within the hardware port of the given virtual pin.
89
- // This comes from the pins_*.c file for the active board configuration.
90
- //
91
- // These perform slightly better as macros compared to inline functions
92
- //
93
- #define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
94
- #define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
95
- #define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
96
- #define analogInPinToBit(P) (P)
97
- #define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
98
- #define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
99
- #define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
100
-
101
- */
102
-
103
-
104
- /* TODO
105
-
106
- // USB
107
- #include "USBAPI.h"
108
- Keyboard
109
- Mouse
110
-
111
- */
112
-
113
- // uint16_t makeWord(uint16_t w);
114
- // uint16_t makeWord(byte h, byte l);
115
- inline unsigned int makeWord(unsigned int w) { return w; }
116
- inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
117
-
118
- #define word(...) makeWord(__VA_ARGS__)
119
-
120
- <<<<<<< Updated upstream
121
-
122
- =======
123
- unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
124
- unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
125
-
126
- // audio is taken care of in GODMODE
127
-
128
-
129
- // BIG TODO ON THIS ONE
130
- // $ find . | grep pins_
131
- // ./arduino-1.8.5/hardware/arduino/avr/variants/circuitplay32u4/pins_arduino.h
132
- // ./arduino-1.8.5/hardware/arduino/avr/variants/eightanaloginputs/pins_arduino.h
133
- // ./arduino-1.8.5/hardware/arduino/avr/variants/ethernet/pins_arduino.h
134
- // ./arduino-1.8.5/hardware/arduino/avr/variants/gemma/pins_arduino.h
135
- // ./arduino-1.8.5/hardware/arduino/avr/variants/leonardo/pins_arduino.h
136
- // ./arduino-1.8.5/hardware/arduino/avr/variants/mega/pins_arduino.h
137
- // ./arduino-1.8.5/hardware/arduino/avr/variants/micro/pins_arduino.h
138
- // ./arduino-1.8.5/hardware/arduino/avr/variants/robot_control/pins_arduino.h
139
- // ./arduino-1.8.5/hardware/arduino/avr/variants/robot_motor/pins_arduino.h
140
- // ./arduino-1.8.5/hardware/arduino/avr/variants/standard/pins_arduino.h
141
- // ./arduino-1.8.5/hardware/arduino/avr/variants/yun/pins_arduino.h
142
- // #include "pins_arduino.h"
143
- >>>>>>> Stashed changes
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'arduino_ci'
3
- require 'set'
4
- require 'pathname'
5
-
6
- WIDTH = 80
7
-
8
- # initialize command and config
9
- config = ArduinoCI::CIConfig.default.from_project_library
10
- @arduino_cmd = ArduinoCI::ArduinoInstallation.autolocate!
11
-
12
- # initialize library under test
13
- installed_library_path = @arduino_cmd.install_local_library(Pathname.new("."))
14
- cpp_library = ArduinoCI::CppLibrary.new(installed_library_path, @arduino_cmd.lib_dir)
15
-
16
- # check GCC
17
- compilers = config.compilers_to_use
18
- compilers.each do |gcc_binary|
19
- puts "Checking #{gcc_binary} version"
20
- puts cpp_library.gcc_version(gcc_binary).split("\n").map { |l| " #{l}" }.join("\n")
21
- exists = cpp_library.libasan?(gcc_binary)
22
- puts "libasan availability for #{gcc_binary}: #{exists}"
23
- next unless exists
24
-
25
- puts "========== Stdout:"
26
- puts @arduino_cmd.last_out
27
- puts "========== Stderr:"
28
- puts @arduino_cmd.last_err
29
- end
@@ -1,328 +0,0 @@
1
- require 'fileutils'
2
- require 'pathname'
3
-
4
- # workaround for https://github.com/arduino/Arduino/issues/3535
5
- WORKAROUND_LIB = "USBHost".freeze
6
-
7
- module ArduinoCI
8
-
9
- # Wrap the Arduino executable. This requires, in some cases, a faked display.
10
- class ArduinoCmd
11
-
12
- # Enable a shortcut syntax for command line flags
13
- # @param name [String] What the flag will be called (prefixed with 'flag_')
14
- # @return [void]
15
- # @macro [attach] flag
16
- # The text of the command line flag for $1
17
- # @!attribute [r] flag_$1
18
- # @return [String] the text of the command line flag (`$2` in this case)
19
- def self.flag(name, text = nil)
20
- text = "(flag #{name} not defined)" if text.nil?
21
- self.class_eval("def flag_#{name};\"#{text}\";end", __FILE__, __LINE__)
22
- end
23
-
24
- # the array of command components to launch the Arduino executable
25
- # @return [Array<String>]
26
- attr_accessor :base_cmd
27
-
28
- # the actual path to the executable on this platform
29
- # @return [Pathname]
30
- attr_accessor :binary_path
31
-
32
- # part of a workaround for https://github.com/arduino/Arduino/issues/3535
33
- attr_reader :libraries_indexed
34
-
35
- # @return [String] STDOUT of the most recently-run command
36
- attr_reader :last_out
37
-
38
- # @return [String] STDERR of the most recently-run command
39
- attr_reader :last_err
40
-
41
- # @return [String] the most recently-run command
42
- attr_reader :last_msg
43
-
44
- # set the command line flags (undefined for now).
45
- # These vary between gui/cli
46
- flag :get_pref
47
- flag :set_pref
48
- flag :save_prefs
49
- flag :use_board
50
- flag :install_boards
51
- flag :install_library
52
- flag :verify
53
-
54
- def initialize
55
- @prefs_cache = {}
56
- @prefs_fetched = false
57
- @libraries_indexed = false
58
- @last_out = ""
59
- @last_err = ""
60
- @last_msg = ""
61
- end
62
-
63
- # Convert a preferences dump into a flat hash
64
- # @param arduino_output [String] The raw Arduino executable output
65
- # @return [Hash] preferences as a hash
66
- def parse_pref_string(arduino_output)
67
- lines = arduino_output.split("\n").select { |l| l.include? "=" }
68
- ret = lines.each_with_object({}) do |e, acc|
69
- parts = e.split("=", 2)
70
- acc[parts[0]] = parts[1]
71
- acc
72
- end
73
- ret
74
- end
75
-
76
- # @return [String] the path to the Arduino libraries directory
77
- def lib_dir
78
- Pathname.new(get_pref("sketchbook.path")) + "libraries"
79
- end
80
-
81
- # fetch preferences in their raw form
82
- # @return [String] Preferences as a set of lines
83
- def _prefs_raw
84
- resp = run_and_capture(flag_get_pref)
85
- return nil unless resp[:success]
86
-
87
- @prefs_fetched = true
88
- resp[:out]
89
- end
90
-
91
- # Get the Arduino preferences, from cache if possible
92
- # @return [Hash] The full set of preferences
93
- def prefs
94
- prefs_raw = _prefs_raw unless @prefs_fetched
95
- return nil if prefs_raw.nil?
96
-
97
- @prefs_cache = parse_pref_string(prefs_raw)
98
- @prefs_cache.clone
99
- end
100
-
101
- # get a preference key
102
- # @param key [String] The preferences key to look up
103
- # @return [String] The preference value
104
- def get_pref(key)
105
- data = @prefs_fetched ? @prefs_cache : prefs
106
- data[key]
107
- end
108
-
109
- # underlying preference-setter.
110
- # @param key [String] The preference name
111
- # @param value [String] The value to set to
112
- # @return [bool] whether the command succeeded
113
- def _set_pref(key, value)
114
- run_and_capture(flag_set_pref, "#{key}=#{value}", flag_save_prefs)[:success]
115
- end
116
-
117
- # set a preference key/value pair, and update the cache.
118
- # @param key [String] the preference key
119
- # @param value [String] the preference value
120
- # @return [bool] whether the command succeeded
121
- def set_pref(key, value)
122
- prefs unless @prefs_fetched # update cache first
123
- success = _set_pref(key, value)
124
- @prefs_cache[key] = value if success
125
- success
126
- end
127
-
128
- def _wrap_run(work_fn, *args, **kwargs)
129
- # do some work to extract & merge environment variables if they exist
130
- has_env = !args.empty? && args[0].class == Hash
131
- env_vars = has_env ? args[0] : {}
132
- actual_args = has_env ? args[1..-1] : args # need to shift over if we extracted args
133
- full_args = @base_cmd + actual_args
134
- full_cmd = env_vars.empty? ? full_args : [env_vars] + full_args
135
-
136
- shell_vars = env_vars.map { |k, v| "#{k}=#{v}" }.join(" ")
137
- @last_msg = " $ #{shell_vars} #{full_args.join(' ')}"
138
- work_fn.call(*full_cmd, **kwargs)
139
- end
140
-
141
- # build and run the arduino command
142
- def run_and_output(*args, **kwargs)
143
- _wrap_run((proc { |*a, **k| Host.run_and_output(*a, **k) }), *args, **kwargs)
144
- end
145
-
146
- # run a command and capture its output
147
- # @return [Hash] {:out => String, :err => String, :success => bool}
148
- def run_and_capture(*args, **kwargs)
149
- ret = _wrap_run((proc { |*a, **k| Host.run_and_capture(*a, **k) }), *args, **kwargs)
150
- @last_err = ret[:err]
151
- @last_out = ret[:out]
152
- ret
153
- end
154
-
155
- # Board manager URLs
156
- # @return [Array<String>] The additional URLs used by the board manager
157
- def board_manager_urls
158
- url_list = get_pref("boardsmanager.additional.urls")
159
- return [] if url_list.nil?
160
-
161
- url_list.split(",")
162
- end
163
-
164
- # Set board manager URLs
165
- # @return [Array<String>] The additional URLs used by the board manager
166
- def board_manager_urls=(all_urls)
167
- set_pref("boardsmanager.additional.urls", all_urls.join(","))
168
- end
169
-
170
- # check whether a board is installed
171
- # we do this by just selecting a board.
172
- # the arduino binary will error if unrecognized and do a successful no-op if it's installed
173
- # @param boardname [String] The board to test
174
- # @return [bool] Whether the board is installed
175
- def board_installed?(boardname)
176
- run_and_capture(flag_use_board, boardname)[:success]
177
- end
178
-
179
- # install a board by name
180
- # @param name [String] the board name
181
- # @return [bool] whether the command succeeded
182
- def install_boards(boardfamily)
183
- # TODO: find out why IO.pipe fails but File::NULL succeeds :(
184
- result = run_and_capture(flag_install_boards, boardfamily)
185
- already_installed = result[:err].include?("Platform is already installed!")
186
- result[:success] || already_installed
187
- end
188
-
189
- # install a library by name
190
- # @param name [String] the library name
191
- # @return [bool] whether the command succeeded
192
- def _install_library(library_name)
193
- result = run_and_capture(flag_install_library, library_name)
194
-
195
- already_installed = result[:err].include?("Library is already installed: #{library_name}")
196
- success = result[:success] || already_installed
197
-
198
- @libraries_indexed = (@libraries_indexed || success) if library_name == WORKAROUND_LIB
199
- success
200
- end
201
-
202
- # index the set of libraries by installing a dummy library
203
- # related to WORKAROUND_LIB and https://github.com/arduino/Arduino/issues/3535
204
- # TODO: unclear if this is still necessary
205
- def index_libraries
206
- return true if @libraries_indexed
207
-
208
- _install_library(WORKAROUND_LIB)
209
- @libraries_indexed
210
- end
211
-
212
- # install a library by name
213
- # @param name [String] the library name
214
- # @return [bool] whether the command succeeded
215
- def install_library(library_name)
216
- index_libraries
217
- _install_library(library_name)
218
- end
219
-
220
- # generate the (very likely) path of a library given its name
221
- # @param library_name [String] The name of the library
222
- # @return [Pathname] The fully qualified library name
223
- def library_path(library_name)
224
- Pathname.new(lib_dir) + library_name
225
- end
226
-
227
- # Determine whether a library is present in the lib dir
228
- #
229
- # Note that `true` doesn't guarantee that the library is valid/installed
230
- # and `false` doesn't guarantee that the library isn't built-in
231
- #
232
- # @param library_name [String] The name of the library
233
- # @return [bool]
234
- def library_present?(library_name)
235
- library_path(library_name).exist?
236
- end
237
-
238
- # update the library index
239
- # @return [bool] Whether the update succeeded
240
- def update_library_index
241
- # install random lib so the arduino IDE grabs a new library index
242
- # see: https://github.com/arduino/Arduino/issues/3535
243
- install_library(WORKAROUND_LIB)
244
- end
245
-
246
- # use a particular board for compilation
247
- # @param boardname [String] The board to use
248
- # @return [bool] whether the command succeeded
249
- def use_board(boardname)
250
- run_and_capture(flag_use_board, boardname, flag_save_prefs)[:success]
251
- end
252
-
253
- # use a particular board for compilation, installing it if necessary
254
- # @param boardname [String] The board to use
255
- # @return [bool] whether the command succeeded
256
- def use_board!(boardname)
257
- return true if use_board(boardname)
258
-
259
- boardfamily = boardname.split(":")[0..1].join(":")
260
- puts "Board '#{boardname}' not found; attempting to install '#{boardfamily}'"
261
- return false unless install_boards(boardfamily) # guess board family from first 2 :-separated fields
262
-
263
- use_board(boardname)
264
- end
265
-
266
- # @param path [String] The sketch to verify
267
- # @return [bool] whether the command succeeded
268
- def verify_sketch(path)
269
- ext = File.extname path
270
- unless ext.casecmp(".ino").zero?
271
- @last_msg = "Refusing to verify sketch with '#{ext}' extension -- rename it to '.ino'!"
272
- return false
273
- end
274
- unless File.exist? path
275
- @last_msg = "Can't verify Sketch at nonexistent path '#{path}'!"
276
- return false
277
- end
278
- ret = run_and_capture(flag_verify, path)
279
- ret[:success]
280
- end
281
-
282
- # ensure that the given library is installed, or symlinked as appropriate
283
- # return the path of the prepared library, or nil
284
- # @param path [Pathname] library to use
285
- # @return [String] the path of the installed library
286
- def install_local_library(path)
287
- src_path = path.realpath
288
- library_name = src_path.basename
289
- destination_path = library_path(library_name)
290
-
291
- # things get weird if the sketchbook contains the library.
292
- # check that first
293
- if destination_path.exist?
294
- uhoh = "There is already a library '#{library_name}' in the library directory"
295
- return destination_path if destination_path == src_path
296
-
297
- # maybe it's a symlink? that would be OK
298
- if destination_path.symlink?
299
- return destination_path if destination_path.readlink == src_path
300
-
301
- @last_msg = "#{uhoh} and it's not symlinked to #{src_path}"
302
- return nil
303
- end
304
-
305
- @last_msg = "#{uhoh}. It may need to be removed manually."
306
- return nil
307
- end
308
-
309
- # install the library
310
- Host.symlink(src_path, destination_path)
311
- destination_path
312
- end
313
-
314
- # @param installed_library_path [String] The library to query
315
- # @return [Array<String>] Example sketch files
316
- def library_examples(installed_library_path)
317
- example_path = Pathname.new(installed_library_path) + "examples"
318
- return [] unless File.exist?(example_path)
319
-
320
- examples = example_path.children.select(&:directory?).map(&:to_path).map(&File.method(:basename))
321
- files = examples.map do |e|
322
- proj_file = example_path + e + "#{e}.ino"
323
- proj_file.exist? ? proj_file.to_s : nil
324
- end
325
- files.reject(&:nil?).sort_by(&:to_s)
326
- end
327
- end
328
- end