1
1
#!/usr/bin/env python
2
+ """
3
+ Arduino-mk Makefile and project initialiser
4
+
5
+ This script can be used in it's basic form create a project specific Makefile
6
+ for use with Arduino-mk. Addionally, it can be used to create a template
7
+ Arduino source file and a traditional boilerplate project file structure.
8
+
9
+ Example:
10
+ * Run prompted within current working directory: `ardmk-init`
11
+ * Create Arduino Uno Makefile (useful within a library example): `ardmk-init -qb uno`
12
+ * Create boilerplate Arduino Uno project in current working directory of same
13
+ name: `ardmk-init -b uno --quiet --project`
14
+ * Create Arduino-mk nano Makefile in current working directory with template .ino:
15
+ `ardmk-init -b nano -u atmega328 -qtn my-project`
16
+
17
+ See `armk-init --help` for CLI arguments
18
+ """
2
19
3
20
from __future__ import print_function
4
- import serial
5
21
import os
6
22
import argparse
7
23
from clint .textui import prompt , validators , colored , puts
8
24
9
25
## Global Vars
10
26
VERSION = "1.0"
11
- directory = os .getcwd ()
12
- ard_template = "\n \
27
+ ARD_TEMPLATE = "\n \
13
28
#include <Arduino.h>\n \
14
29
#include <Wire.h>\n \
15
30
\n \
@@ -22,53 +37,63 @@ void loop() {\n\
22
37
"
23
38
24
39
## Command Parser
25
- parser = argparse .ArgumentParser (description = 'Arduino Makefile and boilerplate project generator. For use with Ard-Makefile: https://github.com/sudar/Arduino-Makefile. Script created by John Whittington https://github.com/tuna-f1sh 2017\n \n Version: ' + VERSION , usage = '"ardmk-init -b uno -quiet -project" Automonously create boiler plate Arduino Uno project in current working directory with same name. See --help for more.' )
26
- parser .add_argument ('-v' , '--verbose' , action = 'store_true' , help = "print file contents during creation" )
27
- parser .add_argument ('-d' , '--directory' , default = directory , help = 'directory to run generator' )
28
- parser .add_argument ('-b' , '--board' , default = 'uno' , help = 'board tag' )
29
- parser .add_argument ('-u' , '--micro' , default = 'AUTO' , help = 'microcontroller on board' )
30
- parser .add_argument ('-f' , '--freq' , default = 'AUTO' , help = 'mlock frequency' )
31
- parser .add_argument ('-p' , '--port' , default = 'AUTO' , help = 'monitor port' )
32
- parser .add_argument ('-n' , '--name' , default = os .path .basename (directory ), help = 'project name' )
33
- parser .add_argument ('-q' , '--quiet' , action = 'store_true' , help = 'run quiet without user prompts' )
34
- parser .add_argument ('-P' , '--project' , action = 'store_true' , help = 'create boilerplate project with src, lib and bin folder structure' )
35
- parser .add_argument ('-t' , '--template' , action = 'store_true' , help = 'create bare minimum Arduino source file' )
36
- args = parser .parse_args ()
37
-
38
- directory = args .directory
39
-
40
- def generateMakefile ():
40
+ PARSER = argparse .ArgumentParser (description = 'Arduino Makefile and boilerplate project generator.\
41
+ For use with Ard-Makefile: https://github.com/sudar/Arduino-Makefile.\
42
+ Script created by John Whittington https://github.com/tuna-f1sh 2017\
43
+ \n \n Version: ' + VERSION , usage = 'ardmk-init # prompted CLI, see --help for more.' )
44
+ PARSER .add_argument ('-v' , '--verbose' , action = 'store_true' ,
45
+ help = "print file contents during creation" )
46
+ PARSER .add_argument ('-d' , '--directory' , default = os .getcwd (), help = 'directory to run generator' )
47
+ PARSER .add_argument ('-b' , '--board' , default = 'uno' , help = 'board tag' )
48
+ PARSER .add_argument ('-u' , '--micro' , default = 'AUTO' , help = 'microcontroller on board' )
49
+ PARSER .add_argument ('-f' , '--freq' , default = 'AUTO' , help = 'mlock frequency' )
50
+ PARSER .add_argument ('-p' , '--port' , default = 'AUTO' , help = 'monitor port' )
51
+ PARSER .add_argument ('-n' , '--name' , default = os .path .basename (os .getcwd ()), help = 'project name' )
52
+ PARSER .add_argument ('-q' , '--quiet' , action = 'store_true' , help = 'run quiet without user prompts' )
53
+ PARSER .add_argument ('-P' , '--project' , action = 'store_true' ,
54
+ help = 'create boilerplate project with src, lib and bin folder structure' )
55
+ PARSER .add_argument ('-t' , '--template' , action = 'store_true' ,
56
+ help = 'create bare minimum Arduino source file' )
57
+ ARGS = PARSER .parse_args ()
58
+
59
+ def generate_makefile ():
60
+ """
61
+ Generate the Makefile content using prompts or parsed arguments
62
+ """
41
63
# Header
42
- fileContents = "# Generated by ard-make version " + VERSION + "\n \n "
64
+ file_content = "# Generated by ard-make version " + VERSION + "\n \n "
43
65
44
66
# Basic
45
- if not args .quiet :
46
- puts (colored .cyan ("Generating Arduino Ard-Makefile project in " + os .path .abspath (directory )))
67
+ if not ARGS .quiet :
68
+ puts (colored .cyan ("Generating Arduino Ard-Makefile project in "
69
+ + os .path .abspath (ARGS .directory )))
47
70
btag = prompt .query ('Board tag?' , default = 'uno' )
48
- if not btag = = 'uno' :
71
+ if btag ! = 'uno' :
49
72
bsub = prompt .query ('Board sub micro?' , default = 'atmega328' )
50
73
f_cpu = prompt .query ('Board frequency' , default = '16000000L' )
51
74
else :
52
75
bsub = 'AUTO'
53
76
f_cpu = 'AUTO'
54
77
monitor_port = prompt .query ('Arduino port?' , default = 'AUTO' )
55
78
else :
56
- btag = args .board
57
- bsub = args .micro
58
- f_cpu = args .freq
59
- monitor_port = args .port
79
+ btag = ARGS .board
80
+ bsub = ARGS .micro
81
+ f_cpu = ARGS .freq
82
+ monitor_port = ARGS .port
60
83
61
- fileContents += checkDefine ('BOARD_TAG' , btag )
62
- fileContents += checkDefine ('BOARD_SUB' , bsub )
63
- fileContents += checkDefine ('F_CPU' , f_cpu )
64
- fileContents += checkDefine ('MONITOR_PORT' , monitor_port )
84
+ file_content += check_define ('BOARD_TAG' , btag )
85
+ file_content += check_define ('BOARD_SUB' , bsub )
86
+ file_content += check_define ('F_CPU' , f_cpu )
87
+ file_content += check_define ('MONITOR_PORT' , monitor_port )
65
88
66
89
# Extended
67
- if not args .quiet :
90
+ if not ARGS .quiet :
68
91
if not prompt .yn ('Extended options?' , default = 'n' ):
69
92
if not prompt .yn ('Define local folders?' , default = 'n' ):
70
- src_dir = prompt .query ('Sources folder (Makefile will be created here)?' , default = '' , validators = [])
71
- userlibs = prompt .query ('Library folder (will create if does not exist) - AUTO is Sketchbook directory?' , default = 'AUTO' , validators = [])
93
+ src_dir = prompt .query ('Sources folder (Makefile will be created here)?' ,\
94
+ default = '' , validators = [])
95
+ userlibs = prompt .query ('Library folder (will create if does not exist) - AUTO is Sketchbook directory?' ,
96
+ default = 'AUTO' , validators = [])
72
97
obj_dir = prompt .query ('Output directory?' , default = 'AUTO' , validators = [])
73
98
else :
74
99
src_dir = ''
@@ -78,37 +103,38 @@ def generateMakefile():
78
103
isp_prog = prompt .query ('ISP programmer?' , default = 'atmelice_isp' )
79
104
isp_port = prompt .query ('ISP port?' , default = 'AUTO' )
80
105
if not prompt .yn ('Quiet make?' , default = 'n' ):
81
- fileContents += "ARDUINO_QUIET = 1\n "
106
+ file_content += "ARDUINO_QUIET = 1\n "
82
107
83
- fileContents += checkDefine ('ISP_PROG' , isp_prog )
84
- fileContents += checkDefine ('ISP_PORT' , isp_port )
85
- fileContents += checkDefine ('BOARDS_TXT' , boards_txt )
108
+ file_content += check_define ('ISP_PROG' , isp_prog )
109
+ file_content += check_define ('ISP_PORT' , isp_port )
110
+ file_content += check_define ('BOARDS_TXT' , boards_txt )
86
111
87
112
# Check andd create folders
88
- checkCreateFolder (src_dir )
89
- checkCreateFolder (userlibs )
90
- checkCreateFolder (obj_dir )
113
+ check_create_folder (src_dir )
114
+ check_create_folder (userlibs )
115
+ check_create_folder (obj_dir )
91
116
92
117
# Makefile will be in src_dir so lib and bin must be relative
93
118
if src_dir :
94
119
userlibs = "../" + userlibs
95
120
obj_dir = "../" + obj_dir
96
121
97
- fileContents += checkDefine ('USER_LIB_PATH' , userlibs )
98
- fileContents += checkDefine ('OBJDIR' , obj_dir )
122
+ file_content += check_define ('USER_LIB_PATH' , userlibs )
123
+ file_content += check_define ('OBJDIR' , obj_dir )
99
124
else :
100
125
src_dir = ''
101
126
102
- if args .template or not prompt .yn ('Create template Arduino source?' , default = 'n' ):
103
- sourceFilename = prompt .query ('Name of project?' , default = os .path .basename (os .getcwd ()))
127
+ if ARGS .template or not prompt .yn ('Create template Arduino source?' , default = 'n' ):
128
+ source_filename = prompt .query ('Name of project?' ,
129
+ default = os .path .basename (os .getcwd ()))
104
130
if src_dir :
105
- writeTemplate (src_dir + "/" + sourceFilename )
131
+ write_template (src_dir + "/" + source_filename )
106
132
else :
107
- writeTemplate ( sourceFilename )
108
- fileContents += checkDefine ('TARGET' , sourceFilename )
133
+ write_template ( source_filename )
134
+ file_content += check_define ('TARGET' , source_filename )
109
135
110
136
else :
111
- if args .project :
137
+ if ARGS .project :
112
138
src_dir = 'src'
113
139
userlibs = 'lib'
114
140
obj_dir = 'bin'
@@ -118,89 +144,111 @@ def generateMakefile():
118
144
obj_dir = 'AUTO'
119
145
120
146
# Check andd create folders
121
- checkCreateFolder (src_dir )
122
- checkCreateFolder (userlibs )
123
- checkCreateFolder (obj_dir )
147
+ check_create_folder (src_dir )
148
+ check_create_folder (userlibs )
149
+ check_create_folder (obj_dir )
124
150
125
151
# Makefile will be in src_dir so lib and bin must be relative
126
152
if src_dir :
127
153
userlibs = "../" + userlibs
128
154
obj_dir = "../" + obj_dir
129
155
130
- fileContents += checkDefine ('USER_LIB_PATH' , userlibs )
131
- fileContents += checkDefine ('OBJDIR' , obj_dir )
156
+ file_content += check_define ('USER_LIB_PATH' , userlibs )
157
+ file_content += check_define ('OBJDIR' , obj_dir )
132
158
133
- if args .project or args .template :
159
+ if ARGS .project or ARGS .template :
134
160
if src_dir :
135
- writeTemplate (src_dir + "/" + args .name )
161
+ write_template (src_dir + "/" + ARGS .name )
136
162
else :
137
- writeTemplate ( args .name )
138
- fileContents += checkDefine ('TARGET' , args .name )
163
+ write_template ( ARGS .name )
164
+ file_content += check_define ('TARGET' , ARGS .name )
139
165
140
166
if not "ARDMK_DIR" in os .environ :
141
- if args .quiet :
142
- puts (colored .magenta ('Warning: ARDMK_DIR environment variable not defined. Must be defined for Makefile to work' ))
167
+ if ARGS .quiet :
168
+ puts (colored .magenta ('Warning: ARDMK_DIR environment variable not defined. \
169
+ Must be defined for Makefile to work' ))
143
170
else :
144
- ardmk = prompt .query ('Arduino Makefile path?' , default = '/usr/share/arduino' , validators = [validators .PathValidator ()])
171
+ ardmk = prompt .query ('Arduino Makefile path?' ,
172
+ default = '/usr/share/arduino' ,
173
+ validators = [validators .PathValidator ()])
145
174
ardmk = "ARDMK_DIR := " + ardmk + "\n "
146
175
147
- fileContents += "\n include $(ARDMK_DIR)/Arduino.mk"
176
+ file_content += "\n include $(ARDMK_DIR)/Arduino.mk"
148
177
149
178
# Add forward slash if source directory exists
150
179
if src_dir :
151
- writeToMakefile ( fileContents , (src_dir + "/" ))
180
+ write_to_makefile ( file_content , (src_dir + "/" ))
152
181
else :
153
- writeToMakefile ( fileContents , "" )
182
+ write_to_makefile ( file_content , "" )
154
183
155
- return fileContents
184
+ return file_content
156
185
157
- def writeToMakefile (fileContents , path ):
186
+ def write_to_makefile (file_content , path ):
187
+ """
188
+ Write the Makefile file
189
+ """
158
190
makefile = open (path + "Makefile" , 'w' )
159
191
puts (colored .cyan ("Writing Makefile..." ))
160
- if args .verbose :
161
- puts (colored .yellow (fileContents ))
162
- makefile .write (fileContents )
192
+ if ARGS .verbose :
193
+ puts (colored .yellow (file_content ))
194
+ makefile .write (file_content )
163
195
makefile .close ()
164
196
165
- def writeTemplate (filename ):
197
+ def write_template (filename ):
198
+ """
199
+ Write template Arduino .ino source
200
+ """
166
201
puts (colored .cyan ("Writing " + os .path .abspath (filename ) + ".ino..." ))
167
202
if os .path .isfile (filename + '.ino' ):
168
- if args .quiet :
203
+ if ARGS .quiet :
169
204
puts (colored .red (filename + '.ino' + ' already exists! Stopping.' ))
170
205
return
171
206
puts (colored .red (filename + '.ino' + ' already exists! Overwrite?' ))
172
207
if prompt .yn ('Continue?' , default = 'n' ):
173
208
return
174
- src = open ((filename + ".ino" ),'w' )
175
- if args .verbose :
176
- puts (colored .yellow (ard_template ))
177
- src .write ("/* Project: " + filename + " */\n " + ard_template )
209
+ src = open ((filename + ".ino" ), 'w' )
210
+ if ARGS .verbose :
211
+ puts (colored .yellow (ARD_TEMPLATE ))
212
+ src .write ("/* Project: " + filename + " */\n " + ARD_TEMPLATE )
178
213
src .close ()
179
214
180
- def checkCreateFolder (folder ):
215
+ def check_create_folder (folder ):
216
+ """
217
+ Check if folder exists and make it if it doesn't and hasn't been set to AUTO
218
+ """
181
219
if folder and not folder == 'AUTO' :
182
220
if not os .path .exists (folder ):
183
221
puts (colored .cyan (("Creating " + os .path .abspath (folder ) + " folder" )))
184
222
os .makedirs (folder )
185
223
186
- def checkDefine (define , user ):
224
+ def check_define (define , user ):
225
+ """
226
+ Check whether user has set define and return Makefile formatted string if they have
227
+ """
228
+ # Return is empty unless user has passed value
229
+ string = ""
230
+
231
+ # Set define only if not empty or set to AUTO
187
232
if user and not user == 'AUTO' :
188
- return define + " = " + user + "\n "
189
- else :
190
- return ""
233
+ string = define + " = " + user + "\n "
191
234
192
- def main ():
235
+ return string
236
+
237
+ if __name__ == '__main__' :
193
238
# Create directory if not exist
194
- checkCreateFolder ( directory )
239
+ check_create_folder ( ARGS . directory )
195
240
# Change to dir so all commands are run relative
196
- os .chdir (directory )
241
+ os .chdir (ARGS . directory )
197
242
if os .path .isfile ('Makefile' ):
198
- if args .quiet :
199
- puts (colored .red ('Makefile in ' + os .path .abspath (directory ) + ' already exists! Stopping.' ))
200
- return
201
- puts (colored .red ('Makefile in ' + os .path .abspath (directory ) + ' already exists! Overwrite?' ))
243
+ if ARGS .quiet :
244
+ puts (colored .red ('Makefile in ' + os .path .abspath (ARGS .directory )
245
+ + ' already exists! Stopping.' ))
246
+ quit ()
247
+
248
+ # Confirm with user if not quiet mode
249
+ puts (colored .red ('Makefile in ' + os .path .abspath (ARGS .directory )
250
+ + ' already exists! Overwrite?' ))
202
251
if prompt .yn ('Continue?' , default = 'n' ):
203
- return
204
- generateMakefile ();
205
-
206
- main ()
252
+ quit ()
253
+ # Run it
254
+ generate_makefile ()
0 commit comments