diff --git a/.gitignore b/.gitignore index 378eac2..80d14d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,57 @@ build + +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties diff --git a/README.rst b/README.rst index 4675f03..7a02c25 100644 --- a/README.rst +++ b/README.rst @@ -19,29 +19,35 @@ Features * Integrates with *Arduino SDK* * Supports all Arduino boards. -* Supports Arduino type libraries +* Supports Arduino type libraries. * Automatic detection of Arduino libraries. * Generates firmware images. +* Generates built-in examples. * Generates libraries. * Sketch support. * Upload support. * Hardware Platform support. * Programmer support (with bootloader upload). * Supports multiple build system types (Makefiles, Eclipse, KDevelop, CodeBlocks, XCode, etc). -* Cross-platform: Windows, Linux, Mac -* Extensible build system, thanks to CMake +* Cross-platform: Windows, Linux, Mac. +* Extensible build system, thanks to CMake. Feedback -------- -**Arduino CMake** is hosted on GitHub and is available at: +**Arduino CMake** is hosted on GitHub and is available on multiple forks (At the time of writing up to **156(!)**), +with the most advanced and maintainable being the following: + +https://github.com/JonasProgrammer/arduino-cmake/ + +However, the original repository deserves its honor, therefore a direct link to it is provided as well: https://github.com/queezythegreat/arduino-cmake Did you find a bug or would like a specific feature, please report it at: -https://github.com/queezythegreat/arduino-cmake/issues +https://github.com/JonasProgrammer/arduino-cmake/issues If you would like to hack on this project, don't hesitate to fork it on GitHub. I will be glad to integrate your changes if you send me a ``Pull Request``. @@ -68,6 +74,8 @@ Contributors I would like to thank the following people for contributing to **Arduino CMake**: +* Jonas (`JonasProgrammer`_) +* MrPointer (`MrPointer`_) * Marc Plano-Lesay (`Kernald`_) * James Goppert (`jgoppert`_) * Matt Tyler (`matt-tyler`_) @@ -89,6 +97,8 @@ I would like to thank the following people for contributing to **Arduino CMake** * Mike Purvis (`mikepurvis`_) * Steffen Hanikel (`hanikesn`_) +.. _JonasProgrammer: https://github.com/JonasProgrammer +.. _MrPointer: https://github.com/MrPointer .. _Kernald: https://github.com/Kernald .. _jgoppert: https://github.com/jgoppert .. _matt-tyler: https://github.com/matt-tyler @@ -127,17 +137,18 @@ Contents 1. `Getting Started`_ 2. `Using Arduino CMake`_ - 1. `Creating firmware images`_ - 2. `Creating libraries`_ + 1. `Creating Firmware Images`_ + 2. `Creating Libraries`_ 3. `Arduino Sketches`_ - 4. `Arduino Libraries`_ - 5. `Arduino Library Examples`_ - 6. `Compiler and Linker Flags`_ - 7. `Programmers`_ - 8. `Pure AVR Development`_ - 9. `Advanced Options`_ - 10. `Miscellaneous Functions`_ - 11. `Bundling Arduino CMake`_ + 4. `Arduino Built-in Examples`_ + 5. `Arduino Libraries`_ + 6. `Arduino Library Examples`_ + 7. `Compiler and Linker Flags`_ + 8. `Programmers`_ + 9. `Pure AVR Development`_ + 10. `Advanced Options`_ + 11. `Miscellaneous Functions`_ + 12. `Bundling Arduino CMake`_ 3. `Linux Environment`_ @@ -278,7 +289,7 @@ You can also specify it at build configuration time:: cmake -DCMAKE_TOOLCHAIN_FILE=../path/to/toolchain/file.cmake PATH_TO_SOURCE_DIR -Creating firmware images +Creating Firmware Images ~~~~~~~~~~~~~~~~~~~~~~~~ Once you have the **Arduino CMake** loaded you can start defining firmware images. @@ -401,7 +412,7 @@ This will create a target named ``${TARGET_NAME}-serial`` (in this example: blin -Creating libraries +Creating Libraries ~~~~~~~~~~~~~~~~~~ Creating libraries is very similar to defining a firmware image, except we use the ``generate_arduino_library`` command. This command creates static libraries, and are not to be confused with `Arduino Libraries`_. The full command syntax:: @@ -464,7 +475,6 @@ Once that library is defined we can use it in our other firmware images... Let's CMake has automatic dependency tracking, so when you build the ``blink`` target, ``blink_lib`` will automatically get built, in the right order. - Arduino Sketches ~~~~~~~~~~~~~~~~ @@ -481,6 +491,72 @@ Note: When specifying the sketch directory path, arduino-cmake is expecting to f You can also specify the path to the main sketch file, then the parent directory of that sketch will be search for additional sketch files. +Arduino Built-in Examples +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Arduino SDK comes with a handful of code examples, providing an easy setup for simple operations. +Since there are many examples, they were categorized, making each example be under a certain category. +Each example consists of at least one source file, named after the example and has the *.ino* or *.pde* extension, and sits under a directory which is also named after the example. +Each category is a directory named after it, having all its examples as sub-directories, named after them. +One such example is ``Blink``, probrably the most popular one as well. It's located under the ``Basics`` category and has a source file named ``Blink.ino``. + +**Arduino CMake** has the abillity to automatically generate these examples, simply by passing their name and optionally their category, as some sort of an optimization. **It supports case-insensitive names** +If you would like to generate and upload some of those examples you can use the `generate_arduino_example` command. The syntax of the command is:: + + generate_arduino_example(target_name + EXAMPLE example_name + [CATEGORY] category_name + [BOARD board_id] + [PORT port] + [SERIAL serial command] + [PORGRAMMER programmer_id] + [AFLAGS avrdude_flags]) + +The options are: + + ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **Name** | **Description** | **Required** | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **EXAMPLE** | Example name. | **REQUIRED** | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **BOARD** | Board ID *(such as uno, mega2560, ...)* | **REQUIRED** | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **CATEGORY** | Category name. | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **PORT** | Serial port, for upload and serial targets (see `Upload Firmware`_) | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **SERIAL** | Serial command for serial target (see `Serial Terminal`_) | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **PROGRAMMER** | Programmer ID, enables programmer burning (see `Programmers`_). | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ +| **AFLAGS** | avrdude flags for target | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ + +To generate a target for the **blink** example from the **Basics** category for the **Uno** board:: + + generate_arduino_example(blink_example + CATEGORY Basics + EXAMPLE Blink + BOARD uno + PORT /dev/ttyUSB0) + +You can also rewrite the previous like so:: + + set(blink_example_CATEGORY Basics) + set(blink_example_EXAMPLE Blink) + set(blink_example_BOARD uno) + set(blink_example_PORT /dev/ttyUSB0) + + generate_arduino_example(blink_example) + +The previous example will generate the following two target:: + + blink_example + blink_example-upload + +**Note:** The above example will work perfectly fine even if the ``Basics`` category hadn't been passed. + Arduino Libraries ~~~~~~~~~~~~~~~~~ @@ -524,9 +600,9 @@ Arduino Libraries are not to be confused with normal static libraries (for exmap Arduino Library Examples ~~~~~~~~~~~~~~~~~~~~~~~~ -Most Arduino libraries have examples bundled with them. If you would like to generate and upload some of those examples you can use the `generate_arduino_example` command. The syntax of the command is:: +Most Arduino libraries have examples bundled with them. If you would like to generate and upload some of those examples you can use the `generate_arduino_library_example` command. The syntax of the command is:: - generate_arduino_example(target_name + generate_arduino_library_example(target_name LIBRARY library_name EXAMPLE example_name [BOARD board_id] @@ -558,7 +634,7 @@ The options are: To generate a target for the **master_writer** example from the **Wire** library for the **Uno**:: - generate_arduino_example(wire_example + generate_arduino_library_example(wire_example LIBRARY Wire EXAMPLE master_writer BOARD uno @@ -571,7 +647,7 @@ You can also rewrite the previous like so:: set(wire_example_BOARD uno) set(wire_example_PORT /dev/ttyUSB0) - generate_arduino_example(wire_example) + generate_arduino_library_example(wire_example) The previous example will generate the following two target:: @@ -1228,4 +1304,3 @@ Here are some resources you might find useful in getting started. .. _CMake: http://www.cmake.org/cmake/resources/software.html .. _CMake Installer: http://www.cmake.org/cmake/resources/software.html .. _Arduino SDK: http://www.arduino.cc/en/Main/Software - diff --git a/cmake/ArduinoToolchain.cmake b/cmake/ArduinoToolchain.cmake index f320898..570dbec 100644 --- a/cmake/ArduinoToolchain.cmake +++ b/cmake/ArduinoToolchain.cmake @@ -32,6 +32,35 @@ elseif(WIN32) include(Platform/WindowsPaths) endif() +#=============================================================================# +# Toolchain file variable scope workaround # +#=============================================================================# +foreach(VAR + ARDUINO_SDK_PATH + ARDUINO_AVRDUDE_CONFIG_PATH + ARDUINO_AVRDUDE_FLAGS + ARDUINO_AVRDUDE_PROGRAM + ARDUINO_BOARDS_PATH + ARDUINO_BOOTLOADERS_PATH + ARDUINO_CORES_PATH + ARDUINO_LIBRARIES_PATH + ARDUINO_OBJCOPY_EEP_FLAGS + ARDUINO_OBJCOPY_HEX_FLAGS + ARDUINO_PLATFORMS + ARDUINO_PROGRAMMERS_PATH + ARDUINO_VARIANTS_PATH + ARDUINO_VERSION_PATH + AVRSIZE_PROGRAM) + if(${VAR}) + # Environment variables are always preserved. + set(ENV{_ARDUINO_CMAKE_WORKAROUND_${VAR}} "${${VAR}}") + else() + if($ENV{_ARDUINO_CMAKE_WORKAROUND_${VAR}}) + set(${VAR} "$ENV{_ARDUINO_CMAKE_WORKAROUND_${VAR}}") + message(DEBUG "RESTORED ${VAR} from env: ${${VAR}}") + endif() + endif() +endforeach() #=============================================================================# # Detect Arduino SDK # @@ -64,6 +93,10 @@ if(NOT ARDUINO_SDK_PATH) endif() list(SORT SDK_PATH_HINTS) list(REVERSE SDK_PATH_HINTS) + + if(DEFINED ENV{ARDUINO_SDK_PATH}) + list(APPEND SDK_PATH_HINTS $ENV{ARDUINO_SDK_PATH}) + endif() endif() find_path(ARDUINO_SDK_PATH diff --git a/cmake/Platform/Arduino.cmake b/cmake/Platform/Arduino.cmake index 042a3c1..16e0dfb 100644 --- a/cmake/Platform/Arduino.cmake +++ b/cmake/Platform/Arduino.cmake @@ -1,4 +1,7 @@ #=============================================================================# +# Official Readme +#=============================================================================# +#=============================================================================# # generate_arduino_firmware(name # [BOARD board_id] # [SKETCH sketch_path | @@ -235,7 +238,7 @@ # See: http://code.google.com/p/arduino/wiki/Platforms # # This enables you to register new types of hardware platforms such as the -# Sagnuino, without having to copy the files into your Arduion SDK. +# Sagnuino, without having to copy the files into your Arduino SDK. # # A Hardware Platform is a directory containing the following: # @@ -246,7 +249,7 @@ # |-- boards.txt # `-- programmers.txt # -# The board.txt describes the target boards and bootloaders. While +# The boards.txt describes the target boards and bootloaders. While # programmers.txt the programmer defintions. # # A good example of a Hardware Platform is in the Arduino SDK: @@ -282,19 +285,20 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. #=============================================================================# + cmake_minimum_required(VERSION 2.8.5) include(CMakeParseArguments) - - - - +#=============================================================================# +# User Functions +#=============================================================================# #=============================================================================# -# User Functions +# Print Functions #=============================================================================# #=============================================================================# +# print_board_list # [PUBLIC/USER] # # print_board_list() @@ -302,16 +306,17 @@ include(CMakeParseArguments) # see documentation at top #=============================================================================# function(PRINT_BOARD_LIST) - foreach(PLATFORM ${ARDUINO_PLATFORMS}) - if(${PLATFORM}_BOARDS) + foreach (PLATFORM ${ARDUINO_PLATFORMS}) + if (${PLATFORM}_BOARDS) message(STATUS "${PLATFORM} Boards:") print_list(${PLATFORM}_BOARDS) message(STATUS "") - endif() - endforeach() + endif () + endforeach () endfunction() #=============================================================================# +# print_programmer_list # [PUBLIC/USER] # # print_programmer_list() @@ -319,16 +324,17 @@ endfunction() # see documentation at top #=============================================================================# function(PRINT_PROGRAMMER_LIST) - foreach(PLATFORM ${ARDUINO_PLATFORMS}) - if(${PLATFORM}_PROGRAMMERS) + foreach (PLATFORM ${ARDUINO_PLATFORMS}) + if (${PLATFORM}_PROGRAMMERS) message(STATUS "${PLATFORM} Programmers:") print_list(${PLATFORM}_PROGRAMMERS) - endif() + endif () message(STATUS "") - endforeach() + endforeach () endfunction() #=============================================================================# +# print_programmer_settings # [PUBLIC/USER] # # print_programmer_settings(PROGRAMMER) @@ -336,196 +342,206 @@ endfunction() # see documentation at top #=============================================================================# function(PRINT_PROGRAMMER_SETTINGS PROGRAMMER) - if(${PROGRAMMER}.SETTINGS) + if (${PROGRAMMER}.SETTINGS) message(STATUS "Programmer ${PROGRAMMER} Settings:") print_settings(${PROGRAMMER}) - endif() + endif () endfunction() +#=============================================================================# +# print_board_settings # [PUBLIC/USER] # # print_board_settings(ARDUINO_BOARD) # # see documentation at top function(PRINT_BOARD_SETTINGS ARDUINO_BOARD) - if(${ARDUINO_BOARD}.SETTINGS) + if (${ARDUINO_BOARD}.SETTINGS) message(STATUS "Arduino ${ARDUINO_BOARD} Board:") print_settings(${ARDUINO_BOARD}) - endif() + endif () endfunction() + +#=============================================================================# +# Generation Functions +#=============================================================================# + #=============================================================================# +# GENERATE_ARDUINO_LIBRARY # [PUBLIC/USER] # see documentation at top #=============================================================================# function(GENERATE_ARDUINO_LIBRARY INPUT_NAME) message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT - "NO_AUTOLIBS;MANUAL" # Options - "BOARD" # One Value Keywords - "SRCS;HDRS;LIBS" # Multi Value Keywords - ${ARGN}) + "NO_AUTOLIBS;MANUAL" # Options + "BOARD" # One Value Keywords + "SRCS;HDRS;LIBS" # Multi Value Keywords + ${ARGN}) - if(NOT INPUT_BOARD) + if (NOT INPUT_BOARD) set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) - endif() - if(NOT INPUT_MANUAL) + endif () + if (NOT INPUT_MANUAL) set(INPUT_MANUAL FALSE) - endif() + endif () required_variables(VARS INPUT_SRCS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") - + set(ALL_LIBS) set(ALL_SRCS ${INPUT_SRCS} ${INPUT_HDRS}) - if(NOT INPUT_MANUAL) - setup_arduino_core(CORE_LIB ${INPUT_BOARD}) - endif() + if (NOT INPUT_MANUAL) + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + endif () find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "") set(LIB_DEP_INCLUDES) - foreach(LIB_DEP ${TARGET_LIBS}) + foreach (LIB_DEP ${TARGET_LIBS}) set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") - endforeach() + endforeach () - if(NOT ${INPUT_NO_AUTOLIBS}) - setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "" "${LIB_DEP_INCLUDES}" "") - endif() + if (NOT ${INPUT_NO_AUTOLIBS}) + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "" "${LIB_DEP_INCLUDES}" "") + endif () list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) add_library(${INPUT_NAME} ${ALL_SRCS}) - get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${INPUT_BOARD} ${INPUT_MANUAL}) + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${INPUT_BOARD} ${INPUT_MANUAL}) set_target_properties(${INPUT_NAME} PROPERTIES - COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS} ${LIB_DEP_INCLUDES}" - LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS} ${LIB_DEP_INCLUDES}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") target_link_libraries(${INPUT_NAME} ${ALL_LIBS} "-lc -lm") endfunction() #=============================================================================# +# GENERATE_AVR_LIBRARY # [PUBLIC/USER] # see documentation at top #=============================================================================# function(GENERATE_AVR_LIBRARY INPUT_NAME) message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT - "NO_AUTOLIBS;MANUAL" # Options - "BOARD" # One Value Keywords - "SRCS;HDRS;LIBS" # Multi Value Keywords - ${ARGN}) - - if(NOT INPUT_BOARD) + "NO_AUTOLIBS;MANUAL" # Options + "BOARD" # One Value Keywords + "SRCS;HDRS;LIBS" # Multi Value Keywords + ${ARGN}) + + if (NOT INPUT_BOARD) set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) - endif() - + endif () + required_variables(VARS INPUT_SRCS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") - - if(INPUT_HDRS) - set( INPUT_HDRS "SRCS ${INPUT_HDRS}" ) - endif() - if(INPUT_LIBS) - set( INPUT_LIBS "LIBS ${INPUT_LIBS}" ) - endif() - if(INPUT_HDRS) + if (INPUT_HDRS) + set(INPUT_HDRS "SRCS ${INPUT_HDRS}") + endif () + if (INPUT_LIBS) + set(INPUT_LIBS "LIBS ${INPUT_LIBS}") + endif () + + if (INPUT_HDRS) list(INSERT INPUT_HDRS 0 "HDRS") - endif() - if(INPUT_LIBS) + endif () + if (INPUT_LIBS) list(INSERT INPUT_LIBS 0 "LIBS") - endif() + endif () - generate_arduino_library( ${INPUT_NAME} - NO_AUTOLIBS - MANUAL - BOARD ${INPUT_BOARD} - SRCS ${INPUT_SRCS} - ${INPUT_HDRS} - ${INPUT_LIBS} ) - + generate_arduino_library(${INPUT_NAME} + NO_AUTOLIBS + MANUAL + BOARD ${INPUT_BOARD} + SRCS ${INPUT_SRCS} + ${INPUT_HDRS} + ${INPUT_LIBS}) + endfunction() #=============================================================================# +# GENERATE_ARDUINO_FIRMWARE # [PUBLIC/USER] # see documentation at top #=============================================================================# function(GENERATE_ARDUINO_FIRMWARE INPUT_NAME) message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT - "NO_AUTOLIBS;MANUAL" # Options - "BOARD;PORT;SKETCH;PROGRAMMER" # One Value Keywords - "SERIAL;SRCS;HDRS;LIBS;ARDLIBS;AFLAGS" # Multi Value Keywords - ${ARGN}) + "NO_AUTOLIBS;MANUAL" # Options + "BOARD;PORT;SKETCH;PROGRAMMER" # One Value Keywords + "SERIAL;SRCS;HDRS;LIBS;ARDLIBS;AFLAGS" # Multi Value Keywords + ${ARGN}) - if(NOT INPUT_BOARD) + if (NOT INPUT_BOARD) set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) - endif() - if(NOT INPUT_PORT) + endif () + if (NOT INPUT_PORT) set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) - endif() - if(NOT INPUT_SERIAL) + endif () + if (NOT INPUT_SERIAL) set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) - endif() - if(NOT INPUT_PROGRAMMER) + endif () + if (NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) - endif() - if(NOT INPUT_MANUAL) + endif () + if (NOT INPUT_MANUAL) set(INPUT_MANUAL FALSE) - endif() + endif () required_variables(VARS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") set(ALL_LIBS) set(ALL_SRCS ${INPUT_SRCS} ${INPUT_HDRS}) set(LIB_DEP_INCLUDES) - if(NOT INPUT_MANUAL) - setup_arduino_core(CORE_LIB ${INPUT_BOARD}) - endif() - - if(NOT "${INPUT_SKETCH}" STREQUAL "") + if (NOT INPUT_MANUAL) + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + endif () + + if (NOT "${INPUT_SKETCH}" STREQUAL "") get_filename_component(INPUT_SKETCH "${INPUT_SKETCH}" ABSOLUTE) setup_arduino_sketch(${INPUT_NAME} ${INPUT_SKETCH} ALL_SRCS) if (IS_DIRECTORY "${INPUT_SKETCH}") set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${INPUT_SKETCH}\"") - else() + else () get_filename_component(INPUT_SKETCH_PATH "${INPUT_SKETCH}" PATH) set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${INPUT_SKETCH_PATH}\"") - endif() - endif() + endif () + endif () required_variables(VARS ALL_SRCS MSG "must define SRCS or SKETCH for target ${INPUT_NAME}") find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "${INPUT_ARDLIBS}") - foreach(LIB_DEP ${TARGET_LIBS}) - arduino_debug_msg("Arduino Library: ${LIB_DEP}") + foreach (LIB_DEP ${TARGET_LIBS}) set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") - endforeach() + endforeach () - if(NOT INPUT_NO_AUTOLIBS) - setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "${INPUT_ARDLIBS}" "${LIB_DEP_INCLUDES}" "") - foreach(LIB_INCLUDES ${ALL_LIBS_INCLUDES}) + if (NOT INPUT_NO_AUTOLIBS) + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "${TARGET_LIBS}" "${LIB_DEP_INCLUDES}" "") + foreach (LIB_INCLUDES ${ALL_LIBS_INCLUDES}) arduino_debug_msg("Arduino Library Includes: ${LIB_INCLUDES}") set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} ${LIB_INCLUDES}") - endforeach() - endif() - + endforeach () + endif () + list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" "${INPUT_MANUAL}") - if(INPUT_PORT) + if (INPUT_PORT) setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") - endif() - - if(INPUT_SERIAL) + endif () + + if (INPUT_SERIAL) setup_serial_target(${INPUT_NAME} "${INPUT_SERIAL}" "${INPUT_PORT}") - endif() + endif () endfunction() #=============================================================================# +# GENERATE_AVR_FIRMWARE # [PUBLIC/USER] # see documentation at top #=============================================================================# @@ -533,76 +549,77 @@ function(GENERATE_AVR_FIRMWARE INPUT_NAME) # TODO: This is not optimal!!!! message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT - "NO_AUTOLIBS;MANUAL" # Options - "BOARD;PORT;PROGRAMMER" # One Value Keywords - "SERIAL;SRCS;HDRS;LIBS;AFLAGS" # Multi Value Keywords - ${ARGN}) - - if(NOT INPUT_BOARD) + "NO_AUTOLIBS;MANUAL" # Options + "BOARD;PORT;PROGRAMMER" # One Value Keywords + "SERIAL;SRCS;HDRS;LIBS;AFLAGS" # Multi Value Keywords + ${ARGN}) + + if (NOT INPUT_BOARD) set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) - endif() - if(NOT INPUT_PORT) + endif () + if (NOT INPUT_PORT) set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) - endif() - if(NOT INPUT_SERIAL) + endif () + if (NOT INPUT_SERIAL) set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) - endif() - if(NOT INPUT_PROGRAMMER) + endif () + if (NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) - endif() - + endif () + required_variables(VARS INPUT_BOARD INPUT_SRCS MSG "must define for target ${INPUT_NAME}") - if(INPUT_HDRS) + if (INPUT_HDRS) list(INSERT INPUT_HDRS 0 "HDRS") - endif() - if(INPUT_LIBS) + endif () + if (INPUT_LIBS) list(INSERT INPUT_LIBS 0 "LIBS") - endif() - if(INPUT_AFLAGS) + endif () + if (INPUT_AFLAGS) list(INSERT INPUT_AFLAGS 0 "AFLAGS") - endif() + endif () + + generate_arduino_firmware(${INPUT_NAME} + NO_AUTOLIBS + MANUAL + BOARD ${INPUT_BOARD} + PORT ${INPUT_PORT} + PROGRAMMER ${INPUT_PROGRAMMER} + SERIAL ${INPUT_SERIAL} + SRCS ${INPUT_SRCS} + ${INPUT_HDRS} + ${INPUT_LIBS} + ${INPUT_AFLAGS}) - generate_arduino_firmware( ${INPUT_NAME} - NO_AUTOLIBS - MANUAL - BOARD ${INPUT_BOARD} - PORT ${INPUT_PORT} - PROGRAMMER ${INPUT_PROGRAMMER} - SERIAL ${INPUT_SERIAL} - SRCS ${INPUT_SRCS} - ${INPUT_HDRS} - ${INPUT_LIBS} - ${INPUT_AFLAGS} ) - endfunction() #=============================================================================# +# GENERATE_ARDUINO_EXAMPLE # [PUBLIC/USER] # see documentation at top #=============================================================================# function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) parse_generator_arguments(${INPUT_NAME} INPUT - "" # Options - "LIBRARY;EXAMPLE;BOARD;PORT;PROGRAMMER" # One Value Keywords - "SERIAL;AFLAGS" # Multi Value Keywords - ${ARGN}) + "" # Options + "CATEGORY;EXAMPLE;BOARD;PORT;PROGRAMMER" # One Value Keywords + "SERIAL;AFLAGS" # Multi Value Keywords + ${ARGN}) - if(NOT INPUT_BOARD) + if (NOT INPUT_BOARD) set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) - endif() - if(NOT INPUT_PORT) + endif () + if (NOT INPUT_PORT) set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) - endif() - if(NOT INPUT_SERIAL) + endif () + if (NOT INPUT_SERIAL) set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) - endif() - if(NOT INPUT_PROGRAMMER) + endif () + if (NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) - endif() - required_variables(VARS INPUT_LIBRARY INPUT_EXAMPLE INPUT_BOARD - MSG "must define for target ${INPUT_NAME}") + endif () + required_variables(VARS INPUT_EXAMPLE INPUT_BOARD + MSG "must define for target ${INPUT_NAME}") message(STATUS "Generating ${INPUT_NAME}") @@ -611,34 +628,105 @@ function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) setup_arduino_core(CORE_LIB ${INPUT_BOARD}) - setup_arduino_example("${INPUT_NAME}" "${INPUT_LIBRARY}" "${INPUT_EXAMPLE}" ALL_SRCS) + SETUP_ARDUINO_EXAMPLE("${INPUT_NAME}" "${INPUT_EXAMPLE}" ALL_SRCS "${INPUT_CATEGORY}") - if(NOT ALL_SRCS) + if (NOT ALL_SRCS) message(FATAL_ERROR "Missing sources for example, aborting!") - endif() + endif () find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "") set(LIB_DEP_INCLUDES) - foreach(LIB_DEP ${TARGET_LIBS}) + foreach (LIB_DEP ${TARGET_LIBS}) set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") - endforeach() + endforeach () setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "" "${LIB_DEP_INCLUDES}" "") list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) - - setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" FALSE) - if(INPUT_PORT) + setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" FALSE) + + if (INPUT_PORT) setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") - endif() - - if(INPUT_SERIAL) + endif () + + if (INPUT_SERIAL) setup_serial_target(${INPUT_NAME} "${INPUT_SERIAL}" "${INPUT_PORT}") - endif() + endif () +endfunction() + +#=============================================================================# +# GENERATE_ARDUINO_LIBRARY_EXAMPLE +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_ARDUINO_LIBRARY_EXAMPLE INPUT_NAME) + parse_generator_arguments(${INPUT_NAME} INPUT + "" # Options + "LIBRARY;EXAMPLE;BOARD;PORT;PROGRAMMER" # One Value Keywords + "SERIAL;AFLAGS" # Multi Value Keywords + ${ARGN}) + + if (NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif () + if (NOT INPUT_PORT) + set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) + endif () + if (NOT INPUT_SERIAL) + set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) + endif () + if (NOT INPUT_PROGRAMMER) + set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) + endif () + required_variables(VARS INPUT_LIBRARY INPUT_EXAMPLE INPUT_BOARD + MSG "must define for target ${INPUT_NAME}") + + message(STATUS "Generating ${INPUT_NAME}") + + set(ALL_LIBS) + set(ALL_SRCS) + + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + + find_arduino_libraries(TARGET_LIBS "" "${INPUT_LIBRARY}") + set(LIB_DEP_INCLUDES) + foreach (LIB_DEP ${TARGET_LIBS}) + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") + endforeach () + + SETUP_ARDUINO_LIBRARY_EXAMPLE("${INPUT_NAME}" "${INPUT_LIBRARY}" + "${INPUT_EXAMPLE}" ALL_SRCS) + + if (NOT ALL_SRCS) + message(FATAL_ERROR "Missing sources for example, aborting!") + endif () + + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "${TARGET_LIBS}" + "${LIB_DEP_INCLUDES}" "") + + list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) + + setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" + "${LIB_DEP_INCLUDES}" "" FALSE) + + if (INPUT_PORT) + setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} + "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") + endif () + + if (INPUT_SERIAL) + setup_serial_target(${INPUT_NAME} "${INPUT_SERIAL}" "${INPUT_PORT}") + endif () endfunction() + +#=============================================================================# +# Other Functions +#=============================================================================# + #=============================================================================# +# REGISTER_HARDWARE_PLATFORM # [PUBLIC/USER] # see documentation at top #=============================================================================# @@ -646,7 +734,13 @@ function(REGISTER_HARDWARE_PLATFORM PLATFORM_PATH) string(REGEX REPLACE "/$" "" PLATFORM_PATH ${PLATFORM_PATH}) GET_FILENAME_COMPONENT(PLATFORM ${PLATFORM_PATH} NAME) - if(PLATFORM) + # platform path changed in versions 1.5 and greater + if (ARDUINO_SDK_VERSION VERSION_GREATER 1.0.5) + set(PLATFORM_PATH "${PLATFORM_PATH}/avr") + endif () + + if (PLATFORM) + # Avoid defining a platform multiple times if it has already been defined before string(TOUPPER ${PLATFORM} PLATFORM) list(FIND ARDUINO_PLATFORMS ${PLATFORM} platform_exists) @@ -655,69 +749,86 @@ function(REGISTER_HARDWARE_PLATFORM PLATFORM_PATH) set(ARDUINO_PLATFORMS ${ARDUINO_PLATFORMS} ${PLATFORM} CACHE INTERNAL "A list of registered platforms") find_file(${PLATFORM}_CORES_PATH - NAMES cores - PATHS ${PLATFORM_PATH} - DOC "Path to directory containing the Arduino core sources.") + NAMES cores + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino core sources.") find_file(${PLATFORM}_VARIANTS_PATH - NAMES variants - PATHS ${PLATFORM_PATH} - DOC "Path to directory containing the Arduino variant sources.") + NAMES variants + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino variant sources.") find_file(${PLATFORM}_BOOTLOADERS_PATH - NAMES bootloaders - PATHS ${PLATFORM_PATH} - DOC "Path to directory containing the Arduino bootloader images and sources.") + NAMES bootloaders + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino bootloader images and sources.") find_file(${PLATFORM}_PROGRAMMERS_PATH - NAMES programmers.txt - PATHS ${PLATFORM_PATH} - DOC "Path to Arduino programmers definition file.") + NAMES programmers.txt + PATHS ${PLATFORM_PATH} + DOC "Path to Arduino programmers definition file.") find_file(${PLATFORM}_BOARDS_PATH - NAMES boards.txt - PATHS ${PLATFORM_PATH} - DOC "Path to Arduino boards definition file.") - - if(${PLATFORM}_BOARDS_PATH) + NAMES boards.txt + PATHS ${PLATFORM_PATH} + DOC "Path to Arduino boards definition file.") + + # some libraries are in platform path in versions 1.5 and greater + if (ARDUINO_SDK_VERSION VERSION_GREATER 1.0.5) + find_file(${PLATFORM}_PLATFORM_LIBRARIES_PATH + NAMES libraries + PATHS ${PLATFORM_PATH} + DOC "Path to platform directory containing the Arduino libraries.") + set(ARDUINO_PLATFORM_LIBRARIES_PATH "${${PLATFORM}_PLATFORM_LIBRARIES_PATH}" PARENT_SCOPE) + else () + set(ARDUINO_PLATFORM_LIBRARIES_PATH "" PARENT_SCOPE) + endif () + + if (${PLATFORM}_BOARDS_PATH) load_arduino_style_settings(${PLATFORM}_BOARDS "${PLATFORM_PATH}/boards.txt") - endif() + endif () - if(${PLATFORM}_PROGRAMMERS_PATH) + if (${PLATFORM}_PROGRAMMERS_PATH) load_arduino_style_settings(${PLATFORM}_PROGRAMMERS "${ARDUINO_PROGRAMMERS_PATH}") - endif() + endif () - if(${PLATFORM}_VARIANTS_PATH) + if (${PLATFORM}_VARIANTS_PATH) file(GLOB sub-dir ${${PLATFORM}_VARIANTS_PATH}/*) - foreach(dir ${sub-dir}) - if(IS_DIRECTORY ${dir}) + foreach (dir ${sub-dir}) + if (IS_DIRECTORY ${dir}) get_filename_component(variant ${dir} NAME) set(VARIANTS ${VARIANTS} ${variant} CACHE INTERNAL "A list of registered variant boards") set(${variant}.path ${dir} CACHE INTERNAL "The path to the variant ${variant}") - endif() - endforeach() - endif() + endif () + endforeach () + endif () - if(${PLATFORM}_CORES_PATH) + if (${PLATFORM}_CORES_PATH) file(GLOB sub-dir ${${PLATFORM}_CORES_PATH}/*) - foreach(dir ${sub-dir}) - if(IS_DIRECTORY ${dir}) + foreach (dir ${sub-dir}) + if (IS_DIRECTORY ${dir}) get_filename_component(core ${dir} NAME) set(CORES ${CORES} ${core} CACHE INTERNAL "A list of registered cores") set(${core}.path ${dir} CACHE INTERNAL "The path to the core ${core}") - endif() - endforeach() - endif() - endif() - endif() + endif () + endforeach () + endif () + endif () + endif () endfunction() + +#=============================================================================# +# Internal Functions +#=============================================================================# + #=============================================================================# -# Internal Functions +# Macros #=============================================================================# #=============================================================================# +# parse_generator_arguments # [PRIVATE/INTERNAL] # # parse_generator_arguments(TARGET_NAME PREFIX OPTIONS ARGS MULTI_ARGS [ARG1 ARG2 .. ARGN]) @@ -738,6 +849,50 @@ macro(PARSE_GENERATOR_ARGUMENTS TARGET_NAME PREFIX OPTIONS ARGS MULTI_ARGS) endmacro() #=============================================================================# +# get_mcu +# [PRIVATE/INTERNAL] +# +# get_mcu(FULL_MCU_NAME, OUTPUT_VAR) +# +# FULL_MCU_NAME - Board's full mcu name, including a trailing 'p' if present +# OUTPUT_VAR - String value in which a regex match will be stored +# +# Matches the board's mcu without leading or trailing characters that would rather mess +# further processing that requires the board's mcu. +# +#=============================================================================# +macro(GET_MCU FULL_MCU_NAME OUTPUT_VAR) + string(REGEX MATCH "^.+[^p]" ${OUTPUT_VAR} "FULL_MCU_NAME" PARENT_SCOPE) +endmacro() + +#=============================================================================# +# increment_example_category_index +# [PRIVATE/INTERNAL] +# +# increment_example_category_index(OUTPUT_VAR) +# +# OUTPUT_VAR - A number representing an example's category prefix +# +# Increments the given number by one, taking into consideration the number notation +# which is defined (Some SDK's or OSs use a leading '0' in single-digit numbers. +# +#=============================================================================# +macro(INCREMENT_EXAMPLE_CATEGORY_INDEX OUTPUT_VAR) + math(EXPR INC_INDEX "${${OUTPUT_VAR}}+1") + if (EXAMPLE_CATEGORY_INDEX_LENGTH GREATER 1 AND INC_INDEX LESS 10) + set(${OUTPUT_VAR} "0${INC_INDEX}") + else () + set(${OUTPUT_VAR} ${INC_INDEX}) + endif () +endmacro() + + +#=============================================================================# +# Load Functions +#=============================================================================# + +#=============================================================================# +# load_generator_settings # [PRIVATE/INTERNAL] # # load_generator_settings(TARGET_NAME PREFIX [SUFFIX_1 SUFFIX_2 .. SUFFIX_N]) @@ -762,76 +917,192 @@ endmacro() # #=============================================================================# function(LOAD_GENERATOR_SETTINGS TARGET_NAME PREFIX) - foreach(GEN_SUFFIX ${ARGN}) - if(${TARGET_NAME}_${GEN_SUFFIX} AND NOT ${PREFIX}_${GEN_SUFFIX}) + foreach (GEN_SUFFIX ${ARGN}) + if (${TARGET_NAME}_${GEN_SUFFIX} AND NOT ${PREFIX}_${GEN_SUFFIX}) set(${PREFIX}_${GEN_SUFFIX} ${${TARGET_NAME}_${GEN_SUFFIX}} PARENT_SCOPE) - endif() - endforeach() + endif () + endforeach () endfunction() #=============================================================================# +# load_arduino_style_settings # [PRIVATE/INTERNAL] # -# get_arduino_flags(COMPILE_FLAGS LINK_FLAGS BOARD_ID MANUAL) +# load_arduino_style_settings(SETTINGS_LIST SETTINGS_PATH) # -# COMPILE_FLAGS_VAR -Variable holding compiler flags -# LINK_FLAGS_VAR - Variable holding linker flags -# BOARD_ID - The board id name -# MANUAL - (Advanced) Only use AVR Libc/Includes +# SETTINGS_LIST - Variable name of settings list +# SETTINGS_PATH - File path of settings file to load. # -# Configures the the build settings for the specified Arduino Board. +# Load a Arduino style settings file into the cache. +# +# Examples of this type of settings file is the boards.txt and +# programmers.txt files located in ${ARDUINO_SDK}/hardware/arduino. +# +# Settings have to following format: +# +# entry.setting[.subsetting] = value +# +# where [.subsetting] is optional +# +# For example, the following settings: +# +# uno.name=Arduino Uno +# uno.upload.protocol=stk500 +# uno.upload.maximum_size=32256 +# uno.build.mcu=atmega328p +# uno.build.core=arduino +# +# will generate the follwoing equivalent CMake variables: +# +# set(uno.name "Arduino Uno") +# set(uno.upload.protocol "stk500") +# set(uno.upload.maximum_size "32256") +# set(uno.build.mcu "atmega328p") +# set(uno.build.core "arduino") +# +# set(uno.SETTINGS name upload build) # List of settings for uno +# set(uno.upload.SUBSETTINGS protocol maximum_size) # List of sub-settings for uno.upload +# set(uno.build.SUBSETTINGS mcu core) # List of sub-settings for uno.build +# +# Note that Arduino 1.6 SDK or greater treats most of the settings differently for some boards, +# by grouping them into menus which differentiate on their cpu architecture. +# +# For example, the settings declared earlier for "regular" SDKs +# would be declared as such in 1.6: +# +# mega.name=Arduino Uno +# mega.menu.cpu.atmega2560.upload.protocol=wiring +# mega.menu.cpu.atmega2560.upload.maximum_size=253952 +# mega.menu.cpu.atmega2560.build.mcu=atmega2560 +# mega.build.core=arduino +# +# The ${ENTRY_NAME}.SETTINGS variable lists all settings for the entry, while +# ${ENTRY_NAME}.SUBSETTINGS variables lists all settings for a sub-setting of +# a entry setting pair. +# +# These variables are generated in order to be able to programatically traverse +# all settings (for a example see print_board_settings() function). # #=============================================================================# -function(get_arduino_flags COMPILE_FLAGS_VAR LINK_FLAGS_VAR BOARD_ID MANUAL) - - set(BOARD_CORE ${${BOARD_ID}.build.core}) - if(BOARD_CORE) - if(ARDUINO_SDK_VERSION MATCHES "([0-9]+)[.]([0-9]+)") - string(REPLACE "." "" ARDUINO_VERSION_DEFINE "${ARDUINO_SDK_VERSION}") # Normalize version (remove all periods) - set(ARDUINO_VERSION_DEFINE "") - if(CMAKE_MATCH_1 GREATER 0) - set(ARDUINO_VERSION_DEFINE "${CMAKE_MATCH_1}") - endif() - if(CMAKE_MATCH_2 GREATER 10) - set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}${CMAKE_MATCH_2}") - else() - set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}0${CMAKE_MATCH_2}") - endif() - else() - message("Invalid Arduino SDK Version (${ARDUINO_SDK_VERSION})") - endif() - - # output - set(COMPILE_FLAGS "-DF_CPU=${${BOARD_ID}.build.f_cpu} -DARDUINO=${ARDUINO_VERSION_DEFINE} -mmcu=${${BOARD_ID}.build.mcu}") - if(DEFINED ${BOARD_ID}.build.vid) - set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_VID=${${BOARD_ID}.build.vid}") - endif() - if(DEFINED ${BOARD_ID}.build.pid) - set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_PID=${${BOARD_ID}.build.pid}") - endif() - if(NOT MANUAL) - set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${${BOARD_CORE}.path}\" -I\"${ARDUINO_LIBRARIES_PATH}\"") - endif() - set(LINK_FLAGS "-mmcu=${${BOARD_ID}.build.mcu}") - if(ARDUINO_SDK_VERSION VERSION_GREATER 1.0 OR ARDUINO_SDK_VERSION VERSION_EQUAL 1.0) - if(NOT MANUAL) - set(PIN_HEADER ${${${BOARD_ID}.build.variant}.path}) - if(PIN_HEADER) - set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${PIN_HEADER}\"") - endif() - endif() - endif() +function(LOAD_ARDUINO_STYLE_SETTINGS SETTINGS_LIST SETTINGS_PATH) - # output - set(${COMPILE_FLAGS_VAR} "${COMPILE_FLAGS}" PARENT_SCOPE) - set(${LINK_FLAGS_VAR} "${LINK_FLAGS}" PARENT_SCOPE) + if (NOT ${SETTINGS_LIST} AND EXISTS ${SETTINGS_PATH}) + file(STRINGS ${SETTINGS_PATH} FILE_ENTRIES) # Settings file split into lines + + foreach (FILE_ENTRY ${FILE_ENTRIES}) + if ("${FILE_ENTRY}" MATCHES "^[^#]+=.*") + string(REGEX MATCH "^[^=]+" SETTING_NAME ${FILE_ENTRY}) + string(REGEX MATCH "[^=]+$" SETTING_VALUE ${FILE_ENTRY}) + string(REPLACE "." ";" ENTRY_NAME_TOKENS ${SETTING_NAME}) + string(STRIP "${SETTING_VALUE}" SETTING_VALUE) + + list(LENGTH ENTRY_NAME_TOKENS ENTRY_NAME_TOKENS_LEN) + + # Add entry to settings list if it does not exist + list(GET ENTRY_NAME_TOKENS 0 ENTRY_NAME) + list(FIND ${SETTINGS_LIST} ${ENTRY_NAME} ENTRY_NAME_INDEX) + if (ENTRY_NAME_INDEX LESS 0) + # Add entry to main list + list(APPEND ${SETTINGS_LIST} ${ENTRY_NAME}) + endif () + + # Add entry setting to entry settings list if it does not exist + set(ENTRY_SETTING_LIST ${ENTRY_NAME}.SETTINGS) + + # menu.cpu.architecture settings + if (ENTRY_NAME_TOKENS_LEN GREATER 5) + list(GET ENTRY_NAME_TOKENS 3 CPU_ARCH) + list(GET ENTRY_NAME_TOKENS 4 ENTRY_SETTING) + set(ENTRY_SETTING menu.cpu.${CPU_ARCH}.${ENTRY_SETTING}) + else () + list(GET ENTRY_NAME_TOKENS 1 ENTRY_SETTING) + endif () + + list(FIND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING} ENTRY_SETTING_INDEX) + if (ENTRY_SETTING_INDEX LESS 0) + # Add setting to entry + list(APPEND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING}) + set(${ENTRY_SETTING_LIST} ${${ENTRY_SETTING_LIST}} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board settings list") + endif () + + set(FULL_SETTING_NAME ${ENTRY_NAME}.${ENTRY_SETTING}) + + # Add entry sub-setting to entry sub-settings list if it does not exists + if (ENTRY_NAME_TOKENS_LEN GREATER 2) + + set(ENTRY_SUBSETTING_LIST ${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) + if (ENTRY_NAME_TOKENS_LEN GREATER 5) + list(GET ENTRY_NAME_TOKENS 5 ENTRY_SUBSETTING) + elseif (ENTRY_NAME_TOKENS_LEN GREATER 3) + # Search for special cpu sub-settings + list(GET ENTRY_NAME_TOKENS 2 ENTRY_SUBSETTING) + string(TOLOWER ${ENTRY_SUBSETTING} ENTRY_SUBSETTING) + if ("${ENTRY_SUBSETTING}" STREQUAL "cpu") + # cpu setting found, determine architecture + list(GET ENTRY_NAME_TOKENS 3 ENTRY_SUBSETTING) + set(ENTRY_SUBSETTING_LIST ${ENTRY_NAME}.${ENTRY_SETTING}.CPUS) + endif () + else () + list(GET ENTRY_NAME_TOKENS 2 ENTRY_SUBSETTING) + endif () + list(FIND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING} ENTRY_SUBSETTING_INDEX) + if (ENTRY_SUBSETTING_INDEX LESS 0) + list(APPEND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING}) + set(${ENTRY_SUBSETTING_LIST} ${${ENTRY_SUBSETTING_LIST}} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board sub-settings list") + endif () + set(FULL_SETTING_NAME ${FULL_SETTING_NAME}.${ENTRY_SUBSETTING}) + + endif () + + # Save setting value + set(${FULL_SETTING_NAME} ${SETTING_VALUE} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board setting") + + endif () + endforeach () + set(${SETTINGS_LIST} ${${SETTINGS_LIST}} + CACHE STRING "List of detected Arduino Board configurations") + mark_as_advanced(${SETTINGS_LIST}) + endif () +endfunction() - else() - message(FATAL_ERROR "Invalid Arduino board ID (${BOARD_ID}), aborting.") - endif() +#=============================================================================# +# load_arduino_examples +# [PRIVATE/INTERNAL] +# +# load_arduino_examples() +# +# Loads all of Arduino's built-in examples categories, listing it by their names +# without the index prefix ('01.Basics' becomes 'Basics'). +# This list is saved in a cached variable named 'ARDUINO_EXAMPLES_CATEGORIES'. +# +#=============================================================================# +function(load_arduino_examples_categories) + file(GLOB EXAMPLE_CATEGORIES RELATIVE ${ARDUINO_EXAMPLES_PATH} ${ARDUINO_EXAMPLES_PATH}/*) + foreach (CATEGORY ${EXAMPLE_CATEGORIES}) + if (NOT EXAMPLE_CATEGORY_INDEX_LENGTH) + string(REGEX MATCH "^[0-9]+" CATEGORY_INDEX ${CATEGORY}) + string(LENGTH ${CATEGORY_INDEX} INDEX_LENGTH) + set(EXAMPLE_CATEGORY_INDEX_LENGTH ${INDEX_LENGTH} CACHE INTERNAL + "Number of digits preceeding an example's category path") + endif () + string(REGEX MATCH "[^0-9.]+$" PARSED_CATEGORY ${CATEGORY}) + string(TOLOWER ${PARSED_CATEGORY} PARSED_CATEGORY) + list(APPEND CATEGORIES "${PARSED_CATEGORY}") + endforeach () + set(ARDUINO_EXAMPLES_CATEGORIES ${CATEGORIES} CACHE INTERNAL + "List of the categories of the built-in Arduino examples") endfunction() + +#=============================================================================# +# Setup Functions +#=============================================================================# + #=============================================================================# +# setup_arduino_core # [PRIVATE/INTERNAL] # # setup_arduino_core(VAR_NAME BOARD_ID) @@ -846,8 +1117,8 @@ endfunction() function(setup_arduino_core VAR_NAME BOARD_ID) set(CORE_LIB_NAME ${BOARD_ID}_CORE) set(BOARD_CORE ${${BOARD_ID}.build.core}) - if(BOARD_CORE) - if(NOT TARGET ${CORE_LIB_NAME}) + if (BOARD_CORE) + if (NOT TARGET ${CORE_LIB_NAME}) set(BOARD_CORE_PATH ${${BOARD_CORE}.path}) find_sources(CORE_SRCS ${BOARD_CORE_PATH} True) # Debian/Ubuntu fix @@ -855,92 +1126,15 @@ function(setup_arduino_core VAR_NAME BOARD_ID) add_library(${CORE_LIB_NAME} ${CORE_SRCS}) get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} FALSE) set_target_properties(${CORE_LIB_NAME} PROPERTIES - COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS}" - LINK_FLAGS "${ARDUINO_LINK_FLAGS}") - endif() + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS}") + endif () set(${VAR_NAME} ${CORE_LIB_NAME} PARENT_SCOPE) - endif() -endfunction() - -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# find_arduino_libraries(VAR_NAME SRCS ARDLIBS) -# -# VAR_NAME - Variable name which will hold the results -# SRCS - Sources that will be analized -# ARDLIBS - Arduino libraries identified by name (e.g., Wire, SPI, Servo) -# -# returns a list of paths to libraries found. -# -# Finds all Arduino type libraries included in sources. Available libraries -# are ${ARDUINO_SDK_PATH}/libraries and ${CMAKE_CURRENT_SOURCE_DIR}. -# -# Also adds Arduino libraries specifically names in ALIBS. We add ".h" to the -# names and then process them just like the Arduino libraries found in the sources. -# -# A Arduino library is a folder that has the same name as the include header. -# For example, if we have a include "#include " then the following -# directory structure is considered a Arduino library: -# -# LibraryName/ -# |- LibraryName.h -# `- LibraryName.c -# -# If such a directory is found then all sources within that directory are considred -# to be part of that Arduino library. -# -#=============================================================================# -function(find_arduino_libraries VAR_NAME SRCS ARDLIBS) - set(ARDUINO_LIBS ) - foreach(SRC ${SRCS}) - - # Skipping generated files. They are, probably, not exist yet. - # TODO: Maybe it's possible to skip only really nonexisting files, - # but then it wiil be less deterministic. - get_source_file_property(_srcfile_generated ${SRC} GENERATED) - # Workaround for sketches, which are marked as generated - get_source_file_property(_sketch_generated ${SRC} GENERATED_SKETCH) - - if(NOT ${_srcfile_generated} OR ${_sketch_generated}) - if(NOT (EXISTS ${SRC} OR - EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} OR - EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${SRC})) - message(FATAL_ERROR "Invalid source file: ${SRC}") - endif() - file(STRINGS ${SRC} SRC_CONTENTS) - - foreach(LIBNAME ${ARDLIBS}) - list(APPEND SRC_CONTENTS "#include <${LIBNAME}.h>") - endforeach() - - foreach(SRC_LINE ${SRC_CONTENTS}) - if("${SRC_LINE}" MATCHES "^[ \t]*#[ \t]*include[ \t]*[<\"]([^>\"]*)[>\"]") - get_filename_component(INCLUDE_NAME ${CMAKE_MATCH_1} NAME_WE) - get_property(LIBRARY_SEARCH_PATH - DIRECTORY # Property Scope - PROPERTY LINK_DIRECTORIES) - foreach(LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libraries ${ARDUINO_EXTRA_LIBRARIES_PATH}) - if(EXISTS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/${CMAKE_MATCH_1}) - list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}) - break() - endif() - if(EXISTS ${LIB_SEARCH_PATH}/${CMAKE_MATCH_1}) - list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}) - break() - endif() - endforeach() - endif() - endforeach() - endif() - endforeach() - if(ARDUINO_LIBS) - list(REMOVE_DUPLICATES ARDUINO_LIBS) - endif() - set(${VAR_NAME} ${ARDUINO_LIBS} PARENT_SCOPE) + endif () endfunction() #=============================================================================# +# setup_arduino_library # [PRIVATE/INTERNAL] # # setup_arduino_library(VAR_NAME BOARD_ID LIB_PATH COMPILE_FLAGS LINK_FLAGS) @@ -962,22 +1156,23 @@ endfunction() set(Wire_RECURSE True) set(Ethernet_RECURSE True) set(SD_RECURSE True) + function(setup_arduino_library VAR_NAME BOARD_ID LIB_PATH COMPILE_FLAGS LINK_FLAGS) - set(LIB_TARGETS) - set(LIB_INCLUDES) - get_filename_component(LIB_NAME ${LIB_PATH} NAME) + string(REGEX REPLACE "/src/?$" "" LIB_PATH_STRIPPED ${LIB_PATH}) + get_filename_component(LIB_NAME ${LIB_PATH_STRIPPED} NAME) set(TARGET_LIB_NAME ${BOARD_ID}_${LIB_NAME}) - if(NOT TARGET ${TARGET_LIB_NAME}) + + if (NOT TARGET ${TARGET_LIB_NAME}) string(REGEX REPLACE ".*/" "" LIB_SHORT_NAME ${LIB_NAME}) # Detect if recursion is needed if (NOT DEFINED ${LIB_SHORT_NAME}_RECURSE) set(${LIB_SHORT_NAME}_RECURSE False) - endif() + endif () find_sources(LIB_SRCS ${LIB_PATH} ${${LIB_SHORT_NAME}_RECURSE}) - if(LIB_SRCS) + if (LIB_SRCS) arduino_debug_msg("Generating Arduino ${LIB_NAME} library") add_library(${TARGET_LIB_NAME} STATIC ${LIB_SRCS}) @@ -986,37 +1181,42 @@ function(setup_arduino_library VAR_NAME BOARD_ID LIB_PATH COMPILE_FLAGS LINK_FLA find_arduino_libraries(LIB_DEPS "${LIB_SRCS}" "") - foreach(LIB_DEP ${LIB_DEPS}) - setup_arduino_library(DEP_LIB_SRCS ${BOARD_ID} ${LIB_DEP} "${COMPILE_FLAGS}" "${LINK_FLAGS}") + foreach (LIB_DEP ${LIB_DEPS}) + setup_arduino_library(DEP_LIB_SRCS ${BOARD_ID} ${LIB_DEP} + "${COMPILE_FLAGS}" "${LINK_FLAGS}") list(APPEND LIB_TARGETS ${DEP_LIB_SRCS}) list(APPEND LIB_INCLUDES ${DEP_LIB_SRCS_INCLUDES}) - endforeach() + endforeach () if (LIB_INCLUDES) string(REPLACE ";" " " LIB_INCLUDES "${LIB_INCLUDES}") - endif() + endif () set_target_properties(${TARGET_LIB_NAME} PROPERTIES - COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${LIB_INCLUDES} -I\"${LIB_PATH}\" -I\"${LIB_PATH}/utility\" ${COMPILE_FLAGS}" - LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${LIB_INCLUDES} -I\"${LIB_PATH}\" -I\"${LIB_PATH}/utility\" ${COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") list(APPEND LIB_INCLUDES "-I\"${LIB_PATH}\" -I\"${LIB_PATH}/utility\"") + if (LIB_TARGETS) + list(REMOVE_ITEM LIB_TARGETS ${TARGET_LIB_NAME}) + endif () target_link_libraries(${TARGET_LIB_NAME} ${BOARD_ID}_CORE ${LIB_TARGETS}) list(APPEND LIB_TARGETS ${TARGET_LIB_NAME}) - endif() - else() + endif () + else () # Target already exists, skiping creating list(APPEND LIB_TARGETS ${TARGET_LIB_NAME}) - endif() - if(LIB_TARGETS) + endif () + if (LIB_TARGETS) list(REMOVE_DUPLICATES LIB_TARGETS) - endif() - set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) + endif () + set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) set(${VAR_NAME}_INCLUDES ${LIB_INCLUDES} PARENT_SCOPE) endfunction() #=============================================================================# +# setup_arduino_libraries # [PRIVATE/INTERNAL] # # setup_arduino_libraries(VAR_NAME BOARD_ID SRCS COMPILE_FLAGS LINK_FLAGS) @@ -1031,23 +1231,20 @@ endfunction() # #=============================================================================# function(setup_arduino_libraries VAR_NAME BOARD_ID SRCS ARDLIBS COMPILE_FLAGS LINK_FLAGS) - set(LIB_TARGETS) - set(LIB_INCLUDES) - - find_arduino_libraries(TARGET_LIBS "${SRCS}" ARDLIBS) - foreach(TARGET_LIB ${TARGET_LIBS}) + foreach (TARGET_LIB ${ARDLIBS}) # Create static library instead of returning sources - setup_arduino_library(LIB_DEPS ${BOARD_ID} ${TARGET_LIB} "${COMPILE_FLAGS}" "${LINK_FLAGS}") + setup_arduino_library(LIB_DEPS ${BOARD_ID} ${TARGET_LIB} + "${COMPILE_FLAGS}" "${LINK_FLAGS}") list(APPEND LIB_TARGETS ${LIB_DEPS}) list(APPEND LIB_INCLUDES ${LIB_DEPS_INCLUDES}) - endforeach() + endforeach () - set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) + set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) set(${VAR_NAME}_INCLUDES ${LIB_INCLUDES} PARENT_SCOPE) endfunction() - #=============================================================================# +# setup_arduino_target # [PRIVATE/INTERNAL] # # setup_arduino_target(TARGET_NAME ALL_SRCS ALL_LIBS COMPILE_FLAGS LINK_FLAGS MANUAL) @@ -1063,62 +1260,65 @@ endfunction() # Creates an Arduino firmware target. # #=============================================================================# -function(setup_arduino_target TARGET_NAME BOARD_ID ALL_SRCS ALL_LIBS COMPILE_FLAGS LINK_FLAGS MANUAL) +function(setup_arduino_target TARGET_NAME BOARD_ID ALL_SRCS ALL_LIBS + COMPILE_FLAGS LINK_FLAGS MANUAL) - add_executable(${TARGET_NAME} ${ALL_SRCS}) + string(STRIP "${ALL_SRCS}" ALL_SRCS) + add_executable(${TARGET_NAME} "${ALL_SRCS}") set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".elf") - get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} ${MANUAL}) + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} ${MANUAL}) set_target_properties(${TARGET_NAME} PROPERTIES - COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS}" - LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") target_link_libraries(${TARGET_NAME} ${ALL_LIBS} "-lc -lm") - if(NOT EXECUTABLE_OUTPUT_PATH) - set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) - endif() + if (NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif () set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_OBJCOPY} - ARGS ${ARDUINO_OBJCOPY_EEP_FLAGS} - ${TARGET_PATH}.elf - ${TARGET_PATH}.eep - COMMENT "Generating EEP image" - VERBATIM) + COMMAND ${CMAKE_OBJCOPY} + ARGS ${ARDUINO_OBJCOPY_EEP_FLAGS} + ${TARGET_PATH}.elf + ${TARGET_PATH}.eep + COMMENT "Generating EEP image" + VERBATIM) # Convert firmware image to ASCII HEX format add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_OBJCOPY} - ARGS ${ARDUINO_OBJCOPY_HEX_FLAGS} - ${TARGET_PATH}.elf - ${TARGET_PATH}.hex - COMMENT "Generating HEX image" - VERBATIM) + COMMAND ${CMAKE_OBJCOPY} + ARGS ${ARDUINO_OBJCOPY_HEX_FLAGS} + ${TARGET_PATH}.elf + ${TARGET_PATH}.hex + COMMENT "Generating HEX image" + VERBATIM) # Display target size add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS -DFIRMWARE_IMAGE=${TARGET_PATH}.elf - -DMCU=${${BOARD_ID}.build.mcu} - -DEEPROM_IMAGE=${TARGET_PATH}.eep - -P ${ARDUINO_SIZE_SCRIPT} - COMMENT "Calculating image size" - VERBATIM) + COMMAND ${CMAKE_COMMAND} + ARGS -DFIRMWARE_IMAGE=${TARGET_PATH}.elf + -DMCU=${${BOARD_ID}.build.mcu} + -DEEPROM_IMAGE=${TARGET_PATH}.eep + -P ${ARDUINO_SIZE_SCRIPT} + COMMENT "Calculating image size" + VERBATIM) # Create ${TARGET_NAME}-size target add_custom_target(${TARGET_NAME}-size - COMMAND ${CMAKE_COMMAND} - -DFIRMWARE_IMAGE=${TARGET_PATH}.elf - -DMCU=${${BOARD_ID}.build.mcu} - -DEEPROM_IMAGE=${TARGET_PATH}.eep - -P ${ARDUINO_SIZE_SCRIPT} - DEPENDS ${TARGET_NAME} - COMMENT "Calculating ${TARGET_NAME} image size") + COMMAND ${CMAKE_COMMAND} + -DFIRMWARE_IMAGE=${TARGET_PATH}.elf + -DMCU=${${BOARD_ID}.build.mcu} + -DEEPROM_IMAGE=${TARGET_PATH}.eep + -P ${ARDUINO_SIZE_SCRIPT} + DEPENDS ${TARGET_NAME} + COMMENT "Calculating ${TARGET_NAME} image size") endfunction() #=============================================================================# +# setup_arduino_upload # [PRIVATE/INTERNAL] # # setup_arduino_upload(BOARD_ID TARGET_NAME PORT) @@ -1136,14 +1336,14 @@ function(setup_arduino_upload BOARD_ID TARGET_NAME PORT PROGRAMMER_ID AVRDUDE_FL setup_arduino_bootloader_upload(${TARGET_NAME} ${BOARD_ID} ${PORT} "${AVRDUDE_FLAGS}") # Add programmer support if defined - if(PROGRAMMER_ID AND ${PROGRAMMER_ID}.protocol) + if (PROGRAMMER_ID AND ${PROGRAMMER_ID}.protocol) setup_arduino_programmer_burn(${TARGET_NAME} ${BOARD_ID} ${PROGRAMMER_ID} ${PORT} "${AVRDUDE_FLAGS}") setup_arduino_bootloader_burn(${TARGET_NAME} ${BOARD_ID} ${PROGRAMMER_ID} ${PORT} "${AVRDUDE_FLAGS}") - endif() + endif () endfunction() - #=============================================================================# +# setup_arduino_bootloader_upload # [PRIVATE/INTERNAL] # # setup_arduino_bootloader_upload(TARGET_NAME BOARD_ID PORT) @@ -1164,32 +1364,33 @@ function(setup_arduino_bootloader_upload TARGET_NAME BOARD_ID PORT AVRDUDE_FLAGS setup_arduino_bootloader_args(${BOARD_ID} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) - if(NOT AVRDUDE_ARGS) + if (NOT AVRDUDE_ARGS) message("Could not generate default avrdude bootloader args, aborting!") return() - endif() + endif () - if(NOT EXECUTABLE_OUTPUT_PATH) - set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) - endif() + if (NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif () set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) - list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex") - list(APPEND AVRDUDE_ARGS "-Ueeprom:w:${TARGET_PATH}.eep:i") + list(APPEND AVRDUDE_ARGS "-Uflash:w:\"${TARGET_PATH}.hex\":i") + list(APPEND AVRDUDE_ARGS "-Ueeprom:w:\"${TARGET_PATH}.eep\":i") add_custom_target(${UPLOAD_TARGET} - ${ARDUINO_AVRDUDE_PROGRAM} - ${AVRDUDE_ARGS} - DEPENDS ${TARGET_NAME}) + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + DEPENDS ${TARGET_NAME}) # Global upload target - if(NOT TARGET upload) + if (NOT TARGET upload) add_custom_target(upload) - endif() + endif () add_dependencies(upload ${UPLOAD_TARGET}) endfunction() #=============================================================================# +# setup_arduino_programmer_burn # [PRIVATE/INTERNAL] # # setup_arduino_programmer_burn(TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) @@ -1212,25 +1413,26 @@ function(setup_arduino_programmer_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRD setup_arduino_programmer_args(${BOARD_ID} ${PROGRAMMER} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) - if(NOT AVRDUDE_ARGS) + if (NOT AVRDUDE_ARGS) message("Could not generate default avrdude programmer args, aborting!") return() - endif() + endif () - if(NOT EXECUTABLE_OUTPUT_PATH) - set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) - endif() + if (NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif () set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) - list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex") + list(APPEND AVRDUDE_ARGS "-Uflash:w:\"${TARGET_PATH}.hex\":i") add_custom_target(${PROGRAMMER_TARGET} - ${ARDUINO_AVRDUDE_PROGRAM} - ${AVRDUDE_ARGS} - DEPENDS ${TARGET_NAME}) + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + DEPENDS ${TARGET_NAME}) endfunction() #=============================================================================# +# setup_arduino_bootloader_burn # [PRIVATE/INTERNAL] # # setup_arduino_bootloader_burn(TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) @@ -1253,51 +1455,105 @@ function(setup_arduino_bootloader_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRD setup_arduino_programmer_args(${BOARD_ID} ${PROGRAMMER} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) - if(NOT AVRDUDE_ARGS) + if (NOT AVRDUDE_ARGS) message("Could not generate default avrdude programmer args, aborting!") return() - endif() - - foreach( ITEM unlock_bits high_fuses low_fuses path file) - if(NOT ${BOARD_ID}.bootloader.${ITEM}) - message("Missing ${BOARD_ID}.bootloader.${ITEM}, not creating bootloader burn target ${BOOTLOADER_TARGET}.") - return() - endif() - endforeach() - - if(NOT EXISTS "${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path}/${${BOARD_ID}.bootloader.file}") + endif () + + # look at bootloader.file + set(BOOTLOADER_FOUND True) + if (NOT ${BOARD_ID}.bootloader.file) + set(BOOTLOADER_FOUND False) + # Bootloader is probably defined in the 'menu' settings of the Arduino 1.6 SDK + if (${BOARD_ID}.build.mcu) + GET_MCU(${${BOARD_ID}.build.mcu} BOARD_MCU) + if (NOT ${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.file) + message("Missing ${BOARD_ID}.bootloader.file, not creating bootloader burn target ${BOOTLOADER_TARGET}.") + return() + endif () + set(BOOTLOADER_FOUND True) + set(${BOARD_ID}.bootloader.file ${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.file) + endif () + endif () + + if (NOT ${BOOTLOADER_FOUND}) + return() + endif () + + # build bootloader.path from bootloader.file... + string(REGEX MATCH "(.+/)*" ${BOARD_ID}.bootloader.path ${${BOARD_ID}.bootloader.file}) + string(REGEX REPLACE "/" "" ${BOARD_ID}.bootloader.path ${${BOARD_ID}.bootloader.path}) + # and fix bootloader.file + string(REGEX MATCH "/.(.+)$" ${BOARD_ID}.bootloader.file ${${BOARD_ID}.bootloader.file}) + string(REGEX REPLACE "/" "" ${BOARD_ID}.bootloader.file ${${BOARD_ID}.bootloader.file}) + + foreach (ITEM unlock_bits high_fuses low_fuses path file) + if (NOT ${BOARD_ID}.bootloader.${ITEM}) + # Try the 'menu' settings of the Arduino 1.6 SDK + if (NOT ${BOARD_ID}.menu.cpu.{BOARD_MCU}.bootloader.${ITEM}) + message("Missing ${BOARD_ID}.bootloader.${ITEM}, not creating bootloader burn target ${BOOTLOADER_TARGET}.") + return() + endif () + endif () + endforeach () + + if (NOT EXISTS "${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path}/${${BOARD_ID}.bootloader.file}") message("${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path}/${${BOARD_ID}.bootloader.file}") message("Missing bootloader image, not creating bootloader burn target ${BOOTLOADER_TARGET}.") return() - endif() + endif () # Erase the chip list(APPEND AVRDUDE_ARGS "-e") # Set unlock bits and fuses (because chip is going to be erased) - list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.unlock_bits}:m") - if(${BOARD_ID}.bootloader.extended_fuses) + + if (${BOARD_ID}.bootloader.unlock_bits) + list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.unlock_bits}:m") + else () + # Arduino 1.6 SDK + list(APPEND AVRDUDE_ARGS + "-Ulock:w:${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.unlock_bits}:m") + endif () + + if (${BOARD_ID}.bootloader.extended_fuses) list(APPEND AVRDUDE_ARGS "-Uefuse:w:${${BOARD_ID}.bootloader.extended_fuses}:m") - endif() - list(APPEND AVRDUDE_ARGS - "-Uhfuse:w:${${BOARD_ID}.bootloader.high_fuses}:m" - "-Ulfuse:w:${${BOARD_ID}.bootloader.low_fuses}:m") + elseif (${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.extended_fuses}) + list(APPEND AVRDUDE_ARGS + "-Uefuse:w:${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.extended_fuses}:m") + endif () + if (${BOARD_ID}.bootloader.high_fuses) + list(APPEND AVRDUDE_ARGS + "-Uhfuse:w:${${BOARD_ID}.bootloader.high_fuses}:m" + "-Ulfuse:w:${${BOARD_ID}.bootloader.low_fuses}:m") + else () + list(APPEND AVRDUDE_ARGS + "-Uhfuse:w:${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.high_fuses}:m" + "-Ulfuse:w:${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.low_fuses}:m") + endif () # Set bootloader image list(APPEND AVRDUDE_ARGS "-Uflash:w:${${BOARD_ID}.bootloader.file}:i") # Set lockbits - list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.lock_bits}:m") + if (${BOARD_ID}.bootloader.lock_bits) + list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.lock_bits}:m") + else () + list(APPEND AVRDUDE_ARGS + "-Ulock:w:${${BOARD_ID}.menu.cpu.${BOARD_MCU}.bootloader.lock_bits}:m") + endif () + # Create burn bootloader target add_custom_target(${BOOTLOADER_TARGET} - ${ARDUINO_AVRDUDE_PROGRAM} - ${AVRDUDE_ARGS} - WORKING_DIRECTORY ${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path} - DEPENDS ${TARGET_NAME}) + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + WORKING_DIRECTORY ${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path} + DEPENDS ${TARGET_NAME}) endfunction() #=============================================================================# +# setup_arduino_programmer_args # [PRIVATE/INTERNAL] # # setup_arduino_programmer_args(BOARD_ID PROGRAMMER TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) @@ -1314,35 +1570,35 @@ endfunction() function(setup_arduino_programmer_args BOARD_ID PROGRAMMER TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) set(AVRDUDE_ARGS ${${OUTPUT_VAR}}) - if(NOT AVRDUDE_FLAGS) + if (NOT AVRDUDE_FLAGS) set(AVRDUDE_FLAGS ${ARDUINO_AVRDUDE_FLAGS}) - endif() + endif () list(APPEND AVRDUDE_ARGS "-C${ARDUINO_AVRDUDE_CONFIG_PATH}") #TODO: Check mandatory settings before continuing - if(NOT ${PROGRAMMER}.protocol) + if (NOT ${PROGRAMMER}.protocol) message(FATAL_ERROR "Missing ${PROGRAMMER}.protocol, aborting!") - endif() + endif () list(APPEND AVRDUDE_ARGS "-c${${PROGRAMMER}.protocol}") # Set programmer - if(${PROGRAMMER}.communication STREQUAL "usb") + if (${PROGRAMMER}.communication STREQUAL "usb") list(APPEND AVRDUDE_ARGS "-Pusb") # Set USB as port - elseif(${PROGRAMMER}.communication STREQUAL "serial") + elseif (${PROGRAMMER}.communication STREQUAL "serial") list(APPEND AVRDUDE_ARGS "-P${PORT}") # Set port - if(${PROGRAMMER}.speed) + if (${PROGRAMMER}.speed) list(APPEND AVRDUDE_ARGS "-b${${PROGRAMMER}.speed}") # Set baud rate - endif() - endif() + endif () + endif () - if(${PROGRAMMER}.force) + if (${PROGRAMMER}.force) list(APPEND AVRDUDE_ARGS "-F") # Set force - endif() + endif () - if(${PROGRAMMER}.delay) + if (${PROGRAMMER}.delay) list(APPEND AVRDUDE_ARGS "-i${${PROGRAMMER}.delay}") # Set delay - endif() + endif () list(APPEND AVRDUDE_ARGS "-p${${BOARD_ID}.build.mcu}") # MCU Type @@ -1352,6 +1608,7 @@ function(setup_arduino_programmer_args BOARD_ID PROGRAMMER TARGET_NAME PORT AVRD endfunction() #=============================================================================# +# setup_arduino_bootloader_args # [PRIVATE/INTERNAL] # # setup_arduino_bootloader_args(BOARD_ID TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) @@ -1367,72 +1624,53 @@ endfunction() function(setup_arduino_bootloader_args BOARD_ID TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) set(AVRDUDE_ARGS ${${OUTPUT_VAR}}) - if(NOT AVRDUDE_FLAGS) + if (NOT AVRDUDE_FLAGS) set(AVRDUDE_FLAGS ${ARDUINO_AVRDUDE_FLAGS}) - endif() + endif () list(APPEND AVRDUDE_ARGS - "-C${ARDUINO_AVRDUDE_CONFIG_PATH}" # avrdude config - "-p${${BOARD_ID}.build.mcu}" # MCU Type - ) + "-C${ARDUINO_AVRDUDE_CONFIG_PATH}" # avrdude config + "-p${${BOARD_ID}.build.mcu}" # MCU Type + ) # Programmer - if(NOT ${BOARD_ID}.upload.protocol OR ${BOARD_ID}.upload.protocol STREQUAL "stk500") + if (NOT ${BOARD_ID}.upload.protocol OR ${BOARD_ID}.upload.protocol STREQUAL "stk500") list(APPEND AVRDUDE_ARGS "-cstk500v1") - else() + else () list(APPEND AVRDUDE_ARGS "-c${${BOARD_ID}.upload.protocol}") - endif() + endif () - set(UPLOAD_SPEED "19200") - if(${BOARD_ID}.upload.speed) + set(UPLOAD_SPEED "19200") # Set a default speed + if (${BOARD_ID}.upload.speed) set(UPLOAD_SPEED ${${BOARD_ID}.upload.speed}) - endif() + else () + # Speed wasn't manually set, and is not defined in the simple board settings + # The only option left is to search in the 'menu' settings of the Arduino 1.6 SDK + list(FIND ${BOARD_ID}.SETTINGS menu MENU_SETTINGS) + # Determine upload speed based on the defined cpu architecture (mcu) + if (${BOARD_ID}.build.mcu) + GET_MCU(${${BOARD_ID}.build.mcu} BOARD_MCU) + list(FIND ${BOARD_ID}.menu.CPUS ${BOARD_MCU} BOARD_MCU_INDEX) + if (BOARD_MCU_INDEX GREATER_EQUAL 0) # Matching mcu is found + set(UPLOAD_SPEED ${${BOARD_ID}.menu.cpu.${BOARD_MCU}.upload.speed}) + endif () + endif () + endif () list(APPEND AVRDUDE_ARGS - "-b${UPLOAD_SPEED}" # Baud rate - "-P${PORT}" # Serial port - "-D" # Dont erase - ) + "-b${UPLOAD_SPEED}" # Baud rate + "-P${PORT}" # Serial port + "-D" # Dont erase + ) list(APPEND AVRDUDE_ARGS ${AVRDUDE_FLAGS}) set(${OUTPUT_VAR} ${AVRDUDE_ARGS} PARENT_SCOPE) -endfunction() -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# find_sources(VAR_NAME LIB_PATH RECURSE) -# -# VAR_NAME - Variable name that will hold the detected sources -# LIB_PATH - The base path -# RECURSE - Whether or not to recurse -# -# Finds all C/C++ sources located at the specified path. -# -#=============================================================================# -function(find_sources VAR_NAME LIB_PATH RECURSE) - set(FILE_SEARCH_LIST - ${LIB_PATH}/*.cpp - ${LIB_PATH}/*.c - ${LIB_PATH}/*.cc - ${LIB_PATH}/*.cxx - ${LIB_PATH}/*.h - ${LIB_PATH}/*.hh - ${LIB_PATH}/*.hxx) - - if(RECURSE) - file(GLOB_RECURSE LIB_FILES ${FILE_SEARCH_LIST}) - else() - file(GLOB LIB_FILES ${FILE_SEARCH_LIST}) - endif() - - if(LIB_FILES) - set(${VAR_NAME} ${LIB_FILES} PARENT_SCOPE) - endif() endfunction() #=============================================================================# +# setup_serial_target # [PRIVATE/INTERNAL] # # setup_serial_target(TARGET_NAME CMD) @@ -1446,161 +1684,494 @@ endfunction() function(setup_serial_target TARGET_NAME CMD SERIAL_PORT) string(CONFIGURE "${CMD}" FULL_CMD @ONLY) add_custom_target(${TARGET_NAME}-serial - COMMAND ${FULL_CMD}) + COMMAND ${FULL_CMD}) endfunction() +#=============================================================================# +# setup_arduino_example +# [PRIVATE/INTERNAL] +# +# setup_arduino_example(TARGET_NAME EXAMPLE_NAME OUTPUT_VAR [CATEGORY_NAME]) +# +# TARGET_NAME - Target name +# EXAMPLE_NAME - Example name +# OUTPUT_VAR - Variable name to save sketch path. +# [CATEGORY_NAME] - Optional name of the example's parent category, such as 'Basics' is for 'Blink'. +# +# Creates an Arduino example from the built-in categories. +#=============================================================================# +function(SETUP_ARDUINO_EXAMPLE TARGET_NAME EXAMPLE_NAME OUTPUT_VAR) + + set(OPTIONAL_ARGUMENTS ${ARGN}) + list(LENGTH OPTIONAL_ARGUMENTS ARGC) + if (${ARGC} GREATER 0) + list(GET OPTIONAL_ARGUMENTS 0 CATEGORY_NAME) + endif () + + # Case-insensitive support + string(TOLOWER ${EXAMPLE_NAME} EXAMPLE_NAME) + + if (CATEGORY_NAME) + + string(TOLOWER ${CATEGORY_NAME} CATEGORY_NAME) + list(FIND ARDUINO_EXAMPLES_CATEGORIES ${CATEGORY_NAME} CATEGORY_INDEX) + if (${CATEGORY_INDEX} LESS 0) + message(SEND_ERROR "${CATEGORY_NAME} example category doesn't exist, please check your spelling") + return() + endif () + INCREMENT_EXAMPLE_CATEGORY_INDEX(CATEGORY_INDEX) + set(CATEGORY_NAME ${CATEGORY_INDEX}.${CATEGORY_NAME}) + file(GLOB EXAMPLES RELATIVE ${ARDUINO_EXAMPLES_PATH}/${CATEGORY_NAME} + ${ARDUINO_EXAMPLES_PATH}/${CATEGORY_NAME}/*) + foreach (EXAMPLE_PATH ${EXAMPLES}) + string(TOLOWER ${EXAMPLE_PATH} EXAMPLE_PATH) + if (${EXAMPLE_PATH} STREQUAL ${EXAMPLE_NAME}) + set(EXAMPLE_SKETCH_PATH + "${ARDUINO_EXAMPLES_PATH}/${CATEGORY_NAME}/${EXAMPLE_NAME}") + break() + endif () + endforeach () + + else () + + file(GLOB CATEGORIES RELATIVE ${ARDUINO_EXAMPLES_PATH} ${ARDUINO_EXAMPLES_PATH}/*) + foreach (CATEGORY_PATH ${CATEGORIES}) + file(GLOB EXAMPLES RELATIVE ${ARDUINO_EXAMPLES_PATH}/${CATEGORY_PATH} + ${ARDUINO_EXAMPLES_PATH}/${CATEGORY_PATH}/*) + foreach (EXAMPLE_PATH ${EXAMPLES}) + string(TOLOWER ${EXAMPLE_PATH} EXAMPLE_PATH) + if (${EXAMPLE_PATH} STREQUAL ${EXAMPLE_NAME}) + set(EXAMPLE_SKETCH_PATH + "${ARDUINO_EXAMPLES_PATH}/${CATEGORY_PATH}/${EXAMPLE_NAME}") + break() + endif () + endforeach () + endforeach () + + endif () + + if (EXAMPLE_SKETCH_PATH) + setup_arduino_sketch(${TARGET_NAME} ${EXAMPLE_SKETCH_PATH} SKETCH_CPP) + set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) + else () + message(FATAL_ERROR "Could not find example ${EXAMPLE_NAME}") + endif () + +endfunction() #=============================================================================# +# setup_arduino_library_example # [PRIVATE/INTERNAL] # -# detect_arduino_version(VAR_NAME) +# setup_arduino_library_example(TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) # -# VAR_NAME - Variable name where the detected version will be saved +# TARGET_NAME - Target name +# LIBRARY_NAME - Library name +# EXAMPLE_NAME - Example name +# OUTPUT_VAR - Variable name to save sketch path. # -# Detects the Arduino SDK Version based on the revisions.txt file. The -# following variables will be generated: +# Creates a Arduino example from the specified library. +#=============================================================================# +function(SETUP_ARDUINO_LIBRARY_EXAMPLE TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) + set(EXAMPLE_SKETCH_PATH) + + get_property(LIBRARY_SEARCH_PATH + DIRECTORY # Property Scope + PROPERTY LINK_DIRECTORIES) + foreach (LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} + ${ARDUINO_PLATFORM_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libraries) + if (EXISTS "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") + set(EXAMPLE_SKETCH_PATH "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") + break() + endif () + endforeach () + + if (EXAMPLE_SKETCH_PATH) + setup_arduino_sketch(${TARGET_NAME} ${EXAMPLE_SKETCH_PATH} SKETCH_CPP) + set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) + else () + message(FATAL_ERROR "Could not find example ${EXAMPLE_NAME} from library ${LIBRARY_NAME}") + endif () +endfunction() + +#=============================================================================# +# setup_arduino_sketch +# [PRIVATE/INTERNAL] # -# ${VAR_NAME} -> the full version (major.minor.patch) -# ${VAR_NAME}_MAJOR -> the major version -# ${VAR_NAME}_MINOR -> the minor version -# ${VAR_NAME}_PATCH -> the patch version +# setup_arduino_sketch(TARGET_NAME SKETCH_PATH OUTPUT_VAR) # +# TARGET_NAME - Target name +# SKETCH_PATH - Path to sketch directory +# OUTPUT_VAR - Variable name where to save generated sketch source +# +# Generates C++ sources from Arduino Sketch. #=============================================================================# -function(detect_arduino_version VAR_NAME) - if(ARDUINO_VERSION_PATH) - file(READ ${ARDUINO_VERSION_PATH} RAW_VERSION) - if("${RAW_VERSION}" MATCHES " *[0]+([0-9]+)") - set(PARSED_VERSION 0.${CMAKE_MATCH_1}.0) - elseif("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+[.][0-9]+)") - set(PARSED_VERSION ${CMAKE_MATCH_1}) - elseif("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+)") - set(PARSED_VERSION ${CMAKE_MATCH_1}.0) - endif() +function(SETUP_ARDUINO_SKETCH TARGET_NAME SKETCH_PATH OUTPUT_VAR) + get_filename_component(SKETCH_NAME "${SKETCH_PATH}" NAME) + get_filename_component(SKETCH_PATH "${SKETCH_PATH}" ABSOLUTE) - if(NOT PARSED_VERSION STREQUAL "") - string(REPLACE "." ";" SPLIT_VERSION ${PARSED_VERSION}) - list(GET SPLIT_VERSION 0 SPLIT_VERSION_MAJOR) - list(GET SPLIT_VERSION 1 SPLIT_VERSION_MINOR) - list(GET SPLIT_VERSION 2 SPLIT_VERSION_PATCH) + if (EXISTS "${SKETCH_PATH}") + set(SKETCH_CPP ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_${SKETCH_NAME}.cpp) - set(${VAR_NAME} "${PARSED_VERSION}" PARENT_SCOPE) - set(${VAR_NAME}_MAJOR "${SPLIT_VERSION_MAJOR}" PARENT_SCOPE) - set(${VAR_NAME}_MINOR "${SPLIT_VERSION_MINOR}" PARENT_SCOPE) - set(${VAR_NAME}_PATCH "${SPLIT_VERSION_PATCH}" PARENT_SCOPE) - endif() + # Find all sketch files + file(GLOB SKETCH_SOURCES ${SKETCH_PATH}/*.pde ${SKETCH_PATH}/*.ino) + list(LENGTH SKETCH_SOURCES NUMBER_OF_SOURCES) + if (NUMBER_OF_SOURCES LESS 0) # Sketch sources not found + message(FATAL_ERROR "Could not find sketch + (${SKETCH_NAME}.pde or ${SKETCH_NAME}.ino) at ${SKETCH_PATH}! + Please specify the main sketch file path instead of directory.") + endif () + list(SORT SKETCH_SOURCES) + message(STATUS "SKETCH_SOURCES: ${SKETCH_SOURCES}") + + #generate_cpp_from_sketch("" "${SKETCH_SOURCES}" "${SKETCH_CPP}") + generate_sketch_cpp(${SKETCH_SOURCES} ${SKETCH_CPP}) + + # Regenerate build system if sketch changes + add_custom_command(OUTPUT ${SKETCH_CPP} + COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${MAIN_SKETCH} ${SKETCH_SOURCES} + COMMENT "Regnerating ${SKETCH_NAME} Sketch") + set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED TRUE) + # Mark file that it exists for find_file + set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED_SKETCH TRUE) + + set(${OUTPUT_VAR} ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) + else () + message(FATAL_ERROR "Sketch does not exist: ${SKETCH_PATH}") + endif () +endfunction() + +#=============================================================================# +# setup_arduino_size_script +# [PRIVATE/INTERNAL] +# +# setup_arduino_size_script(OUTPUT_VAR) +# +# OUTPUT_VAR - Output variable that will contain the script path +# +# Generates script used to display the firmware size. +#=============================================================================# +function(SETUP_ARDUINO_SIZE_SCRIPT OUTPUT_VAR) + set(ARDUINO_SIZE_SCRIPT_PATH ${CMAKE_BINARY_DIR}/CMakeFiles/FirmwareSize.cmake) + + file(WRITE ${ARDUINO_SIZE_SCRIPT_PATH} + "set(AVRSIZE_PROGRAM \"${AVRSIZE_PROGRAM}\") +set(AVRSIZE_FLAGS -C --mcu=\${MCU}) +execute_process(COMMAND \${AVRSIZE_PROGRAM} \${AVRSIZE_FLAGS} \${FIRMWARE_IMAGE} \${EEPROM_IMAGE} +OUTPUT_VARIABLE SIZE_OUTPUT) + +string(STRIP \"\${SIZE_OUTPUT}\" RAW_SIZE_OUTPUT) + +# Convert lines into a list +string(REPLACE \"\\n\" \";\" SIZE_OUTPUT_LIST \"\${SIZE_OUTPUT}\") + +set(SIZE_OUTPUT_LINES) +foreach(LINE \${SIZE_OUTPUT_LIST}) + if(NOT \"\${LINE}\" STREQUAL \"\") + list(APPEND SIZE_OUTPUT_LINES \"\${LINE}\") + endif() +endforeach() + +function(EXTRACT LIST_NAME INDEX VARIABLE) + list(GET \"\${LIST_NAME}\" \${INDEX} RAW_VALUE) + string(STRIP \"\${RAW_VALUE}\" VALUE) + set(\${VARIABLE} \"\${VALUE}\" PARENT_SCOPE) +endfunction() + +function(PARSE INPUT VARIABLE_PREFIX) + if(\${INPUT} MATCHES \"([^:]+):[ \\t]*([0-9]+)[ \\t]*([^ \\t]+)[ \\t]*[(]([0-9.]+)%.*\") + set(ENTRY_NAME \${CMAKE_MATCH_1}) + set(ENTRY_SIZE \${CMAKE_MATCH_2}) + set(ENTRY_SIZE_TYPE \${CMAKE_MATCH_3}) + set(ENTRY_PERCENT \${CMAKE_MATCH_4}) + endif() + + set(\${VARIABLE_PREFIX}_NAME \${ENTRY_NAME} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_SIZE \${ENTRY_SIZE} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_SIZE_TYPE \${ENTRY_SIZE_TYPE} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_PERCENT \${ENTRY_PERCENT} PARENT_SCOPE) +endfunction() + +list(LENGTH SIZE_OUTPUT_LINES SIZE_OUTPUT_LENGTH) + +#message(\"\${SIZE_OUTPUT_LINES}\") +#message(\"\${SIZE_OUTPUT_LENGTH}\") + +if (\${SIZE_OUTPUT_LENGTH} STREQUAL 14) + EXTRACT(SIZE_OUTPUT_LINES 3 FIRMWARE_PROGRAM_SIZE_ROW) + EXTRACT(SIZE_OUTPUT_LINES 5 FIRMWARE_DATA_SIZE_ROW) + PARSE(FIRMWARE_PROGRAM_SIZE_ROW FIRMWARE_PROGRAM) + PARSE(FIRMWARE_DATA_SIZE_ROW FIRMWARE_DATA) + + set(FIRMWARE_STATUS \"Firmware Size: \") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_PROGRAM_NAME}: \${FIRMWARE_PROGRAM_SIZE} \${FIRMWARE_PROGRAM_SIZE_TYPE} (\${FIRMWARE_PROGRAM_PERCENT}%)] \") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_DATA_NAME}: \${FIRMWARE_DATA_SIZE} \${FIRMWARE_DATA_SIZE_TYPE} (\${FIRMWARE_DATA_PERCENT}%)]\") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} on \${MCU}\") + + EXTRACT(SIZE_OUTPUT_LINES 10 EEPROM_PROGRAM_SIZE_ROW) + EXTRACT(SIZE_OUTPUT_LINES 12 EEPROM_DATA_SIZE_ROW) + PARSE(EEPROM_PROGRAM_SIZE_ROW EEPROM_PROGRAM) + PARSE(EEPROM_DATA_SIZE_ROW EEPROM_DATA) + + set(EEPROM_STATUS \"EEPROM Size: \") + set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_PROGRAM_NAME}: \${EEPROM_PROGRAM_SIZE} \${EEPROM_PROGRAM_SIZE_TYPE} (\${EEPROM_PROGRAM_PERCENT}%)] \") + set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_DATA_NAME}: \${EEPROM_DATA_SIZE} \${EEPROM_DATA_SIZE_TYPE} (\${EEPROM_DATA_PERCENT}%)]\") + set(EEPROM_STATUS \"\${EEPROM_STATUS} on \${MCU}\") + + message(\"\${FIRMWARE_STATUS}\") + message(\"\${EEPROM_STATUS}\\n\") + + if(\$ENV{VERBOSE}) + message(\"\${RAW_SIZE_OUTPUT}\\n\") + elseif(\$ENV{VERBOSE_SIZE}) + message(\"\${RAW_SIZE_OUTPUT}\\n\") endif() +else() + message(\"\${RAW_SIZE_OUTPUT}\") +endif()") + + set(${OUTPUT_VAR} ${ARDUINO_SIZE_SCRIPT_PATH} PARENT_SCOPE) endfunction() #=============================================================================# +# Find Functions +#=============================================================================# + +#=============================================================================# +# find_arduino_libraries # [PRIVATE/INTERNAL] # -# load_arduino_style_settings(SETTINGS_LIST SETTINGS_PATH) +# find_arduino_libraries(VAR_NAME SRCS ARDLIBS) # -# SETTINGS_LIST - Variable name of settings list -# SETTINGS_PATH - File path of settings file to load. +# VAR_NAME - Variable name which will hold the results +# SRCS - Sources that will be analized +# ARDLIBS - Arduino libraries identified by name (e.g., Wire, SPI, Servo) # -# Load a Arduino style settings file into the cache. -# -# Examples of this type of settings file is the boards.txt and -# programmers.txt files located in ${ARDUINO_SDK}/hardware/arduino. +# returns a list of paths to libraries found. # -# Settings have to following format: +# Finds all Arduino type libraries included in sources. Available libraries +# are ${ARDUINO_SDK_PATH}/libraries and ${CMAKE_CURRENT_SOURCE_DIR}. # -# entry.setting[.subsetting] = value +# Also adds Arduino libraries specifically names in ALIBS. We add ".h" to the +# names and then process them just like the Arduino libraries found in the sources. # -# where [.subsetting] is optional +# A Arduino library is a folder that has the same name as the include header. +# For example, if we have a include "#include " then the following +# directory structure is considered a Arduino library: # -# For example, the following settings: +# LibraryName/ +# |- LibraryName.h +# `- LibraryName.c # -# uno.name=Arduino Uno -# uno.upload.protocol=stk500 -# uno.upload.maximum_size=32256 -# uno.build.mcu=atmega328p -# uno.build.core=arduino +# If such a directory is found then all sources within that directory are considred +# to be part of that Arduino library. # -# will generate the follwoing equivalent CMake variables: +#=============================================================================# +function(find_arduino_libraries VAR_NAME SRCS ARDLIBS) + set(ARDUINO_LIBS) + + if (ARDLIBS) # Libraries are known in advance, just find their absoltue paths + + foreach (LIB ${ARDLIBS}) + get_property(LIBRARY_SEARCH_PATH + DIRECTORY # Property Scope + PROPERTY LINK_DIRECTORIES) + + foreach (LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} + ${ARDUINO_LIBRARIES_PATH} + ${ARDUINO_PLATFORM_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libraries) + + if (EXISTS ${LIB_SEARCH_PATH}/${LIB}/${LIB}.h) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${LIB}) + break() + endif () + if (EXISTS ${LIB_SEARCH_PATH}/${LIB}.h) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}) + break() + endif () + + # Some libraries like Wire and SPI require building from source + if (EXISTS ${LIB_SEARCH_PATH}/${LIB}/src/${LIB}.h) + message(STATUS "avr library found: ${LIB}") + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${LIB}/src) + break() + endif () + if (EXISTS ${LIB_SEARCH_PATH}/src/${LIB}.h) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/src) + break() + endif () + + endforeach () + endforeach () + + else () + + foreach (SRC ${SRCS}) + + # Skipping generated files. They are, probably, not exist yet. + # TODO: Maybe it's possible to skip only really nonexisting files, + # but then it wiil be less deterministic. + get_source_file_property(_srcfile_generated ${SRC} GENERATED) + # Workaround for sketches, which are marked as generated + get_source_file_property(_sketch_generated ${SRC} GENERATED_SKETCH) + + if (NOT ${_srcfile_generated} OR ${_sketch_generated}) + if (NOT (EXISTS ${SRC} OR + EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} OR + EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${SRC})) + message(FATAL_ERROR "Invalid source file: ${SRC}") + endif () + file(STRINGS ${SRC} SRC_CONTENTS) + + foreach (LIBNAME ${ARDLIBS}) + list(APPEND SRC_CONTENTS "#include <${LIBNAME}.h>") + endforeach () + + foreach (SRC_LINE ${SRC_CONTENTS}) + if ("${SRC_LINE}" MATCHES + "^[ \t]*#[ \t]*include[ \t]*[<\"]([^>\"]*)[>\"]") + + get_filename_component(INCLUDE_NAME ${CMAKE_MATCH_1} NAME_WE) + get_property(LIBRARY_SEARCH_PATH + DIRECTORY # Property Scope + PROPERTY LINK_DIRECTORIES) + foreach (LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} ${ARDUINO_PLATFORM_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libraries ${ARDUINO_EXTRA_LIBRARIES_PATH}) + if (EXISTS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}) + break() + endif () + if (EXISTS ${LIB_SEARCH_PATH}/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}) + break() + endif () + + # Some libraries like Wire and SPI require building from source + if (EXISTS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/src/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/src) + break() + endif () + if (EXISTS ${LIB_SEARCH_PATH}/src/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/src) + break() + endif () + endforeach () + + endif () + endforeach () + + endif () + endforeach () + + endif () + + if (ARDUINO_LIBS) + list(REMOVE_DUPLICATES ARDUINO_LIBS) + endif () + set(${VAR_NAME} ${ARDUINO_LIBS} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# find_sources +# [PRIVATE/INTERNAL] # -# set(uno.name "Arduino Uno") -# set(uno.upload.protocol "stk500") -# set(uno.upload.maximum_size "32256") -# set(uno.build.mcu "atmega328p") -# set(uno.build.core "arduino") +# find_sources(VAR_NAME LIB_PATH RECURSE) # -# set(uno.SETTINGS name upload build) # List of settings for uno -# set(uno.upload.SUBSETTINGS protocol maximum_size) # List of sub-settings for uno.upload -# set(uno.build.SUBSETTINGS mcu core) # List of sub-settings for uno.build -# -# The ${ENTRY_NAME}.SETTINGS variable lists all settings for the entry, while -# ${ENTRY_NAME}.SUBSETTINGS variables lists all settings for a sub-setting of -# a entry setting pair. +# VAR_NAME - Variable name that will hold the detected sources +# LIB_PATH - The base path +# RECURSE - Whether or not to recurse # -# These variables are generated in order to be able to programatically traverse -# all settings (for a example see print_board_settings() function). +# Finds all C/C++ sources located at the specified path. # #=============================================================================# -function(LOAD_ARDUINO_STYLE_SETTINGS SETTINGS_LIST SETTINGS_PATH) +function(find_sources VAR_NAME LIB_PATH RECURSE) + set(FILE_SEARCH_LIST + ${LIB_PATH}/*.cpp + ${LIB_PATH}/*.c + ${LIB_PATH}/*.cc + ${LIB_PATH}/*.cxx + ${LIB_PATH}/*.h + ${LIB_PATH}/*.hh + ${LIB_PATH}/*.hxx) + + if (RECURSE) + file(GLOB_RECURSE LIB_FILES ${FILE_SEARCH_LIST}) + else () + file(GLOB LIB_FILES ${FILE_SEARCH_LIST}) + endif () - if(NOT ${SETTINGS_LIST} AND EXISTS ${SETTINGS_PATH}) - file(STRINGS ${SETTINGS_PATH} FILE_ENTRIES) # Settings file split into lines - - foreach(FILE_ENTRY ${FILE_ENTRIES}) - if("${FILE_ENTRY}" MATCHES "^[^#]+=.*") - string(REGEX MATCH "^[^=]+" SETTING_NAME ${FILE_ENTRY}) - string(REGEX MATCH "[^=]+$" SETTING_VALUE ${FILE_ENTRY}) - string(REPLACE "." ";" ENTRY_NAME_TOKENS ${SETTING_NAME}) - string(STRIP "${SETTING_VALUE}" SETTING_VALUE) - - list(LENGTH ENTRY_NAME_TOKENS ENTRY_NAME_TOKENS_LEN) - - # Add entry to settings list if it does not exist - list(GET ENTRY_NAME_TOKENS 0 ENTRY_NAME) - list(FIND ${SETTINGS_LIST} ${ENTRY_NAME} ENTRY_NAME_INDEX) - if(ENTRY_NAME_INDEX LESS 0) - # Add entry to main list - list(APPEND ${SETTINGS_LIST} ${ENTRY_NAME}) - endif() - - # Add entry setting to entry settings list if it does not exist - set(ENTRY_SETTING_LIST ${ENTRY_NAME}.SETTINGS) - list(GET ENTRY_NAME_TOKENS 1 ENTRY_SETTING) - list(FIND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING} ENTRY_SETTING_INDEX) - if(ENTRY_SETTING_INDEX LESS 0) - # Add setting to entry - list(APPEND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING}) - set(${ENTRY_SETTING_LIST} ${${ENTRY_SETTING_LIST}} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board settings list") - endif() - - set(FULL_SETTING_NAME ${ENTRY_NAME}.${ENTRY_SETTING}) - - # Add entry sub-setting to entry sub-settings list if it does not exists - if(ENTRY_NAME_TOKENS_LEN GREATER 2) - set(ENTRY_SUBSETTING_LIST ${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) - list(GET ENTRY_NAME_TOKENS 2 ENTRY_SUBSETTING) - list(FIND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING} ENTRY_SUBSETTING_INDEX) - if(ENTRY_SUBSETTING_INDEX LESS 0) - list(APPEND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING}) - set(${ENTRY_SUBSETTING_LIST} ${${ENTRY_SUBSETTING_LIST}} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board sub-settings list") - endif() - set(FULL_SETTING_NAME ${FULL_SETTING_NAME}.${ENTRY_SUBSETTING}) - endif() - - # Save setting value - set(${FULL_SETTING_NAME} ${SETTING_VALUE} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board setting") - - - endif() - endforeach() - set(${SETTINGS_LIST} ${${SETTINGS_LIST}} - CACHE STRING "List of detected Arduino Board configurations") - mark_as_advanced(${SETTINGS_LIST}) - endif() + if (LIB_FILES) + set(${VAR_NAME} ${LIB_FILES} PARENT_SCOPE) + endif () endfunction() #=============================================================================# +# find_prototypes +# [PRIVATE/INTERNAL] +# +# find_sources(VAR_NAME LIB_PATH RECURSE) +# +# SEARCH_SOURCES - List of source files to search prototypes in +# OUTPUT_VAR - Output variable that will contain the list of found prototypes +# +# Find all function prototypes in the given source files +# +#=============================================================================# +function(find_prototypes SEARCH_SOURCES OUTPUT_VAR) + + if (ARGC GREATER 2) + list(GET ARGN 0 PROTOTYPE_PATTERN) + else () + set(ALPHA "a-zA-Z") + set(NUM "0-9") + set(ALPHANUM "${ALPHA}${NUM}") + set(WORD "_${ALPHANUM}") + set(LINE_START "(^|[\n])") + set(QUALIFIERS "[ \t]*([${ALPHA}]+[ ])*") + set(TYPE "[${WORD}]+([ ]*[\n][\t]*|[ ])+") + set(FNAME "[${WORD}]+[ ]?[\n]?[\t]*[ ]*") + set(FARGS "[(]([\t]*[ ]*[*&]?[ ]?[${WORD}](\\[([${NUM}]+)?\\])*[,]?[ ]*[\n]?)*([,]?[ ]*[\n]?)?[)]") + set(BODY_START "([ ]*[\n][\t]*|[ ]|[\n])*{") + set(PROTOTYPE_PATTERN "${LINE_START}${QUALIFIERS}${TYPE}${FNAME}${FARGS}${BODY_START}") + endif () + + find_sources(SEARCH_SOURCES ${SEARCH_SOURCES} False) + foreach (SOURCE ${SEARCH_SOURCES}) + ARDUINO_DEBUG_MSG("Prototype search source: ${SOURCE}") + file(READ ${SOURCE} SOURCE) + remove_comments(SOURCE SOURCE) + string(REGEX MATCHALL ${PROTOTYPE_PATTERN} SOURCE_PROTOTYPES ${SOURCE}) + ARDUINO_DEBUG_MSG("Prototypes: ${SOURCE_PROTOTYPES}") + foreach (PROTOTYPE ${SOURCE_PROTOTYPES}) + string(REPLACE "\n" " " SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") + string(REPLACE "{" "" SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") + # " else if(var == other) {" shoudn't be listed as prototype + if (NOT SKETCH_PROTOTYPE MATCHES "(if[ ]?[\n]?[\t]*[ ]*[)])") + list(APPEND PROTOTYPES "${SKETCH_PROTOTYPE}") + else () + arduino_debug_msg("\trejected prototype: ${PROTOTYPE};") + endif () + endforeach () + endforeach () + + list(REMOVE_DUPLICATES PROTOTYPES) + set(${OUTPUT_VAR} ${PROTOTYPES} PARENT_SCOPE) + +endfunction() + + +#=============================================================================# +# Print Functions +#=============================================================================# + +#=============================================================================# +# print_settings +# [PRIVATE/INTERNAL] +# # print_settings(ENTRY_NAME) # # ENTRY_NAME - name of entry @@ -1609,25 +2180,26 @@ endfunction() # #=============================================================================# function(PRINT_SETTINGS ENTRY_NAME) - if(${ENTRY_NAME}.SETTINGS) + if (${ENTRY_NAME}.SETTINGS) - foreach(ENTRY_SETTING ${${ENTRY_NAME}.SETTINGS}) - if(${ENTRY_NAME}.${ENTRY_SETTING}) + foreach (ENTRY_SETTING ${${ENTRY_NAME}.SETTINGS}) + if (${ENTRY_NAME}.${ENTRY_SETTING}) message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}}") - endif() - if(${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) - foreach(ENTRY_SUBSETTING ${${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS}) - if(${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}) + endif () + if (${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) + foreach (ENTRY_SUBSETTING ${${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS}) + if (${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}) message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}}") - endif() - endforeach() - endif() + endif () + endforeach () + endif () message(STATUS "") - endforeach() - endif() + endforeach () + endif () endfunction() #=============================================================================# +# print_list # [PRIVATE/INTERNAL] # # print_list(SETTINGS_LIST) @@ -1637,154 +2209,168 @@ endfunction() # Print list settings and names (see load_arduino_syle_settings()). #=============================================================================# function(PRINT_LIST SETTINGS_LIST) - if(${SETTINGS_LIST}) + if (${SETTINGS_LIST}) set(MAX_LENGTH 0) - foreach(ENTRY_NAME ${${SETTINGS_LIST}}) + foreach (ENTRY_NAME ${${SETTINGS_LIST}}) string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) - if(CURRENT_LENGTH GREATER MAX_LENGTH) + if (CURRENT_LENGTH GREATER MAX_LENGTH) set(MAX_LENGTH ${CURRENT_LENGTH}) - endif() - endforeach() - foreach(ENTRY_NAME ${${SETTINGS_LIST}}) + endif () + endforeach () + foreach (ENTRY_NAME ${${SETTINGS_LIST}}) string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) math(EXPR PADDING_LENGTH "${MAX_LENGTH}-${CURRENT_LENGTH}") set(PADDING "") - foreach(X RANGE ${PADDING_LENGTH}) + foreach (X RANGE ${PADDING_LENGTH}) set(PADDING "${PADDING} ") - endforeach() + endforeach () message(STATUS " ${PADDING}${ENTRY_NAME}: ${${ENTRY_NAME}.name}") - endforeach() - endif() + endforeach () + endif () endfunction() + +#=============================================================================# +# Other Functions +#=============================================================================# + #=============================================================================# +# get_arduino_flags # [PRIVATE/INTERNAL] # -# setup_arduino_example(TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) +# get_arduino_flags(COMPILE_FLAGS LINK_FLAGS BOARD_ID MANUAL) # -# TARGET_NAME - Target name -# LIBRARY_NAME - Library name -# EXAMPLE_NAME - Example name -# OUTPUT_VAR - Variable name to save sketch path. +# COMPILE_FLAGS_VAR -Variable holding compiler flags +# LINK_FLAGS_VAR - Variable holding linker flags +# BOARD_ID - The board id name +# MANUAL - (Advanced) Only use AVR Libc/Includes +# +# Configures the the build settings for the specified Arduino Board. # -# Creates a Arduino example from a the specified library. #=============================================================================# -function(SETUP_ARDUINO_EXAMPLE TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) - set(EXAMPLE_SKETCH_PATH ) +function(get_arduino_flags COMPILE_FLAGS_VAR LINK_FLAGS_VAR BOARD_ID MANUAL) - get_property(LIBRARY_SEARCH_PATH - DIRECTORY # Property Scope - PROPERTY LINK_DIRECTORIES) - foreach(LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libraries) - if(EXISTS "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") - set(EXAMPLE_SKETCH_PATH "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") - break() - endif() - endforeach() + set(BOARD_CORE ${${BOARD_ID}.build.core}) + if (BOARD_CORE) + if (ARDUINO_SDK_VERSION MATCHES "([0-9]+)[.]([0-9]+)") + string(REPLACE "." "" ARDUINO_VERSION_DEFINE "${ARDUINO_SDK_VERSION}") # Normalize version (remove all periods) + set(ARDUINO_VERSION_DEFINE "") + if (CMAKE_MATCH_1 GREATER 0) + set(ARDUINO_VERSION_DEFINE "${CMAKE_MATCH_1}") + endif () + if (CMAKE_MATCH_2 GREATER 10) + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}${CMAKE_MATCH_2}") + else () + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}0${CMAKE_MATCH_2}") + endif () + else () + message("Invalid Arduino SDK Version (${ARDUINO_SDK_VERSION})") + endif () - if(EXAMPLE_SKETCH_PATH) - setup_arduino_sketch(${TARGET_NAME} ${EXAMPLE_SKETCH_PATH} SKETCH_CPP) - set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) - else() - message(FATAL_ERROR "Could not find example ${EXAMPLE_NAME} from library ${LIBRARY_NAME}") - endif() + # output + set(COMPILE_FLAGS "-DF_CPU=${${BOARD_ID}.build.f_cpu} -DARDUINO=${ARDUINO_VERSION_DEFINE} -mmcu=${${BOARD_ID}.build.mcu}") + if (DEFINED ${BOARD_ID}.build.vid) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_VID=${${BOARD_ID}.build.vid}") + endif () + if (DEFINED ${BOARD_ID}.build.pid) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_PID=${${BOARD_ID}.build.pid}") + endif () + if (NOT MANUAL) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${${BOARD_CORE}.path}\" -I\"${ARDUINO_LIBRARIES_PATH}\" -I\"${ARDUINO_PLATFORM_LIBRARIES_PATH}\" ") + endif () + set(LINK_FLAGS "-mmcu=${${BOARD_ID}.build.mcu}") + if (ARDUINO_SDK_VERSION VERSION_GREATER 1.0 OR ARDUINO_SDK_VERSION VERSION_EQUAL 1.0) + if (NOT MANUAL) + set(PIN_HEADER ${${${BOARD_ID}.build.variant}.path}) + if (PIN_HEADER) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${PIN_HEADER}\"") + endif () + endif () + endif () + + # output + set(${COMPILE_FLAGS_VAR} "${COMPILE_FLAGS}" PARENT_SCOPE) + set(${LINK_FLAGS_VAR} "${LINK_FLAGS}" PARENT_SCOPE) + + else () + message(FATAL_ERROR "Invalid Arduino board ID (${BOARD_ID}), aborting.") + endif () endfunction() #=============================================================================# +# detect_arduino_version # [PRIVATE/INTERNAL] # -# setup_arduino_sketch(TARGET_NAME SKETCH_PATH OUTPUT_VAR) +# detect_arduino_version(VAR_NAME) # -# TARGET_NAME - Target name -# SKETCH_PATH - Path to sketch directory -# OUTPUT_VAR - Variable name where to save generated sketch source +# VAR_NAME - Variable name where the detected version will be saved +# +# Detects the Arduino SDK Version based on the revisions.txt file. The +# following variables will be generated: +# +# ${VAR_NAME} -> the full version (major.minor.patch) +# ${VAR_NAME}_MAJOR -> the major version +# ${VAR_NAME}_MINOR -> the minor version +# ${VAR_NAME}_PATCH -> the patch version # -# Generates C++ sources from Arduino Sketch. #=============================================================================# -function(SETUP_ARDUINO_SKETCH TARGET_NAME SKETCH_PATH OUTPUT_VAR) - get_filename_component(SKETCH_NAME "${SKETCH_PATH}" NAME) - get_filename_component(SKETCH_PATH "${SKETCH_PATH}" ABSOLUTE) - - if(EXISTS "${SKETCH_PATH}") - set(SKETCH_CPP ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_${SKETCH_NAME}.cpp) - - if (IS_DIRECTORY "${SKETCH_PATH}") - # Sketch directory specified, try to find main sketch... - set(MAIN_SKETCH ${SKETCH_PATH}/${SKETCH_NAME}) - - if(EXISTS "${MAIN_SKETCH}.pde") - set(MAIN_SKETCH "${MAIN_SKETCH}.pde") - elseif(EXISTS "${MAIN_SKETCH}.ino") - set(MAIN_SKETCH "${MAIN_SKETCH}.ino") - else() - message(FATAL_ERROR "Could not find main sketch (${SKETCH_NAME}.pde or ${SKETCH_NAME}.ino) at ${SKETCH_PATH}! Please specify the main sketch file path instead of directory.") - endif() - else() - # Sektch file specified, assuming parent directory as sketch directory - set(MAIN_SKETCH ${SKETCH_PATH}) - get_filename_component(SKETCH_PATH "${SKETCH_PATH}" PATH) - endif() - arduino_debug_msg("sketch: ${MAIN_SKETCH}") - - # Find all sketch files - file(GLOB SKETCH_SOURCES ${SKETCH_PATH}/*.pde ${SKETCH_PATH}/*.ino) - list(REMOVE_ITEM SKETCH_SOURCES ${MAIN_SKETCH}) - list(SORT SKETCH_SOURCES) - - generate_cpp_from_sketch("${MAIN_SKETCH}" "${SKETCH_SOURCES}" "${SKETCH_CPP}") +function(detect_arduino_version VAR_NAME) + if (ARDUINO_VERSION_PATH) + file(READ ${ARDUINO_VERSION_PATH} RAW_VERSION) + if ("${RAW_VERSION}" MATCHES " *[0]+([0-9]+)") + set(PARSED_VERSION 0.${CMAKE_MATCH_1}.0) + elseif ("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+[.][0-9]+)") + set(PARSED_VERSION ${CMAKE_MATCH_1}) + elseif ("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+)") + set(PARSED_VERSION ${CMAKE_MATCH_1}.0) + endif () - # Regenerate build system if sketch changes - add_custom_command(OUTPUT ${SKETCH_CPP} - COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${MAIN_SKETCH} ${SKETCH_SOURCES} - COMMENT "Regnerating ${SKETCH_NAME} Sketch") - set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED TRUE) - # Mark file that it exists for find_file - set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED_SKETCH TRUE) + if (NOT PARSED_VERSION STREQUAL "") + string(REPLACE "." ";" SPLIT_VERSION ${PARSED_VERSION}) + list(GET SPLIT_VERSION 0 SPLIT_VERSION_MAJOR) + list(GET SPLIT_VERSION 1 SPLIT_VERSION_MINOR) + list(GET SPLIT_VERSION 2 SPLIT_VERSION_PATCH) - set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) - else() - message(FATAL_ERROR "Sketch does not exist: ${SKETCH_PATH}") - endif() + set(${VAR_NAME} "${PARSED_VERSION}" PARENT_SCOPE) + set(${VAR_NAME}_MAJOR "${SPLIT_VERSION_MAJOR}" PARENT_SCOPE) + set(${VAR_NAME}_MINOR "${SPLIT_VERSION_MINOR}" PARENT_SCOPE) + set(${VAR_NAME}_PATCH "${SPLIT_VERSION_PATCH}" PARENT_SCOPE) + endif () + endif () endfunction() - #=============================================================================# +# generate_sketch_cpp # [PRIVATE/INTERNAL] # -# generate_cpp_from_sketch(MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) +# generate_sketch_cpp(MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) # -# MAIN_SKETCH_PATH - Main sketch file path # SKETCH_SOURCES - Setch source paths # SKETCH_CPP - Name of file to generate # # Generate C++ source file from Arduino sketch files. #=============================================================================# -function(GENERATE_CPP_FROM_SKETCH MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) +function(generate_sketch_cpp SKETCH_SOURCES SKETCH_CPP) file(WRITE ${SKETCH_CPP} "// automatically generated by arduino-cmake\n") - file(READ ${MAIN_SKETCH_PATH} MAIN_SKETCH) + list(GET SKETCH_SOURCES 0 MAIN_SKETCH) + file(READ ${MAIN_SKETCH} MAIN_SKETCH_CONTENT) # remove comments - remove_comments(MAIN_SKETCH MAIN_SKETCH_NO_COMMENTS) + remove_comments(MAIN_SKETCH_CONTENT MAIN_SKETCH_NO_COMMENTS) # find first statement string(REGEX MATCH "[\n][_a-zA-Z0-9]+[^\n]*" FIRST_STATEMENT "${MAIN_SKETCH_NO_COMMENTS}") - string(FIND "${MAIN_SKETCH}" "${FIRST_STATEMENT}" HEAD_LENGTH) + string(FIND "${MAIN_SKETCH_CONTENT}" "${FIRST_STATEMENT}" HEAD_LENGTH) if ("${HEAD_LENGTH}" STREQUAL "-1") set(HEAD_LENGTH 0) - endif() - #message(STATUS "FIRST STATEMENT: ${FIRST_STATEMENT}") - #message(STATUS "FIRST STATEMENT POSITION: ${HEAD_LENGTH}") - string(LENGTH "${MAIN_SKETCH}" MAIN_SKETCH_LENGTH) + endif () + string(LENGTH "${MAIN_SKETCH_CONTENT}" MAIN_SKETCH_LENGTH) - string(SUBSTRING "${MAIN_SKETCH}" 0 ${HEAD_LENGTH} SKETCH_HEAD) - #arduino_debug_msg("SKETCH_HEAD:\n${SKETCH_HEAD}") + string(SUBSTRING "${MAIN_SKETCH_CONTENT}" 0 ${HEAD_LENGTH} SKETCH_HEAD) # find the body of the main pde math(EXPR BODY_LENGTH "${MAIN_SKETCH_LENGTH}-${HEAD_LENGTH}") - string(SUBSTRING "${MAIN_SKETCH}" "${HEAD_LENGTH}+1" "${BODY_LENGTH}-1" SKETCH_BODY) - #arduino_debug_msg("BODY:\n${SKETCH_BODY}") + string(SUBSTRING "${MAIN_SKETCH_CONTENT}" "${HEAD_LENGTH}+1" "${BODY_LENGTH}-1" SKETCH_BODY) # write the file head file(APPEND ${SKETCH_CPP} "#line 1 \"${MAIN_SKETCH_PATH}\"\n${SKETCH_HEAD}") @@ -1795,198 +2381,28 @@ function(GENERATE_CPP_FROM_SKETCH MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) math(EXPR SKETCH_HEAD_OFFSET "${SKETCH_HEAD_LINES_COUNT}+2") # add arduino include header - #file(APPEND ${SKETCH_CPP} "\n#line 1 \"autogenerated\"\n") file(APPEND ${SKETCH_CPP} "\n#line ${SKETCH_HEAD_OFFSET} \"${SKETCH_CPP}\"\n") - if(ARDUINO_SDK_VERSION VERSION_LESS 1.0) + if (ARDUINO_SDK_VERSION VERSION_LESS 1.0) file(APPEND ${SKETCH_CPP} "#include \"WProgram.h\"\n") - else() + else () file(APPEND ${SKETCH_CPP} "#include \"Arduino.h\"\n") - endif() - - # add function prototypes - foreach(SKETCH_SOURCE_PATH ${SKETCH_SOURCES} ${MAIN_SKETCH_PATH}) - arduino_debug_msg("Sketch: ${SKETCH_SOURCE_PATH}") - file(READ ${SKETCH_SOURCE_PATH} SKETCH_SOURCE) - remove_comments(SKETCH_SOURCE SKETCH_SOURCE) - - set(ALPHA "a-zA-Z") - set(NUM "0-9") - set(ALPHANUM "${ALPHA}${NUM}") - set(WORD "_${ALPHANUM}") - set(LINE_START "(^|[\n])") - set(QUALIFIERS "[ \t]*([${ALPHA}]+[ ])*") - set(TYPE "[${WORD}]+([ ]*[\n][\t]*|[ ])+") - set(FNAME "[${WORD}]+[ ]?[\n]?[\t]*[ ]*") - set(FARGS "[(]([\t]*[ ]*[*&]?[ ]?[${WORD}](\\[([${NUM}]+)?\\])*[,]?[ ]*[\n]?)*([,]?[ ]*[\n]?)?[)]") - set(BODY_START "([ ]*[\n][\t]*|[ ]|[\n])*{") - set(PROTOTYPE_PATTERN "${LINE_START}${QUALIFIERS}${TYPE}${FNAME}${FARGS}${BODY_START}") + endif () - string(REGEX MATCHALL "${PROTOTYPE_PATTERN}" SKETCH_PROTOTYPES "${SKETCH_SOURCE}") - - # Write function prototypes - file(APPEND ${SKETCH_CPP} "\n//=== START Forward: ${SKETCH_SOURCE_PATH}\n") - foreach(SKETCH_PROTOTYPE ${SKETCH_PROTOTYPES}) - string(REPLACE "\n" " " SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") - string(REPLACE "{" "" SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") - arduino_debug_msg("\tprototype: ${SKETCH_PROTOTYPE};") - # " else if(var == other) {" shoudn't be listed as prototype - if(NOT SKETCH_PROTOTYPE MATCHES "(if[ ]?[\n]?[\t]*[ ]*[)])") - file(APPEND ${SKETCH_CPP} "${SKETCH_PROTOTYPE};\n") - else() - arduino_debug_msg("\trejected prototype: ${SKETCH_PROTOTYPE};") - endif() - file(APPEND ${SKETCH_CPP} "${SKETCH_PROTOTYPE};\n") - endforeach() - file(APPEND ${SKETCH_CPP} "//=== END Forward: ${SKETCH_SOURCE_PATH}\n") - endforeach() - - # Write Sketch CPP source get_num_lines("${SKETCH_HEAD}" HEAD_NUM_LINES) file(APPEND ${SKETCH_CPP} "#line ${HEAD_NUM_LINES} \"${MAIN_SKETCH_PATH}\"\n") file(APPEND ${SKETCH_CPP} "\n${SKETCH_BODY}") + list(REMOVE_ITEM SKETCH_SOURCES ${MAIN_SKETCH}) foreach (SKETCH_SOURCE_PATH ${SKETCH_SOURCES}) file(READ ${SKETCH_SOURCE_PATH} SKETCH_SOURCE) file(APPEND ${SKETCH_CPP} "\n//=== START : ${SKETCH_SOURCE_PATH}\n") file(APPEND ${SKETCH_CPP} "#line 1 \"${SKETCH_SOURCE_PATH}\"\n") file(APPEND ${SKETCH_CPP} "${SKETCH_SOURCE}") file(APPEND ${SKETCH_CPP} "\n//=== END : ${SKETCH_SOURCE_PATH}\n") - endforeach() -endfunction() - -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# setup_arduino_size_script(OUTPUT_VAR) -# -# OUTPUT_VAR - Output variable that will contain the script path -# -# Generates script used to display the firmware size. -#=============================================================================# -function(SETUP_ARDUINO_SIZE_SCRIPT OUTPUT_VAR) - set(ARDUINO_SIZE_SCRIPT_PATH ${CMAKE_BINARY_DIR}/CMakeFiles/FirmwareSize.cmake) - - file(WRITE ${ARDUINO_SIZE_SCRIPT_PATH} " - set(AVRSIZE_PROGRAM ${AVRSIZE_PROGRAM}) - set(AVRSIZE_FLAGS -C --mcu=\${MCU}) - - execute_process(COMMAND \${AVRSIZE_PROGRAM} \${AVRSIZE_FLAGS} \${FIRMWARE_IMAGE} \${EEPROM_IMAGE} - OUTPUT_VARIABLE SIZE_OUTPUT) - - - string(STRIP \"\${SIZE_OUTPUT}\" RAW_SIZE_OUTPUT) - - # Convert lines into a list - string(REPLACE \"\\n\" \";\" SIZE_OUTPUT_LIST \"\${SIZE_OUTPUT}\") - - set(SIZE_OUTPUT_LINES) - foreach(LINE \${SIZE_OUTPUT_LIST}) - if(NOT \"\${LINE}\" STREQUAL \"\") - list(APPEND SIZE_OUTPUT_LINES \"\${LINE}\") - endif() - endforeach() - - function(EXTRACT LIST_NAME INDEX VARIABLE) - list(GET \"\${LIST_NAME}\" \${INDEX} RAW_VALUE) - string(STRIP \"\${RAW_VALUE}\" VALUE) - - set(\${VARIABLE} \"\${VALUE}\" PARENT_SCOPE) - endfunction() - function(PARSE INPUT VARIABLE_PREFIX) - if(\${INPUT} MATCHES \"([^:]+):[ \\t]*([0-9]+)[ \\t]*([^ \\t]+)[ \\t]*[(]([0-9.]+)%.*\") - set(ENTRY_NAME \${CMAKE_MATCH_1}) - set(ENTRY_SIZE \${CMAKE_MATCH_2}) - set(ENTRY_SIZE_TYPE \${CMAKE_MATCH_3}) - set(ENTRY_PERCENT \${CMAKE_MATCH_4}) - endif() - - set(\${VARIABLE_PREFIX}_NAME \${ENTRY_NAME} PARENT_SCOPE) - set(\${VARIABLE_PREFIX}_SIZE \${ENTRY_SIZE} PARENT_SCOPE) - set(\${VARIABLE_PREFIX}_SIZE_TYPE \${ENTRY_SIZE_TYPE} PARENT_SCOPE) - set(\${VARIABLE_PREFIX}_PERCENT \${ENTRY_PERCENT} PARENT_SCOPE) - endfunction() - - list(LENGTH SIZE_OUTPUT_LINES SIZE_OUTPUT_LENGTH) - #message(\"\${SIZE_OUTPUT_LINES}\") - #message(\"\${SIZE_OUTPUT_LENGTH}\") - if (\${SIZE_OUTPUT_LENGTH} STREQUAL 14) - EXTRACT(SIZE_OUTPUT_LINES 3 FIRMWARE_PROGRAM_SIZE_ROW) - EXTRACT(SIZE_OUTPUT_LINES 5 FIRMWARE_DATA_SIZE_ROW) - PARSE(FIRMWARE_PROGRAM_SIZE_ROW FIRMWARE_PROGRAM) - PARSE(FIRMWARE_DATA_SIZE_ROW FIRMWARE_DATA) - - set(FIRMWARE_STATUS \"Firmware Size: \") - set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_PROGRAM_NAME}: \${FIRMWARE_PROGRAM_SIZE} \${FIRMWARE_PROGRAM_SIZE_TYPE} (\${FIRMWARE_PROGRAM_PERCENT}%)] \") - set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_DATA_NAME}: \${FIRMWARE_DATA_SIZE} \${FIRMWARE_DATA_SIZE_TYPE} (\${FIRMWARE_DATA_PERCENT}%)]\") - set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} on \${MCU}\") - - EXTRACT(SIZE_OUTPUT_LINES 10 EEPROM_PROGRAM_SIZE_ROW) - EXTRACT(SIZE_OUTPUT_LINES 12 EEPROM_DATA_SIZE_ROW) - PARSE(EEPROM_PROGRAM_SIZE_ROW EEPROM_PROGRAM) - PARSE(EEPROM_DATA_SIZE_ROW EEPROM_DATA) - - set(EEPROM_STATUS \"EEPROM Size: \") - set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_PROGRAM_NAME}: \${EEPROM_PROGRAM_SIZE} \${EEPROM_PROGRAM_SIZE_TYPE} (\${EEPROM_PROGRAM_PERCENT}%)] \") - set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_DATA_NAME}: \${EEPROM_DATA_SIZE} \${EEPROM_DATA_SIZE_TYPE} (\${EEPROM_DATA_PERCENT}%)]\") - set(EEPROM_STATUS \"\${EEPROM_STATUS} on \${MCU}\") - - message(\"\${FIRMWARE_STATUS}\") - message(\"\${EEPROM_STATUS}\\n\") - - if(\$ENV{VERBOSE}) - message(\"\${RAW_SIZE_OUTPUT}\\n\") - elseif(\$ENV{VERBOSE_SIZE}) - message(\"\${RAW_SIZE_OUTPUT}\\n\") - endif() - else() - message(\"\${RAW_SIZE_OUTPUT}\") - endif() - ") - - set(${OUTPUT_VAR} ${ARDUINO_SIZE_SCRIPT_PATH} PARENT_SCOPE) -endfunction() - - -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# arduino_debug_on() -# -# Enables Arduino module debugging. -#=============================================================================# -function(ARDUINO_DEBUG_ON) - set(ARDUINO_DEBUG True PARENT_SCOPE) -endfunction() - - -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# arduino_debug_off() -# -# Disables Arduino module debugging. -#=============================================================================# -function(ARDUINO_DEBUG_OFF) - set(ARDUINO_DEBUG False PARENT_SCOPE) -endfunction() - - -#=============================================================================# -# [PRIVATE/INTERNAL] -# -# arduino_debug_msg(MSG) -# -# MSG - Message to print -# -# Print Arduino debugging information. In order to enable printing -# use arduino_debug_on() and to disable use arduino_debug_off(). -#=============================================================================# -function(ARDUINO_DEBUG_MSG MSG) - if(ARDUINO_DEBUG) - message("## ${MSG}") - endif() + endforeach () endfunction() #=============================================================================# +# remove_comments # [PRIVATE/INTERNAL] # # remove_comments(SRC_VAR OUT_VAR) @@ -2006,7 +2422,8 @@ function(REMOVE_COMMENTS SRC_VAR OUT_VAR) #message(STATUS "\n${SRC}") # remove all comments - string(REGEX REPLACE "([/][/][^\n]*)|([/][\\*]([^\\*]|([\\*]+[^/\\*]))*[\\*]+[/])" "" OUT "${SRC}") + string(REGEX REPLACE "([/][/][^\n]*)|([/][\\*]([^\\*]|([\\*]+[^/\\*]))*[\\*]+[/])" + "" OUT "${SRC}") #file(WRITE "${CMAKE_BINARY_DIR}/${FILE}_post_remove_comments.txt" ${SRC}) #message(STATUS "\n${SRC}") @@ -2016,6 +2433,7 @@ function(REMOVE_COMMENTS SRC_VAR OUT_VAR) endfunction() #=============================================================================# +# get_num_lines # [PRIVATE/INTERNAL] # # get_num_lines(DOCUMENT OUTPUT_VAR) @@ -2032,6 +2450,7 @@ function(GET_NUM_LINES DOCUMENT OUTPUT_VAR) endfunction() #=============================================================================# +# required_variables # [PRIVATE/INTERNAL] # # required_variables(MSG msg VARS var1 var2 .. varN) @@ -2044,14 +2463,15 @@ endfunction() function(REQUIRED_VARIABLES) cmake_parse_arguments(INPUT "" "MSG" "VARS" ${ARGN}) error_for_unparsed(INPUT) - foreach(VAR ${INPUT_VARS}) + foreach (VAR ${INPUT_VARS}) if ("${${VAR}}" STREQUAL "") message(FATAL_ERROR "${VAR} not set: ${INPUT_MSG}") - endif() - endforeach() + endif () + endforeach () endfunction() #=============================================================================# +# error_for_unparsed # [PRIVATE/INTERNAL] # # error_for_unparsed(PREFIX) @@ -2062,26 +2482,71 @@ endfunction() #=============================================================================# function(ERROR_FOR_UNPARSED PREFIX) set(ARGS "${${PREFIX}_UNPARSED_ARGUMENTS}") - if (NOT ( "${ARGS}" STREQUAL "") ) + if (NOT ("${ARGS}" STREQUAL "")) message(FATAL_ERROR "unparsed argument: ${ARGS}") - endif() + endif () endfunction() +#=============================================================================# +# Debug Functions +#=============================================================================# + +#=============================================================================# +# arduino_debug_on() +# [PRIVATE/INTERNAL] +# +# arduino_debug_on() +# +# Enables Arduino module debugging. +#=============================================================================# +function(ARDUINO_DEBUG_ON) + set(ARDUINO_DEBUG True PARENT_SCOPE) +endfunction() +#=============================================================================# +# arduino_debug_on() +# [PRIVATE/INTERNAL] +# +# arduino_debug_off() +# +# Disables Arduino module debugging. +#=============================================================================# +function(ARDUINO_DEBUG_OFF) + set(ARDUINO_DEBUG False PARENT_SCOPE) +endfunction() +#=============================================================================# +# arduino_debug_msg +# [PRIVATE/INTERNAL] +# +# arduino_debug_msg(MSG) +# +# MSG - Message to print +# +# Print Arduino debugging information. In order to enable printing +# use arduino_debug_on() and to disable use arduino_debug_off(). +#=============================================================================# +function(ARDUINO_DEBUG_MSG MSG) + if (ARDUINO_DEBUG) + message("## ${MSG}") + endif () +endfunction() +#=============================================================================# +# Initialization Script +#=============================================================================# #=============================================================================# # C Flags #=============================================================================# if (NOT DEFINED ARDUINO_C_FLAGS) set(ARDUINO_C_FLAGS "-mcall-prologues -ffunction-sections -fdata-sections") endif (NOT DEFINED ARDUINO_C_FLAGS) -set(CMAKE_C_FLAGS "-g -Os ${ARDUINO_C_FLAGS}" CACHE STRING "") -set(CMAKE_C_FLAGS_DEBUG "-g ${ARDUINO_C_FLAGS}" CACHE STRING "") -set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG ${ARDUINO_C_FLAGS}" CACHE STRING "") -set(CMAKE_C_FLAGS_RELEASE "-Os -DNDEBUG -w ${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS "-g -Os ${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_DEBUG "-g ${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG ${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_RELEASE "-Os -DNDEBUG -w ${ARDUINO_C_FLAGS}" CACHE STRING "") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Os -g -w ${ARDUINO_C_FLAGS}" CACHE STRING "") #=============================================================================# @@ -2090,36 +2555,36 @@ set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Os -g -w ${ARDUINO_C_FLAGS}" CACHE STRI if (NOT DEFINED ARDUINO_CXX_FLAGS) set(ARDUINO_CXX_FLAGS "${ARDUINO_C_FLAGS} -fno-exceptions") endif (NOT DEFINED ARDUINO_CXX_FLAGS) -set(CMAKE_CXX_FLAGS "-g -Os ${ARDUINO_CXX_FLAGS}" CACHE STRING "") -set(CMAKE_CXX_FLAGS_DEBUG "-g ${ARDUINO_CXX_FLAGS}" CACHE STRING "") -set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG ${ARDUINO_CXX_FLAGS}" CACHE STRING "") -set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG ${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS "-g -Os ${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_DEBUG "-g ${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG ${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG ${ARDUINO_CXX_FLAGS}" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-Os -g ${ARDUINO_CXX_FLAGS}" CACHE STRING "") #=============================================================================# # Executable Linker Flags # #=============================================================================# set(ARDUINO_LINKER_FLAGS "-Wl,--gc-sections -lm") -set(CMAKE_EXE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") #=============================================================================# #=============================================================================# # Shared Lbrary Linker Flags # #=============================================================================# -set(CMAKE_SHARED_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_MODULE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") -set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") @@ -2127,85 +2592,114 @@ set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STR # Arduino Settings #=============================================================================# set(ARDUINO_OBJCOPY_EEP_FLAGS -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load - --no-change-warnings --change-section-lma .eeprom=0 CACHE STRING "") -set(ARDUINO_OBJCOPY_HEX_FLAGS -O ihex -R .eeprom CACHE STRING "") -set(ARDUINO_AVRDUDE_FLAGS -V CACHE STRING "") + --no-change-warnings --change-section-lma .eeprom=0 CACHE STRING "") +set(ARDUINO_OBJCOPY_HEX_FLAGS -O ihex -R .eeprom CACHE STRING "") +set(ARDUINO_AVRDUDE_FLAGS -V CACHE STRING "") #=============================================================================# # Initialization #=============================================================================# -if(NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) +if (NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) + + find_file(ARDUINO_VERSION_PATH + NAMES lib/version.txt + PATHS ${ARDUINO_SDK_PATH} + DOC "Path to Arduino version file.") + + # get version first (some stuff depends on versions) + detect_arduino_version(ARDUINO_SDK_VERSION) + set(ARDUINO_SDK_VERSION ${ARDUINO_SDK_VERSION} CACHE STRING "Arduino SDK Version") + set(ARDUINO_SDK_VERSION_MAJOR ${ARDUINO_SDK_VERSION_MAJOR} CACHE STRING "Arduino SDK Major Version") + set(ARDUINO_SDK_VERSION_MINOR ${ARDUINO_SDK_VERSION_MINOR} CACHE STRING "Arduino SDK Minor Version") + set(ARDUINO_SDK_VERSION_PATCH ${ARDUINO_SDK_VERSION_PATCH} CACHE STRING "Arduino SDK Patch Version") + + if (ARDUINO_SDK_VERSION VERSION_LESS 0.19) + message(FATAL_ERROR "Unsupported Arduino SDK (require verion 0.19 or higher)") + endif () + + message(STATUS "Arduino SDK version ${ARDUINO_SDK_VERSION}: ${ARDUINO_SDK_PATH}") + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/) - find_file(ARDUINO_LIBRARIES_PATH - NAMES libraries - PATHS ${ARDUINO_SDK_PATH} - DOC "Path to directory containing the Arduino libraries.") + find_file(ARDUINO_EXAMPLES_PATH + NAMES examples + PATHS ${ARDUINO_SDK_PATH} + DOC "Path to directory containg the Arduino built-in examples." + NO_DEFAULT_PATH) - find_file(ARDUINO_VERSION_PATH - NAMES lib/version.txt - PATHS ${ARDUINO_SDK_PATH} - DOC "Path to Arduino version file.") + find_file(ARDUINO_LIBRARIES_PATH + NAMES libraries + PATHS ${ARDUINO_SDK_PATH} + DOC "Path to directory containing the Arduino libraries." + NO_DEFAULT_PATH) find_program(ARDUINO_AVRDUDE_PROGRAM - NAMES avrdude - PATHS ${ARDUINO_SDK_PATH} - PATH_SUFFIXES hardware/tools hardware/tools/avr/bin - NO_DEFAULT_PATH) + NAMES avrdude + PATHS ${ARDUINO_SDK_PATH} + PATH_SUFFIXES hardware/tools hardware/tools/avr/bin + NO_DEFAULT_PATH) find_program(ARDUINO_AVRDUDE_PROGRAM - NAMES avrdude - DOC "Path to avrdude programmer binary.") + NAMES avrdude + DOC "Path to avrdude programmer binary.") find_program(AVRSIZE_PROGRAM - NAMES avr-size) + NAMES avr-size) find_file(ARDUINO_AVRDUDE_CONFIG_PATH - NAMES avrdude.conf - PATHS ${ARDUINO_SDK_PATH} /etc/avrdude /etc - PATH_SUFFIXES hardware/tools - hardware/tools/avr/etc - DOC "Path to avrdude programmer configuration file.") - - if(NOT CMAKE_OBJCOPY) + NAMES avrdude.conf + PATHS ${ARDUINO_SDK_PATH} /etc/avrdude /etc + PATH_SUFFIXES hardware/tools + hardware/tools/avr/etc + DOC "Path to avrdude programmer configuration file.") + + if (ARDUINO_SDK_VERSION VERSION_LESS 1.0.0) + find_file(ARDUINO_PLATFORM_HEADER_FILE_PATH + NAMES WProgram.h + PATHS ${ARDUINO_SDK_PATH} + PATH_SUFFIXES hardware/arduino/avr/cores/arduino + DOC "Path to Arduino platform's main header file" + NO_DEFAULT_PATH) + else () + find_file(ARDUINO_PLATFORM_HEADER_FILE_PATH + NAMES Arduino.h + PATHS ${ARDUINO_SDK_PATH} + PATH_SUFFIXES hardware/arduino/avr/cores/arduino + DOC "Path to Arduino platform's main header file" + NO_DEFAULT_PATH) + endif () + + if (NOT CMAKE_OBJCOPY) find_program(AVROBJCOPY_PROGRAM - avr-objcopy) + avr-objcopy) set(ADDITIONAL_REQUIRED_VARS AVROBJCOPY_PROGRAM) set(CMAKE_OBJCOPY ${AVROBJCOPY_PROGRAM}) - endif(NOT CMAKE_OBJCOPY) + endif (NOT CMAKE_OBJCOPY) - set(ARDUINO_DEFAULT_BOARD uno CACHE STRING "Default Arduino Board ID when not specified.") - set(ARDUINO_DEFAULT_PORT CACHE STRING "Default Arduino port when not specified.") - set(ARDUINO_DEFAULT_SERIAL CACHE STRING "Default Arduino Serial command when not specified.") + if (EXISTS "${ARDUINO_EXAMPLES_PATH}") + load_arduino_examples_categories() + endif () + + set(ARDUINO_DEFAULT_BOARD uno CACHE STRING "Default Arduino Board ID when not specified.") + set(ARDUINO_DEFAULT_PORT CACHE STRING "Default Arduino port when not specified.") + set(ARDUINO_DEFAULT_SERIAL CACHE STRING "Default Arduino Serial command when not specified.") set(ARDUINO_DEFAULT_PROGRAMMER CACHE STRING "Default Arduino Programmer ID when not specified.") # Ensure that all required paths are found required_variables(VARS - ARDUINO_PLATFORMS - ARDUINO_CORES_PATH - ARDUINO_BOOTLOADERS_PATH - ARDUINO_LIBRARIES_PATH - ARDUINO_BOARDS_PATH - ARDUINO_PROGRAMMERS_PATH - ARDUINO_VERSION_PATH - ARDUINO_AVRDUDE_FLAGS - ARDUINO_AVRDUDE_PROGRAM - ARDUINO_AVRDUDE_CONFIG_PATH - AVRSIZE_PROGRAM - ${ADDITIONAL_REQUIRED_VARS} - MSG "Invalid Arduino SDK path (${ARDUINO_SDK_PATH}).\n") - - detect_arduino_version(ARDUINO_SDK_VERSION) - set(ARDUINO_SDK_VERSION ${ARDUINO_SDK_VERSION} CACHE STRING "Arduino SDK Version") - set(ARDUINO_SDK_VERSION_MAJOR ${ARDUINO_SDK_VERSION_MAJOR} CACHE STRING "Arduino SDK Major Version") - set(ARDUINO_SDK_VERSION_MINOR ${ARDUINO_SDK_VERSION_MINOR} CACHE STRING "Arduino SDK Minor Version") - set(ARDUINO_SDK_VERSION_PATCH ${ARDUINO_SDK_VERSION_PATCH} CACHE STRING "Arduino SDK Patch Version") - - if(ARDUINO_SDK_VERSION VERSION_LESS 0.19) - message(FATAL_ERROR "Unsupported Arduino SDK (require verion 0.19 or higher)") - endif() - - message(STATUS "Arduino SDK version ${ARDUINO_SDK_VERSION}: ${ARDUINO_SDK_PATH}") + ARDUINO_PLATFORMS + ARDUINO_CORES_PATH + ARDUINO_BOOTLOADERS_PATH + ARDUINO_LIBRARIES_PATH + ARDUINO_BOARDS_PATH + ARDUINO_PROGRAMMERS_PATH + ARDUINO_VERSION_PATH + ARDUINO_AVRDUDE_FLAGS + ARDUINO_AVRDUDE_PROGRAM + ARDUINO_AVRDUDE_CONFIG_PATH + AVRSIZE_PROGRAM + ${ADDITIONAL_REQUIRED_VARS} + MSG "Invalid Arduino SDK path (${ARDUINO_SDK_PATH}).\n") setup_arduino_size_script(ARDUINO_SIZE_SCRIPT) set(ARDUINO_SIZE_SCRIPT ${ARDUINO_SIZE_SCRIPT} CACHE INTERNAL "Arduino Size Script") @@ -2215,18 +2709,17 @@ if(NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) set(ARDUINO_FOUND True CACHE INTERNAL "Arduino Found") mark_as_advanced( - ARDUINO_CORES_PATH - ARDUINO_VARIANTS_PATH - ARDUINO_BOOTLOADERS_PATH - ARDUINO_LIBRARIES_PATH - ARDUINO_BOARDS_PATH - ARDUINO_PROGRAMMERS_PATH - ARDUINO_VERSION_PATH - ARDUINO_AVRDUDE_FLAGS - ARDUINO_AVRDUDE_PROGRAM - ARDUINO_AVRDUDE_CONFIG_PATH - ARDUINO_OBJCOPY_EEP_FLAGS - ARDUINO_OBJCOPY_HEX_FLAGS - AVRSIZE_PROGRAM) -endif() - + ARDUINO_CORES_PATH + ARDUINO_VARIANTS_PATH + ARDUINO_BOOTLOADERS_PATH + ARDUINO_LIBRARIES_PATH + ARDUINO_BOARDS_PATH + ARDUINO_PROGRAMMERS_PATH + ARDUINO_VERSION_PATH + ARDUINO_AVRDUDE_FLAGS + ARDUINO_AVRDUDE_PROGRAM + ARDUINO_AVRDUDE_CONFIG_PATH + ARDUINO_OBJCOPY_EEP_FLAGS + ARDUINO_OBJCOPY_HEX_FLAGS + AVRSIZE_PROGRAM) +endif () diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 2302e27..4e0b794 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -2,24 +2,38 @@ # can be used. For a detailed explenation of all the options please # reade README.rst. -set(ARDUINO_DEFAULT_BOARD diecimila) # Default Board ID, when not specified +set(ARDUINO_DEFAULT_BOARD uno) # Default Board ID, when not specified set(ARDUINO_DEFAULT_PORT /dev/ttyUSB0) # Default Port, when not specified - #====================================================================# # master_writer example from Wire library #====================================================================# -generate_arduino_example(wire_example - LIBRARY Wire - EXAMPLE master_writer) +GENERATE_ARDUINO_LIBRARY_EXAMPLE(wire_example + LIBRARY Wire + EXAMPLE master_writer + BOARD uno) # Alternative: by vairables #set(wire_example_LIBRARY Wire) #set(wire_example_EXAMPLE master_writer) -# +#set(blink_example_BOARD uno) #generate_arduino_example(wire_example) +#====================================================================# +# Original blink example (from Arduino SDK examples) +#====================================================================# +GENERATE_ARDUINO_EXAMPLE(blink_example + CATEGORY Basics + EXAMPLE Blink + BOARD uno) +# Alternative: by variables +#set(blink_example_CATEGORY Basics) +#set(blink_example_EXAMPLE Blink) +#set(blink_example_PORT /dev/ttyACM) +#set(blink_example_BOARD uno) +# +#generate_arduino_firmware(blink_original) #====================================================================# # Original blink sketch (from Arduino SDK examples) @@ -28,15 +42,15 @@ generate_arduino_example(wire_example # Some installations have renamed the example directories if (EXISTS "${ARDUINO_SDK_PATH}/examples/01.Basics/Blink") set(BLINK_SKETCH "${ARDUINO_SDK_PATH}/examples/01.Basics/Blink") -else() +else () set(BLINK_SKETCH "${ARDUINO_SDK_PATH}/examples/1.Basics/Blink") -endif() +endif () generate_arduino_firmware(blink_original - SKETCH "${BLINK_SKETCH}" - PORT /dev/ttyACM0 - SERIAL picocom @SERIAL_PORT@ - BOARD uno) + SKETCH "${BLINK_SKETCH}" + PORT /dev/ttyACM0 + SERIAL picocom @SERIAL_PORT@ + BOARD uno) # Alternative: by variables #set(blink_original_SKETCH "${BLINK_SKETCH}") @@ -47,15 +61,13 @@ generate_arduino_firmware(blink_original #generate_arduino_firmware(blink_original) - - #====================================================================# # Bundled blink sketch example #====================================================================# generate_arduino_firmware(blink_bundled - SKETCH Blink - PROGRAMMER usbtinyisp - NO_AUTOLIBS) + SKETCH Blink + PROGRAMMER usbtinyisp + NO_AUTOLIBS) # Alternative: by variables #set(blink_bundled_SKETCH Blink) @@ -65,15 +77,13 @@ generate_arduino_firmware(blink_bundled #generate_arduino_firmware(blink_bundled) - - #====================================================================# # Advanced static library exmaple #====================================================================# generate_arduino_library(blink_lib - SRCS blink_lib.cpp - HDRS blink_lib.h - BOARD uno) + SRCS blink_lib.cpp + HDRS blink_lib.h + BOARD uno) # Alternative: by variables #set(blink_lib_SRCS blink_lib.cpp) @@ -83,15 +93,15 @@ generate_arduino_library(blink_lib #generate_arduino_library(blink_lib) - - #====================================================================# # Advanced firwmare example #====================================================================# +set(nano.build.mcu "atmega328p") generate_arduino_firmware(blink - SRCS blink.cpp - LIBS blink_lib - BOARD uno) + SRCS blink.cpp + LIBS blink_lib + BOARD nano + PORT com4) # Alternative: by variables #set(blink_SRCS blink.cpp) @@ -99,3 +109,18 @@ generate_arduino_firmware(blink #set(blink_BOARD uno) # #generate_arduino_firmware(blink) + +#====================================================================# +# Avr library linkage without copying lib to local directory +#====================================================================# +GENERATE_ARDUINO_FIRMWARE(serial_lib + SRCS serial.cpp + ARDLIBS SoftwareSerial + BOARD uno) + +# Alternative: by variables +#set(blink_SRCS serial.cpp) +#set(blink_ARDLIBS SoftwareSerial) +#set(blink_BOARD uno) +# +#generate_arduino_firmware(blink) diff --git a/example/serial.cpp b/example/serial.cpp new file mode 100644 index 0000000..3a9b446 --- /dev/null +++ b/example/serial.cpp @@ -0,0 +1,13 @@ +#include "Arduino.h" +#include "SoftwareSerial.h" + +void setup() +{ + SoftwareSerial serial(9, 10); + serial.begin(9600); +} + +void loop() +{ + +} \ No newline at end of file