arduino_ci 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|