forked from u-blox/ubxlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathu_arduino_common.py
269 lines (242 loc) · 11 KB
/
u_arduino_common.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/usr/bin/env python
'''Stuff used by both u_arduino_lib.py and u_arduino_test.py.'''
import os
import subprocess
import platform # Figure out current OS
# The e-mail address to contact ubxlib
UBXLIB_EMAIL = "ubxlib@u-blox.com"
# The name of the library
LIBRARY_NAME = "ubxlib"
# The name of the library properties file
PROPERTIES_FILE = "library.properties"
# Architectures supported: the first item in each list
# is the ubxlib platform name and the subsequent items
# are the corresponding Arduino architecture(s)
ARCHITECTURES = [["esp-idf", "esp32"]]
# The strings which indicate that an include path is public
PUBLIC_INCLUDE_INDICATOR = ["cfg" + os.sep,
os.sep + "api" + os.sep,
"_clib_",
"platform" + os.sep + "esp-idf"]
def read_list_from_file(file, wanted_platform):
'''Read a list, line by line, from a file'''
output_list = []
# Read list
temp_list = [line.strip() for line in open(file, 'r')]
for item in temp_list:
# Throw away comment lines
item = item.strip()
if item and not item.startswith("#"):
platform_type = None
try:
platform_type = item.split("port/platform")[1].split("/")[0]
except:
pass
if not platform_type or ("common" or wanted_platform in platform_type):
output_list.append(item)
return output_list
# subprocess arguments behaves a little differently on Linux and Windows
# depending if a shell is used or not, which can be read here:
# https://stackoverflow.com/a/15109975
# This function will compensate for these deviations
def subprocess_osify(cmd, shell=True):
''' expects an array of strings being [command, param, ...] '''
if platform.system() != "Windows" and shell:
line = ''
for command in cmd:
# Put everything in a single string and quote args containing spaces
if ' ' in command:
line += '\"{}\" '.format(command)
else:
line += '{} '.format(command)
cmd = line
return cmd
# Copy a file from A to B, full paths included
def copy_file(source, destination, forced):
'''Copy a file from A to B'''
return_value = -1
# If a given file either does not exist in the destination
# directory (with a .cpp extension if it is a source file)
# or the one in the ubxlib source directory has a more recent
# modification date than the one under this directory then
# copy it from the ubxlib location into here.
if os.path.isfile(source):
do_copy = True
if not forced:
try:
source_timestamp = os.path.getmtime(source)
destination_timestamp = os.path.getmtime(destination)
if destination_timestamp == source_timestamp:
do_copy = False
return_value = 0
print("{} is already up to date.".format(destination))
else:
if destination_timestamp > source_timestamp:
do_copy = False
return_value = 0
print("WARNING: not updating {} as it has been locally modified.". \
format(destination))
except OSError:
pass
if do_copy:
directories = os.path.dirname(destination)
if not os.path.isdir(directories):
try:
os.makedirs(directories)
except OSError:
print("Unable to create directory {}.".format(directories))
do_copy = False
if do_copy:
call_list = []
if platform.system() == "Windows":
call_list.append("copy")
call_list.append("/Y")
else:
call_list.append("cp")
call_list.append(source)
call_list.append(destination)
try:
print("Copying {} to {}...".format(source, destination))
subprocess.check_output(subprocess_osify(call_list), shell=True)
return_value = 1
except subprocess.CalledProcessError as error:
print("Error when copying {} to {}, {} {}: \"{}\"".
format(source, destination, error.cmd,
error.returncode, error.output))
else:
print("{} is not a file.".format(source))
return return_value
# Copy the source and header files from the lists into a directory
# structure that Arduino understands
# https://arduino.github.io/arduino-cli/0.19/library-specification/#layout-of-folders-and-files
def copy_files(source_list, include_list, ubxlib_dir, forced, include_files):
'''Copy files into a form that Arduino can understand'''
return_value = -1
file_count = 0
src_files_copied_count = 0
path_count = 0
header_files_copied_count = 0
# If there is no "src" sub-directory then create it
if not os.path.isdir("src"):
os.mkdir("src")
# First the source files
for file in source_list:
file = file.replace("/", os.sep)
ubxlib_file = os.path.join(ubxlib_dir, file)
# Copy without the whole path, just dumping
# the source file into the src directory; we
# won't have duplicate names (the Segger
# Embedded Studio toolchain already brings
# that requirement since it dumps all object
# files into one directory) and its clearer
# this way
destination_file = os.path.join("src", os.path.basename(file))
copied = copy_file(ubxlib_file, destination_file, forced)
if copied < 0:
break
file_count += 1
src_files_copied_count += copied
print("{} source file(s) copied.".format(src_files_copied_count))
if file_count == len(source_list):
# Must have succeeded, now do the include files
for file_path in include_list:
file_path = file_path.replace("/", os.sep)
ubxlib_file_path = os.path.join(ubxlib_dir, file_path)
ubxlib_files = []
destination_files = []
if os.path.isfile(ubxlib_file_path) and ubxlib_file_path not in ubxlib_files:
# An explicitly included file: just add it
ubxlib_files.append(ubxlib_file_path)
destination_files.append(os.path.join("src", ubxlib_file_path))
include_files.append(os.path.basename(ubxlib_file_path))
else:
for file_name in sorted(os.listdir(ubxlib_file_path)):
# A directory, go through the files
item = os.path.join(ubxlib_file_path, file_name)
if os.path.isfile(item) and item.endswith(".h") and item not in ubxlib_files:
ubxlib_files.append(item)
destination_files.append(os.path.join("src", file_name))
add_to_includes = False
if include_files is not None:
for public_indicator in PUBLIC_INCLUDE_INDICATOR:
if public_indicator in item:
add_to_includes = True
break
if add_to_includes:
include_files.append(file_name)
for idx, ubxlib_file in enumerate(ubxlib_files):
copied = copy_file(ubxlib_file, destination_files[idx], forced)
if copied < 0:
break
header_files_copied_count += copied
path_count += 1
if path_count == len(include_list):
# Must have succeeded
return_value = 0
print("{} header file(s) copied.".format(header_files_copied_count))
if return_value >= 0:
return_value = src_files_copied_count + header_files_copied_count
return return_value
# Create a header file which brings in all our disparate headers;
# this is the best way to get things into Arduino
def create_header_file(filename, comment_text, include_files):
'''Create Arduino library header file'''
return_value = -1
filename_no_ext = filename.split(".")[0].upper()
with open(os.path.join("src", filename), "w") as file:
file.write(comment_text)
file.write("#ifndef _U_{}_H_\n".format(filename_no_ext))
file.write("#define _U_{}_H_\n\n".format(filename_no_ext))
if include_files:
for include_file in include_files:
file.write("#include <{}>\n".format(include_file))
file.write("\n#endif // _U_{}_H_\n\n".format(filename_no_ext))
file.write("// End of file\n".format(filename_no_ext))
return_value = 0
return return_value
# Create the Arduino library metadata
# https://arduino.github.io/arduino-cli/0.19/library-specification/#library-metadata
def create_metadata(library_name, version_string, sentence, paragraph, precompiled,
platform_type, include_files):
'''Create Arduino library metadata file'''
return_value = -1
architecture_list = ""
for architecture in ARCHITECTURES:
for idx, item in enumerate(architecture):
if idx == 0:
if item.lower() != platform_type.lower():
break
else:
if len(architecture_list) > 0:
architecture_list += ", "
architecture_list += item
if architecture_list:
with open(PROPERTIES_FILE, "w") as file:
file.write("name={}\n".format(library_name))
if not version_string:
# version is a mandatory field, have to put in something
version_string = "0.0.0"
file.write("version={}\n".format(version_string))
file.write("author={}\n".format(UBXLIB_EMAIL))
file.write("maintainer={}\n".format(UBXLIB_EMAIL))
file.write("sentence={}\n".format(sentence))
file.write("paragraph={}\n".format(paragraph))
file.write("category=Communication\n")
file.write("url=https://github.com/u-blox/ubxlib\n")
file.write("architectures={}\n".format(architecture_list))
if precompiled:
file.write("dot_a_linkage=true\n")
# precompiled is set to full so that, if a version of the library
# is compiled, it may be copied from your sketch (kept in the
# subdirectory libraries/ubxlib/ubxlib.a) to the global library
# folder with the right architecture name, which in this case
# would be libraries/ubxlib/esp32/ubxlib.a
file.write("precompiled=full\n")
text = ""
for include_file in include_files:
if len(text) > 0:
text += ", "
text += include_file
file.write("includes={}\n".format(text))
return_value = 0
return return_value