arduino_ci 0.4.0 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +34 -7
- data/cpp/arduino/Client.h +1 -0
- data/exe/arduino_ci.rb +85 -86
- data/exe/arduino_library_location.rb +2 -2
- data/lib/arduino_ci/arduino_backend.rb +218 -0
- data/lib/arduino_ci/arduino_downloader.rb +42 -73
- data/lib/arduino_ci/arduino_downloader_linux.rb +17 -55
- data/lib/arduino_ci/arduino_downloader_osx.rb +21 -33
- data/lib/arduino_ci/arduino_downloader_windows.rb +11 -53
- data/lib/arduino_ci/arduino_installation.rb +13 -75
- data/lib/arduino_ci/ci_config.rb +0 -7
- data/lib/arduino_ci/cpp_library.rb +166 -79
- data/lib/arduino_ci/host.rb +59 -4
- data/lib/arduino_ci/library_properties.rb +12 -2
- data/lib/arduino_ci/version.rb +1 -1
- data/misc/default.yml +6 -2
- metadata +3 -78
- data/lib/arduino_ci/arduino_cmd.rb +0 -332
- data/lib/arduino_ci/arduino_cmd_linux.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -19
- data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
- data/lib/arduino_ci/installed_cpp_library.rb +0 -0
@@ -1,16 +1,10 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require "arduino_ci/host"
|
3
|
-
require "arduino_ci/
|
4
|
-
require "arduino_ci/arduino_cmd_linux"
|
5
|
-
require "arduino_ci/arduino_cmd_windows"
|
6
|
-
require "arduino_ci/arduino_cmd_linux_builder"
|
3
|
+
require "arduino_ci/arduino_backend"
|
7
4
|
require "arduino_ci/arduino_downloader_osx"
|
8
5
|
require "arduino_ci/arduino_downloader_linux"
|
9
|
-
|
10
6
|
require "arduino_ci/arduino_downloader_windows" if ArduinoCI::Host.os == :windows
|
11
7
|
|
12
|
-
DESIRED_ARDUINO_IDE_VERSION = "1.8.6".freeze
|
13
|
-
|
14
8
|
module ArduinoCI
|
15
9
|
|
16
10
|
class ArduinoInstallationError < StandardError; end
|
@@ -18,85 +12,29 @@ module ArduinoCI
|
|
18
12
|
# Manage the OS-specific install location of Arduino
|
19
13
|
class ArduinoInstallation
|
20
14
|
|
15
|
+
DESIRED_ARDUINO_CLI_VERSION = "0.13.0".freeze
|
16
|
+
|
21
17
|
class << self
|
22
18
|
|
23
19
|
# attempt to find a workable Arduino executable across platforms
|
24
20
|
#
|
25
21
|
# Autolocation assumed to be an expensive operation
|
26
|
-
# @return [ArduinoCI::
|
22
|
+
# @return [ArduinoCI::ArduinoBackend] an instance of the command or nil if it can't be found
|
27
23
|
def autolocate
|
28
|
-
|
29
|
-
|
30
|
-
when :
|
31
|
-
|
32
|
-
when :linux then
|
33
|
-
loc = ArduinoDownloaderLinux.autolocated_executable
|
34
|
-
return nil if loc.nil?
|
35
|
-
|
36
|
-
ret = ArduinoCmdLinux.new
|
37
|
-
ret.base_cmd = [loc]
|
38
|
-
ret.binary_path = Pathname.new(loc)
|
39
|
-
when :windows then
|
40
|
-
loc = ArduinoDownloaderWindows.autolocated_executable
|
41
|
-
return nil if loc.nil?
|
42
|
-
|
43
|
-
ret = ArduinoCmdWindows.new
|
44
|
-
ret.base_cmd = [loc]
|
45
|
-
ret.binary_path = Pathname.new(loc)
|
24
|
+
downloader_class = case Host.os
|
25
|
+
when :osx then ArduinoDownloaderOSX
|
26
|
+
when :linux then ArduinoDownloaderLinux
|
27
|
+
when :windows then ArduinoDownloaderWindows
|
46
28
|
end
|
47
|
-
ret
|
48
|
-
end
|
49
|
-
|
50
|
-
# @return [ArduinoCI::ArduinoCmdOSX] an instance of the command or nil if it can't be found
|
51
|
-
def autolocate_osx
|
52
|
-
osx_root = ArduinoDownloaderOSX.autolocated_installation
|
53
|
-
return nil if osx_root.nil?
|
54
|
-
return nil unless File.exist? osx_root
|
55
|
-
|
56
|
-
launchers = [
|
57
|
-
# try a hack that skips splash screen
|
58
|
-
# from https://github.com/arduino/Arduino/issues/1970#issuecomment-321975809
|
59
|
-
[
|
60
|
-
"java",
|
61
|
-
"-cp",
|
62
|
-
"#{osx_root}/Contents/Java/*",
|
63
|
-
"-DAPP_DIR=#{osx_root}/Contents/Java",
|
64
|
-
"-Dfile.encoding=UTF-8",
|
65
|
-
"-Dapple.awt.UIElement=true",
|
66
|
-
"-Xms128M",
|
67
|
-
"-Xmx512M",
|
68
|
-
"processing.app.Base",
|
69
|
-
],
|
70
|
-
# failsafe way
|
71
|
-
[File.join(osx_root, "Contents", "MacOS", "Arduino")]
|
72
|
-
]
|
73
29
|
|
74
|
-
|
75
|
-
|
76
|
-
launchers.each do |launcher|
|
77
|
-
# test whether this method successfully launches the IDE
|
78
|
-
# note that "successful launch" involves a command that will fail,
|
79
|
-
# because that's faster than any command which succeeds. what we
|
80
|
-
# don't want to see is a java error.
|
81
|
-
args = launcher + ["--bogus-option"]
|
82
|
-
result = Host.run_and_capture(*args)
|
30
|
+
loc = downloader_class.autolocated_executable
|
31
|
+
return nil if loc.nil?
|
83
32
|
|
84
|
-
|
85
|
-
# but also need to find "Erreur: option inconnue : --bogus-option"
|
86
|
-
# and who knows how many other languages.
|
87
|
-
# For now, just search for the end of the error and hope that the java-style
|
88
|
-
# launch of this won't include a similar string in it
|
89
|
-
next unless result[:err].include? ": --bogus-option"
|
90
|
-
|
91
|
-
ret.base_cmd = launcher
|
92
|
-
ret.binary_path = Pathname.new(osx_root)
|
93
|
-
return ret
|
94
|
-
end
|
95
|
-
nil
|
33
|
+
ArduinoBackend.new(loc)
|
96
34
|
end
|
97
35
|
|
98
36
|
# Attempt to find a workable Arduino executable across platforms, and install it if we don't
|
99
|
-
# @return [ArduinoCI::
|
37
|
+
# @return [ArduinoCI::ArduinoBackend] an instance of a command
|
100
38
|
def autolocate!(output = $stdout)
|
101
39
|
candidate = autolocate
|
102
40
|
return candidate unless candidate.nil?
|
@@ -109,7 +47,7 @@ module ArduinoCI
|
|
109
47
|
|
110
48
|
# Forcibly install Arduino from the web
|
111
49
|
# @return [bool] Whether the command succeeded
|
112
|
-
def force_install(output = $stdout, version =
|
50
|
+
def force_install(output = $stdout, version = DESIRED_ARDUINO_CLI_VERSION)
|
113
51
|
worker_class = case Host.os
|
114
52
|
when :osx then ArduinoDownloaderOSX
|
115
53
|
when :windows then ArduinoDownloaderWindows
|
data/lib/arduino_ci/ci_config.rb
CHANGED
@@ -232,13 +232,6 @@ module ArduinoCI
|
|
232
232
|
deep_clone(defn)
|
233
233
|
end
|
234
234
|
|
235
|
-
# Whether a package is built-in to arduino
|
236
|
-
# @param package [String] the package name (e.g. "arduino:avr")
|
237
|
-
# @return [bool]
|
238
|
-
def package_builtin?(package)
|
239
|
-
package.start_with?("arduino:")
|
240
|
-
end
|
241
|
-
|
242
235
|
# the URL that gives the download info for a given package (a JSON file).
|
243
236
|
# this is NOT where the package comes from.
|
244
237
|
# @param package [String] the package name (e.g. "arduino:avr")
|
@@ -14,15 +14,21 @@ module ArduinoCI
|
|
14
14
|
# Information about an Arduino CPP library, specifically for compilation purposes
|
15
15
|
class CppLibrary
|
16
16
|
|
17
|
-
# @return [
|
18
|
-
|
17
|
+
# @return [String] The official library properties file name
|
18
|
+
LIBRARY_PROPERTIES_FILE = "library.properties".freeze
|
19
19
|
|
20
|
-
# @return [
|
21
|
-
attr_reader :
|
20
|
+
# @return [String] The "official" name of the library, which can include spaces (in a way that the lib dir won't)
|
21
|
+
attr_reader :name
|
22
|
+
|
23
|
+
# @return [ArduinoBackend] The backend support for this library
|
24
|
+
attr_reader :backend
|
22
25
|
|
23
26
|
# @return [Array<Pathname>] The set of artifacts created by this class (note: incomplete!)
|
24
27
|
attr_reader :artifacts
|
25
28
|
|
29
|
+
# @return [Array<Pathname>] The set of directories that should be excluded from compilation
|
30
|
+
attr_reader :exclude_dirs
|
31
|
+
|
26
32
|
# @return [String] STDERR from the last command
|
27
33
|
attr_reader :last_err
|
28
34
|
|
@@ -35,30 +41,100 @@ module ArduinoCI
|
|
35
41
|
# @return [Array<Pathname>] Directories suspected of being vendor-bundle
|
36
42
|
attr_reader :vendor_bundle_cache
|
37
43
|
|
38
|
-
# @param
|
39
|
-
# @param
|
40
|
-
|
41
|
-
|
42
|
-
raise ArgumentError, '
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@base_dir = base_dir
|
48
|
-
@exclude_dirs = exclude_dirs
|
49
|
-
@arduino_lib_dir = arduino_lib_dir.expand_path
|
44
|
+
# @param friendly_name [String] The "official" name of the library, which can contain spaces
|
45
|
+
# @param backend [ArduinoBackend] The support backend
|
46
|
+
def initialize(friendly_name, backend)
|
47
|
+
raise ArgumentError, "friendly_name is not a String (got #{friendly_name.class})" unless friendly_name.is_a? String
|
48
|
+
raise ArgumentError, 'backend is not a ArduinoBackend' unless backend.is_a? ArduinoBackend
|
49
|
+
|
50
|
+
@name = friendly_name
|
51
|
+
@backend = backend
|
52
|
+
@info_cache = nil
|
50
53
|
@artifacts = []
|
51
54
|
@last_err = ""
|
52
55
|
@last_out = ""
|
53
56
|
@last_msg = ""
|
54
57
|
@has_libasan_cache = {}
|
55
58
|
@vendor_bundle_cache = nil
|
59
|
+
@exclude_dirs = []
|
60
|
+
end
|
61
|
+
|
62
|
+
# Generate a guess as to the on-disk (coerced character) name of this library
|
63
|
+
#
|
64
|
+
# @TODO: delegate this to the backend in some way? It uses "official" names for install, but dir names in lists :(
|
65
|
+
# @param friendly_name [String] The library name as it might appear in library manager
|
66
|
+
# @return [String] How the path will be stored on disk -- spaces are coerced to underscores
|
67
|
+
def self.library_directory_name(friendly_name)
|
68
|
+
friendly_name.tr(" ", "_")
|
69
|
+
end
|
70
|
+
|
71
|
+
# Generate a guess as to the on-disk (coerced character) name of this library
|
72
|
+
#
|
73
|
+
# @TODO: delegate this to the backend in some way? It uses "official" names for install, but dir names in lists :(
|
74
|
+
# @return [String] How the path will be stored on disk -- spaces are coerced to underscores
|
75
|
+
def name_on_disk
|
76
|
+
self.class.library_directory_name(@name)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Get the path to this library, whether or not it exists
|
80
|
+
# @return [Pathname] The fully qualified library path
|
81
|
+
def path
|
82
|
+
@backend.lib_dir + name_on_disk
|
83
|
+
end
|
84
|
+
|
85
|
+
# Determine whether a library is present in the lib dir
|
86
|
+
#
|
87
|
+
# Note that `true` doesn't guarantee that the library is valid/installed
|
88
|
+
# and `false` doesn't guarantee that the library isn't built-in
|
89
|
+
#
|
90
|
+
# @return [bool]
|
91
|
+
def installed?
|
92
|
+
path.exist?
|
93
|
+
end
|
94
|
+
|
95
|
+
# install a library by name
|
96
|
+
# @param version [String] the version to install
|
97
|
+
# @param recursive [bool] whether to also install its dependencies
|
98
|
+
# @return [bool] whether the command succeeded
|
99
|
+
def install(version = nil, recursive = false)
|
100
|
+
return true if installed? && !recursive
|
101
|
+
|
102
|
+
fqln = version.nil? ? @name : "#{@name}@#{version}"
|
103
|
+
result = if recursive
|
104
|
+
@backend.run_and_capture("lib", "install", fqln)
|
105
|
+
else
|
106
|
+
@backend.run_and_capture("lib", "install", "--no-deps", fqln)
|
107
|
+
end
|
108
|
+
result[:success]
|
109
|
+
end
|
110
|
+
|
111
|
+
# information about the library as reported by the backend
|
112
|
+
# @return [Hash] the metadata object
|
113
|
+
def info
|
114
|
+
return nil unless installed?
|
115
|
+
|
116
|
+
# note that if the library isn't found, we're going to do a lot of cache attempts...
|
117
|
+
if @info_cache.nil?
|
118
|
+
@info_cache = @backend.installed_libraries.find do |l|
|
119
|
+
lib_info = l["library"]
|
120
|
+
Pathname.new(lib_info["install_dir"]).realpath == path.realpath
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
@info_cache
|
125
|
+
end
|
126
|
+
|
127
|
+
# @param installed_library_path [String] The library to query
|
128
|
+
# @return [Array<String>] Example sketch files
|
129
|
+
def example_sketches
|
130
|
+
reported_dirs = info["library"]["examples"].map(&Pathname::method(:new))
|
131
|
+
reported_dirs.map { |e| e + e.basename.sub_ext(".ino") }.select(&:exist?).sort_by(&:to_s)
|
56
132
|
end
|
57
133
|
|
58
134
|
# The expected path to the library.properties file (i.e. even if it does not exist)
|
59
135
|
# @return [Pathname]
|
60
136
|
def library_properties_path
|
61
|
-
|
137
|
+
path + LIBRARY_PROPERTIES_FILE
|
62
138
|
end
|
63
139
|
|
64
140
|
# Whether library.properties definitions for this library exist
|
@@ -68,16 +144,29 @@ module ArduinoCI
|
|
68
144
|
lib_props.exist? && lib_props.file?
|
69
145
|
end
|
70
146
|
|
147
|
+
# Library properties
|
148
|
+
# @return [LibraryProperties] The library.properties metadata wrapper for this library
|
149
|
+
def library_properties
|
150
|
+
return nil unless library_properties?
|
151
|
+
|
152
|
+
LibraryProperties.new(library_properties_path)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Set directories that should be excluded from compilation
|
156
|
+
# @param rval [Array] Array of strings or pathnames that will be coerced to pathnames
|
157
|
+
def exclude_dirs=(rval)
|
158
|
+
@exclude_dirs = rval.map { |d| d.is_a?(Pathname) ? d : Pathname.new(d) }
|
159
|
+
end
|
160
|
+
|
71
161
|
# Decide whether this is a 1.5-compatible library
|
72
162
|
#
|
73
|
-
# according to https://arduino.github.io/arduino-cli/latest/library-specification
|
74
|
-
#
|
75
|
-
# Should match logic from https://github.com/arduino/arduino-cli/blob/master/arduino/libraries/loader.go
|
163
|
+
# This should be according to https://arduino.github.io/arduino-cli/latest/library-specification
|
164
|
+
# but we rely on the cli to decide for us
|
76
165
|
# @return [bool]
|
77
166
|
def one_point_five?
|
78
167
|
return false unless library_properties?
|
79
168
|
|
80
|
-
src_dir =
|
169
|
+
src_dir = path + "src"
|
81
170
|
src_dir.exist? && src_dir.directory?
|
82
171
|
end
|
83
172
|
|
@@ -88,9 +177,9 @@ module ArduinoCI
|
|
88
177
|
# That gets us the vendor directory (or multiple directories). We can check
|
89
178
|
# if the given path is contained by any of those.
|
90
179
|
#
|
91
|
-
# @param
|
180
|
+
# @param some_path [Pathname] The path to check
|
92
181
|
# @return [bool]
|
93
|
-
def vendor_bundle?(
|
182
|
+
def vendor_bundle?(some_path)
|
94
183
|
# Cache bundle information, as it is (1) time consuming to fetch and (2) not going to change while we run
|
95
184
|
if @vendor_bundle_cache.nil?
|
96
185
|
bundle_info = Host.run_and_capture("bundle show --paths")
|
@@ -125,7 +214,7 @@ module ArduinoCI
|
|
125
214
|
|
126
215
|
# With vendor bundles located, check this file against those
|
127
216
|
@vendor_bundle_cache.any? do |gem_path|
|
128
|
-
|
217
|
+
some_path.ascend do |part|
|
129
218
|
break true if gem_path == part
|
130
219
|
end
|
131
220
|
end
|
@@ -135,13 +224,13 @@ module ArduinoCI
|
|
135
224
|
#
|
136
225
|
# @param path [Pathname] The path to check
|
137
226
|
# @return [bool]
|
138
|
-
def in_tests_dir?(
|
227
|
+
def in_tests_dir?(sourcefile_path)
|
139
228
|
return false unless tests_dir.exist?
|
140
229
|
|
141
230
|
tests_dir_aliases = [tests_dir, tests_dir.realpath]
|
142
231
|
# we could do this but some rubies don't return an enumerator for ascend
|
143
232
|
# path.ascend.any? { |part| tests_dir_aliases.include?(part) }
|
144
|
-
|
233
|
+
sourcefile_path.ascend do |part|
|
145
234
|
return true if tests_dir_aliases.include?(part)
|
146
235
|
end
|
147
236
|
false
|
@@ -151,11 +240,11 @@ module ArduinoCI
|
|
151
240
|
#
|
152
241
|
# @param path [Pathname] The path to check
|
153
242
|
# @return [bool]
|
154
|
-
def in_exclude_dir?(
|
243
|
+
def in_exclude_dir?(sourcefile_path)
|
155
244
|
# we could do this but some rubies don't return an enumerator for ascend
|
156
245
|
# path.ascend.any? { |part| tests_dir_aliases.include?(part) }
|
157
|
-
|
158
|
-
return true if exclude_dir.any? { |p| p.realpath == part }
|
246
|
+
sourcefile_path.ascend do |part|
|
247
|
+
return true if exclude_dir.any? { |p| p.realpath == part.realpath }
|
159
248
|
end
|
160
249
|
false
|
161
250
|
end
|
@@ -166,42 +255,26 @@ module ArduinoCI
|
|
166
255
|
# @param gcc_binary [String]
|
167
256
|
def libasan?(gcc_binary)
|
168
257
|
unless @has_libasan_cache.key?(gcc_binary)
|
169
|
-
|
170
|
-
begin
|
258
|
+
Tempfile.create(["arduino_ci_libasan_check", ".cpp"]) do |file|
|
171
259
|
file.write "int main(){}"
|
172
260
|
file.close
|
173
261
|
@has_libasan_cache[gcc_binary] = run_gcc(gcc_binary, "-o", "/dev/null", "-fsanitize=address", file.path)
|
174
|
-
ensure
|
175
|
-
file.delete
|
176
262
|
end
|
177
263
|
end
|
178
264
|
@has_libasan_cache[gcc_binary]
|
179
265
|
end
|
180
266
|
|
181
|
-
# Library properties
|
182
|
-
def library_properties
|
183
|
-
return nil unless library_properties?
|
184
|
-
|
185
|
-
LibraryProperties.new(library_properties_path)
|
186
|
-
end
|
187
|
-
|
188
|
-
# Get a list of all dependencies as defined in library.properties
|
189
|
-
# @return [Array<String>] The library names of the dependencies (not the paths)
|
190
|
-
def arduino_library_dependencies
|
191
|
-
return nil unless library_properties?
|
192
|
-
|
193
|
-
library_properties.depends
|
194
|
-
end
|
195
|
-
|
196
267
|
# Get a list of all CPP source files in a directory and its subdirectories
|
197
268
|
# @param some_dir [Pathname] The directory in which to begin the search
|
198
269
|
# @param extensions [Array<Sring>] The set of allowable file extensions
|
199
270
|
# @return [Array<Pathname>] The paths of the found files
|
200
271
|
def code_files_in(some_dir, extensions)
|
201
272
|
raise ArgumentError, 'some_dir is not a Pathname' unless some_dir.is_a? Pathname
|
202
|
-
return [] unless some_dir.exist? && some_dir.directory?
|
203
273
|
|
204
|
-
|
274
|
+
full_dir = path + some_dir
|
275
|
+
return [] unless full_dir.exist? && full_dir.directory?
|
276
|
+
|
277
|
+
files = full_dir.children.reject(&:directory?)
|
205
278
|
cpp = files.select { |path| extensions.include?(path.extname.downcase) }
|
206
279
|
not_hidden = cpp.reject { |path| path.basename.to_s.start_with?(".") }
|
207
280
|
not_hidden.sort_by(&:to_s)
|
@@ -215,17 +288,18 @@ module ArduinoCI
|
|
215
288
|
raise ArgumentError, 'some_dir is not a Pathname' unless some_dir.is_a? Pathname
|
216
289
|
return [] unless some_dir.exist? && some_dir.directory?
|
217
290
|
|
218
|
-
|
219
|
-
Find.find(real).map { |p| Pathname.new(p) }.select(&:directory?).map { |d| code_files_in(d, extensions) }.flatten
|
291
|
+
Find.find(some_dir).map { |p| Pathname.new(p) }.select(&:directory?).map { |d| code_files_in(d, extensions) }.flatten
|
220
292
|
end
|
221
293
|
|
222
|
-
#
|
294
|
+
# Source files that are part of the library under test
|
295
|
+
# @param extensions [Array<String>] the allowed extensions (or, the ones we're looking for)
|
223
296
|
# @return [Array<Pathname>]
|
224
|
-
def
|
297
|
+
def source_files(extensions)
|
298
|
+
source_dir = Pathname.new(info["library"]["source_dir"])
|
225
299
|
ret = if one_point_five?
|
226
|
-
code_files_in_recursive(
|
300
|
+
code_files_in_recursive(source_dir, extensions)
|
227
301
|
else
|
228
|
-
[
|
302
|
+
[source_dir, source_dir + "utility"].map { |d| code_files_in(d, extensions) }.flatten
|
229
303
|
end
|
230
304
|
|
231
305
|
# note to future troubleshooter: some of these tests may not be relevant, but at the moment at
|
@@ -233,18 +307,16 @@ module ArduinoCI
|
|
233
307
|
ret.reject { |p| vendor_bundle?(p) || in_tests_dir?(p) || in_exclude_dir?(p) }
|
234
308
|
end
|
235
309
|
|
310
|
+
# Header files that are part of the project library under test
|
311
|
+
# @return [Array<Pathname>]
|
312
|
+
def header_files
|
313
|
+
source_files(HPP_EXTENSIONS)
|
314
|
+
end
|
315
|
+
|
236
316
|
# CPP files that are part of the project library under test
|
237
317
|
# @return [Array<Pathname>]
|
238
318
|
def cpp_files
|
239
|
-
|
240
|
-
code_files_in_recursive(@base_dir + "src", CPP_EXTENSIONS)
|
241
|
-
else
|
242
|
-
[@base_dir, @base_dir + "utility"].map { |d| code_files_in(d, CPP_EXTENSIONS) }.flatten
|
243
|
-
end
|
244
|
-
|
245
|
-
# note to future troubleshooter: some of these tests may not be relevant, but at the moment at
|
246
|
-
# least some of them are tied to existing features
|
247
|
-
ret.reject { |p| vendor_bundle?(p) || in_tests_dir?(p) || in_exclude_dir?(p) }
|
319
|
+
source_files(CPP_EXTENSIONS)
|
248
320
|
end
|
249
321
|
|
250
322
|
# CPP files that are part of the arduino mock library we're providing
|
@@ -269,13 +341,13 @@ module ArduinoCI
|
|
269
341
|
# Returns the Pathnames for all paths to exclude from testing and compilation
|
270
342
|
# @return [Array<Pathname>]
|
271
343
|
def exclude_dir
|
272
|
-
@exclude_dirs.map { |p| Pathname.new(
|
344
|
+
@exclude_dirs.map { |p| Pathname.new(path) + p }.select(&:exist?)
|
273
345
|
end
|
274
346
|
|
275
347
|
# The directory where we expect to find unit test defintions provided by the user
|
276
348
|
# @return [Pathname]
|
277
349
|
def tests_dir
|
278
|
-
Pathname.new(
|
350
|
+
Pathname.new(path) + "test"
|
279
351
|
end
|
280
352
|
|
281
353
|
# The files provided by the user that contain unit tests
|
@@ -311,18 +383,33 @@ module ArduinoCI
|
|
311
383
|
@last_err
|
312
384
|
end
|
313
385
|
|
314
|
-
#
|
315
|
-
# @return [Array<
|
316
|
-
def
|
386
|
+
# Get a list of all dependencies as defined in library.properties
|
387
|
+
# @return [Array<String>] The library names of the dependencies (not the paths)
|
388
|
+
def arduino_library_dependencies
|
389
|
+
return [] unless library_properties?
|
390
|
+
return [] if library_properties.depends.nil?
|
391
|
+
|
392
|
+
library_properties.depends
|
393
|
+
end
|
394
|
+
|
395
|
+
# Arduino library dependencies all the way down, installing if they are not present
|
396
|
+
# @return [Array<String>] The library names of the dependencies (not the paths)
|
397
|
+
def all_arduino_library_dependencies!(additional_libraries = [])
|
317
398
|
# Pull in all possible places that headers could live, according to the spec:
|
318
399
|
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification
|
400
|
+
recursive = (additional_libraries + arduino_library_dependencies).map do |n|
|
401
|
+
other_lib = self.class.new(n, @backend)
|
402
|
+
other_lib.install unless other_lib.installed?
|
403
|
+
other_lib.all_arduino_library_dependencies!
|
404
|
+
end.flatten
|
405
|
+
ret = (additional_libraries + recursive).uniq
|
406
|
+
ret
|
407
|
+
end
|
319
408
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
self.class.new(@arduino_lib_dir + legal_dir, @arduino_lib_dir, @exclude_dirs).header_dirs
|
325
|
-
end.flatten.uniq
|
409
|
+
# Arduino library directories containing sources -- only those of the dependencies
|
410
|
+
# @return [Array<Pathname>]
|
411
|
+
def arduino_library_src_dirs(aux_libraries)
|
412
|
+
all_arduino_library_dependencies!(aux_libraries).map { |l| self.class.new(l, @backend).header_dirs }.flatten.uniq
|
326
413
|
end
|
327
414
|
|
328
415
|
# GCC command line arguments for including aux libraries
|
@@ -415,9 +502,9 @@ module ArduinoCI
|
|
415
502
|
|
416
503
|
# combine library.properties defs (if existing) with config file.
|
417
504
|
# TODO: as much as I'd like to rely only on the properties file(s), I think that would prevent testing 1.0-spec libs
|
418
|
-
|
419
|
-
arg_sets << test_args(
|
420
|
-
arg_sets << cpp_files_libraries(
|
505
|
+
full_dependencies = all_arduino_library_dependencies!(aux_libraries)
|
506
|
+
arg_sets << test_args(full_dependencies, ci_gcc_config)
|
507
|
+
arg_sets << cpp_files_libraries(full_dependencies).map(&:to_s)
|
421
508
|
arg_sets << [test_file.to_s]
|
422
509
|
args = arg_sets.flatten(1)
|
423
510
|
return nil unless run_gcc(gcc_binary, *args)
|