diff --git a/Arduino.mk b/Arduino.mk index f2e48a5..3473166 100644 --- a/Arduino.mk +++ b/Arduino.mk @@ -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)/*) diff --git a/HISTORY.md b/HISTORY.md index b4ad884..a6aa14f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -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) diff --git a/README.md b/README.md index 972b03d..953d067 100644 --- a/README.md +++ b/README.md @@ -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-Arduino–Project If you are planning on using this makefile in a larger/professional project, you might want to take a look at the [Bare-Arduino–Project](https://github.com/WeAreLeka/Bare-Arduino-Project) framework. diff --git a/ardmk-init.1 b/ardmk-init.1 new file mode 100644 index 0000000..bb83fd2 --- /dev/null +++ b/ardmk-init.1 @@ -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. diff --git a/bin/ardmk-init b/bin/ardmk-init new file mode 100755 index 0000000..1a01cd3 --- /dev/null +++ b/bin/ardmk-init @@ -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 \n\ +#include \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() diff --git a/packaging/fedora/arduino-mk.spec b/packaging/fedora/arduino-mk.spec index 61bf317..b1f07f1 100644 --- a/packaging/fedora/arduino-mk.spec +++ b/packaging/fedora/arduino-mk.spec @@ -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 +- Added ardmk-init binary and manpage * Tue Jul 11 2017 Karl Semich - Added robotis-loader binary and manpage * Sat Apr 12 2014 Simon John