Merge pull request #530 from tuna-f1sh/master

ardmk-init - Makefile initialisation and template project utility
This commit is contained in:
Simon John 2018-01-12 19:27:14 +00:00 committed by GitHub
commit 74e1ef00fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 359 additions and 3 deletions

View file

@ -1443,7 +1443,7 @@ endif
AVRDUDE_ISP_OPTS = -c $(ISP_PROG) -b $(AVRDUDE_ISP_BAUDRATE)
ifndef $(ISP_PORT)
ifneq ($(strip $(ISP_PROG)),$(filter $(ISP_PROG), usbasp usbtiny gpio linuxgpio avrispmkii dragon_isp dragon_dw))
ifneq ($(strip $(ISP_PROG)),$(filter $(ISP_PROG), atmelice_isp usbasp usbtiny gpio linuxgpio avrispmkii dragon_isp dragon_dw))
AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
endif
else
@ -1605,7 +1605,7 @@ ifneq ($(words $(wildcard $(TAGS_FILE))), 0)
rm -f $(TAGS_FILE)
endif
@$(ECHO) "Generating tags for local sources (INO an PDE files as C++): "
$(CTAGS_CMD) $(TAGS_FILE) --langmap=c++:.ino --langmap=c++:.pde $(LOCAL_SRCS)
$(CTAGS_CMD) $(TAGS_FILE) --langmap=c++:+.ino.pde $(LOCAL_SRCS)
ifneq ($(words $(ARDUINO_LIBS)), 0)
@$(ECHO) "Generating tags for project libraries: "
$(CTAGS_CMD) $(TAGS_FILE) $(foreach lib, $(ARDUINO_LIBS),$(USER_LIB_PATH)/$(lib)/*)

View file

@ -14,8 +14,10 @@ I tried to give credit whenever possible. If I have missed anyone, kindly add it
- Tweak: Move non-standard-related items from CxxFLAGS_STD to CxxFLAGS (issue #523) (https://github.com/sej7278)
- Tweak: Update Windows usage documentation and allow non-relative paths (issue #519) (https://github.com/tuna-f1sh)
- Tweak: Support Cygwin Unix Python and Windows installation on Windows to pass correct port binding. (https://github.com/tuna-f1sh)
- New: Added -fdiagnostics-color to *STD flags (https://github.com/sej7278)
- New: Added -fdiagnostics-color to \*STD flags (https://github.com/sej7278)
- New: Add generation of tags file using ctags, which automatically includes project libs and Arduino core. (https://github.com/tuna-f1sh)
- New: Add template Makefile and project boilerplate initialise script, `ardmk-init`. (https://github.com/tuna-f1sh)
- New: Support atmelice_isp JTAG tool as ISP programmer. (https://github.com/tuna-f1sh)
### 1.6.0 (2017-07-11)
- Fix: Allowed for SparkFun's weird usb pid/vid submenu shenanigans (issue #499). (https://github.com/sej7278)

View file

@ -428,6 +428,20 @@ all of the examples. The bootstrap script is primarily intended for use by a
continuous integration server, specifically Travis CI. It is not intended for
normal users.
## Makefile Generator and Project Initialisation
`ardmk-init` within the bin/ folder is a utility Python script to create a
Arduino-mk Makefile for a project and also has option to create a traditional *tree*
organization (src, lib, bin). It can be used as with commanline arguments or
prompted - see examples below (append `$ARDMK_DIR/bin/` to command if not on path):
* Run prompted within current working directory: `ardmk-init`
* Create Arduino Uno Makefile (useful within a library example): `ardmk-init -qb uno`
* Create boilerplate Arduino Uno project in current working directory of same
name: `ardmk-init -b uno --quiet --project`
* Create Arduino-mk nano Makefile in current working directory with template .ino: `ardmk-init -b nano -u atmega328 -qtn my-project`
* See `ardmk-init --help` for more.
### Bare-ArduinoProject
If you are planning on using this makefile in a larger/professional project, you might want to take a look at the [Bare-ArduinoProject](https://github.com/WeAreLeka/Bare-Arduino-Project) framework.

60
ardmk-init.1 Normal file
View file

@ -0,0 +1,60 @@
.TH ARDMK-INIT "1" "Nov 2017" "ardmk-init" "Arduino Makefile Generator"
.SH NAME
ardmk-init - Generate Arduino Makefile environments
.SH SYNOPSIS
.B ardmk-init
[OPTION]...
.SH OPTIONS
.B \-v, \-\-verbose
Print file contents during creation.
.B \-d, \-\-directory
Directory to run generator.
.B \-b, \-\-board
Board tag.
.B \-u, \-\-micro
Microcontroller on board.
.B \-f, \-\-freq
Clock frequency.
.B \-p, \-\-port
Monitor port.
.B \-n, \-\-name
Project name.
.B \-\-cli
Run with user prompts rather than arguments.
.B \-p, \-\-project
Create boilerplate project with src, lib and bin folder structure.
.B \-t, \-\-template
Create bare minimum Arduino source file.
.SH DESCRIPTION
Creates a Makefile and project tree structure from templates.
.SH EXAMPLE
ardmk-init -b uno # create Arduino uno Makefile
.PP
ardmk-init --cli # run with user prompts
.PP
ardmk-init --board uno --project --template --name my-project # create Arduino uno project and template with name "my-project"
.SH BUGS
Problems may reported on the github project page at:
.PP
https://github.com/sudar/Arduino-Makefile
.SH AUTHOR
John Whittington, git@jbrengineering.co.uk
.SH LICENSE
This is under MIT license.

274
bin/ardmk-init Executable file
View file

@ -0,0 +1,274 @@
#!/usr/bin/env python
"""
Arduino-mk Makefile and project initialiser
This script can be used in its basic form create a project specific Makefile
for use with Arduino-mk. Addionally, it can be used to create a template
Arduino source file and a traditional boilerplate project file structure.
Example:
* Run prompted within current working directory (requires Clint): `ardmk-init --cli`
* Create Arduino Uno Makefile (useful within a library example): `ardmk-init -b uno`
* Create boilerplate Arduino Uno project in current working directory of same
name: `ardmk-init -b uno --project`
* Create Arduino-mk nano Makefile in current working directory with template .ino:
`ardmk-init -b nano -u atmega328 -tn my-project`
See `armk-init --help` for CLI arguments
"""
from __future__ import print_function
import os
import argparse
## Global Vars
VERSION = "1.1"
ARD_TEMPLATE = "\n\
#include <Arduino.h>\n\
#include <Wire.h>\n\
\n\
\n\
void setup() {\n\
}\n\
\n\
void loop() {\n\
}\n\
"
## Command Parser
PARSER = argparse.ArgumentParser(prog='ardmk-init',
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\nVersion: ' + VERSION)
PARSER.add_argument('-v', '--verbose', action='store_true',
help="print file contents during creation")
PARSER.add_argument('-d', '--directory', default=os.getcwd(), help='directory to run generator, default cwd')
PARSER.add_argument('-b', '--board', default='uno', help='board tag')
PARSER.add_argument('-u', '--micro', default='AUTO', help='microcontroller on board')
PARSER.add_argument('-f', '--freq', default='AUTO', help='clock frequency')
PARSER.add_argument('-p', '--port', default='AUTO', help='monitor port')
PARSER.add_argument('-n', '--name', default=os.path.basename(os.getcwd()), help='project name')
PARSER.add_argument('--cli', action='store_true', help='run with user prompts (requires "Clint" module), rather than args')
PARSER.add_argument('-P', '--project', action='store_true',
help='create boilerplate project with src, lib and bin folder structure')
PARSER.add_argument('-t', '--template', action='store_true',
help='create bare minimum Arduino source file')
PARSER.add_argument('-V', '--version', action='version', version='%(prog)s '+ VERSION)
ARGS = PARSER.parse_args()
try:
from clint.textui import prompt, validators
except ImportError:
if ARGS.cli:
print("Python module 'clint' is required for running prompted. Install the module or run with arguments only")
quit()
def generate_makefile():
"""
Generate the Makefile content using prompts or parsed arguments
"""
# Header
file_content = "# Generated by ard-make version " + VERSION + "\n\n"
# Basic
if ARGS.cli:
print("Generating Arduino Ard-Makefile project in "
+ os.path.abspath(ARGS.directory))
btag = prompt.query('Board tag?', default='uno')
if btag != 'uno':
bsub = prompt.query('Board sub micro?', default='atmega328')
f_cpu = prompt.query('Board frequency', default='16000000L')
else:
bsub = 'AUTO'
f_cpu = 'AUTO'
monitor_port = prompt.query('Arduino port?', default='AUTO')
else:
btag = ARGS.board
bsub = ARGS.micro
f_cpu = ARGS.freq
monitor_port = ARGS.port
file_content += check_define('BOARD_TAG', btag)
file_content += check_define('BOARD_SUB', bsub)
file_content += check_define('F_CPU', f_cpu)
file_content += check_define('MONITOR_PORT', monitor_port)
# Extended
if ARGS.cli:
if not prompt.yn('Extended options?', default='n'):
if not prompt.yn('Define local folders?', default='n'):
src_dir = prompt.query('Sources folder (Makefile will be created here)?',
default='', validators=[])
userlibs = prompt.query('Library folder (will create if does not exist) - AUTO is Sketchbook directory?',
default='AUTO', validators=[])
obj_dir = prompt.query('Output directory?', default='AUTO', validators=[])
else:
src_dir = ''
userlibs = 'AUTO'
obj_dir = 'AUTO'
boards_txt = prompt.query('Boards file?', default='AUTO')
isp_prog = prompt.query('ISP programmer?', default='atmelice_isp')
isp_port = prompt.query('ISP port?', default='AUTO')
if not prompt.yn('Quiet make?', default='n'):
file_content += "ARDUINO_QUIET = 1\n"
file_content += check_define('ISP_PROG', isp_prog)
file_content += check_define('ISP_PORT', isp_port)
file_content += check_define('BOARDS_TXT', boards_txt)
# Check andd create folders
check_create_folder(src_dir)
check_create_folder(userlibs)
check_create_folder(obj_dir)
# Makefile will be in src_dir so lib and bin must be relative
if src_dir:
userlibs = "../" + userlibs
obj_dir = "../" + obj_dir
file_content += check_define('USER_LIB_PATH', userlibs)
file_content += check_define('OBJDIR', obj_dir)
else:
src_dir = ''
if ARGS.template or not prompt.yn('Create template Arduino source?', default='n'):
source_filename = prompt.query('Name of project?',
default=os.path.basename(os.getcwd()))
if src_dir:
write_template(src_dir + "/" + source_filename)
else:
write_template(source_filename)
file_content += check_define('TARGET', source_filename)
else:
if ARGS.project:
src_dir = 'src'
userlibs = 'lib'
obj_dir = 'bin'
else:
src_dir = ''
userlibs = 'AUTO'
obj_dir = 'AUTO'
# Check andd create folders
check_create_folder(src_dir)
check_create_folder(userlibs)
check_create_folder(obj_dir)
# Makefile will be in src_dir so lib and bin must be relative
if src_dir:
userlibs = "../" + userlibs
obj_dir = "../" + obj_dir
file_content += check_define('USER_LIB_PATH', userlibs)
file_content += check_define('OBJDIR', obj_dir)
if ARGS.project or ARGS.template:
if src_dir:
write_template(src_dir + "/" + ARGS.name)
else:
write_template(ARGS.name)
file_content += check_define('TARGET', ARGS.name)
if not "ARDMK_DIR" in os.environ:
if not ARGS.cli:
print("Warning: ARDMK_DIR environment variable not defined. \
Must be defined for Makefile to work")
else:
ardmk = prompt.query('Arduino Makefile path?',
default='/usr/share/arduino',
validators=[validators.PathValidator()])
ardmk = "ARDMK_DIR := " + ardmk + "\n"
file_content += "\ninclude $(ARDMK_DIR)/Arduino.mk"
# Add forward slash if source directory exists
if src_dir:
write_to_makefile(file_content, (src_dir + "/"))
else:
write_to_makefile(file_content, "")
return file_content
def write_to_makefile(file_content, path):
"""
Write the Makefile file
"""
makefile = open(path + "Makefile", 'w')
print("Writing Makefile...")
if ARGS.verbose:
print(file_content)
makefile.write(file_content)
makefile.close()
def write_template(filename):
"""
Write template Arduino .ino source
"""
print("Writing " + os.path.abspath(filename) + ".ino...")
if os.path.isfile(filename + '.ino'):
if not ARGS.cli:
print(filename + '.ino' + ' already exists! Stopping.')
return
print(filename + '.ino' + ' already exists! Overwrite?')
if prompt.yn('Continue?', default='n'):
return
src = open((filename + ".ino"), 'w')
if ARGS.verbose:
print(ARD_TEMPLATE)
src.write("/* Project: " + filename + " */\n" + ARD_TEMPLATE)
src.close()
def check_create_folder(folder):
"""
Check if folder exists and make it if it doesn't and hasn't been set to AUTO
"""
if folder and not folder == 'AUTO':
if not os.path.exists(folder):
print("Creating " + os.path.abspath(folder) + " folder")
os.makedirs(folder)
def check_define(define, user):
"""
Check whether user has set define and return Makefile formatted string if they have
"""
# Return is empty unless user has passed value
string = ""
# Set define only if not empty or set to AUTO
if user and not user == 'AUTO':
string = define + " = " + user + "\n"
return string
def check_args():
"""
Check input args will work with Makefile
"""
# Micro should be defined for non uno boards
if ARGS.board != 'uno' and ARGS.micro == 'AUTO':
print('\n!!! Warning: --micro should be defined and not left AUTO for non-Uno boards\n')
if __name__ == '__main__':
# Create directory if not exist
check_create_folder(ARGS.directory)
# Check input args
check_args()
# Change to dir so all commands are run relative
os.chdir(ARGS.directory)
if os.path.isfile('Makefile'):
if not ARGS.cli:
print('Makefile in ' + os.path.abspath(ARGS.directory)
+ ' already exists! Please remove before generating. Stopping.')
quit()
# Confirm with user if not quiet mode
print('Makefile in ' + os.path.abspath(ARGS.directory)
+ ' already exists! Overwrite?')
if prompt.yn('Continue?', default='n'):
quit()
# Run it
generate_makefile()

View file

@ -39,6 +39,8 @@ install -m 755 bin/ard-reset-arduino %{buildroot}/%{_bindir}/ard-reset-arduino
install -m 644 ard-reset-arduino.1 %{buildroot}/%{_mandir}/man1
install -m 755 bin/robotis-loader %{buildroot}/%{_bindir}/robotis-loader
install -m 644 robotis-loader.1 %{buildroot}/%{_mandir}/man1
install -m 755 bin/ardmk-init %{buildroot}/%{_bindir}/ardmk-init
install -m 644 ardmk-init.1 %{buildroot}/%{_mandir}/man1
%clean
rm -rf %{buildroot}
@ -49,6 +51,8 @@ rm -rf %{buildroot}
%{_mandir}/man1/ard-reset-arduino.1*
%{_bindir}/robotis-loader
%{_mandir}/man1/robotis-loader.1*
%{_bindir}/ardmk-init
%{_mandir}/man1/ardmk-init.1*
%{_datadir}/arduino/*.mk
%{_datadir}/arduino/arduino-mk-vars.md
%doc %{_docdir}/%{name}/licence.txt
@ -56,6 +60,8 @@ rm -rf %{buildroot}
%{_docdir}/%{name}/examples
%changelog
* Thu Oct 05 2017 Simon John <git@the-jedi.co.uk>
- Added ardmk-init binary and manpage
* Tue Jul 11 2017 Karl Semich <fuzzyTew@gmail.com>
- Added robotis-loader binary and manpage
* Sat Apr 12 2014 Simon John <git@the-jedi.co.uk>