From 10874b9a45de7a5e0aa59fb6a116b69e2acb69a7 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Fri, 23 Aug 2024 16:45:57 +0200 Subject: [PATCH 1/5] Unify reading of information from android-cli --- toolchain/arduino-cli-toolchain.cmake | 156 +++++++++++++------------- 1 file changed, 80 insertions(+), 76 deletions(-) diff --git a/toolchain/arduino-cli-toolchain.cmake b/toolchain/arduino-cli-toolchain.cmake index 5904bd0..c26cd60 100644 --- a/toolchain/arduino-cli-toolchain.cmake +++ b/toolchain/arduino-cli-toolchain.cmake @@ -493,73 +493,99 @@ endfunction() # Internal utility functions that find Arduino components and configurations. # ====================================================================================================================== +set(__ARDUINO_PROPERTIES_EXPANDED_DESCRIPTION "expanded build properties") +set(__ARDUINO_PROPERTIES_EXPANDED_FILENAME "properties-expanded.txt") +set(__ARDUINO_PROPERTIES_EXPANDED_COMMAND board details "--fqbn=${ARDUINO_BOARD}" --format=text --show-properties=expanded) + +set(__ARDUINO_PROPERTIES_UNEXPANDED_DESCRIPTION "unexpanded build properties") +set(__ARDUINO_PROPERTIES_UNEXPANDED_FILENAME "properties-unexpanded.txt") +set(__ARDUINO_PROPERTIES_UNEXPANDED_COMMAND board details "--fqbn=${ARDUINO_BOARD}" --format=text --show-properties=unexpanded) + +set(__ARDUINO_INSTALLED_LIBRARIES_DESCRIPTION "installed Arduino libraries") +set(__ARDUINO_INSTALLED_LIBRARIES_FILENAME "libraries.json") +set(__ARDUINO_INSTALLED_LIBRARIES_COMMAND lib list "--fqbn=${ARDUINO_BOARD}" --format=json) + # ---------------------------------------------------------------------------------------------------------------------- -# Collects build properties for the current board from arduino-cli, -# and stores them in prefixed CMake variables. -# -# See `arduino_get_property()` and `__arduino_property_to_variable()`. +# Reads information from `arduino-cli` into `__ARDUINO_${TOPIC}` and tries to cache it. # ---------------------------------------------------------------------------------------------------------------------- -function(__arduino_find_properties MODE) - if (MODE STREQUAL UNEXPANDED) # <---------------------------------------------------------- parse function arguments - set(_property_mode UNEXPANDED) - elseif (MODE STREQUAL EXPANDED) - set(_property_mode) - else() - message(FATAL_ERROR "Unsupported mode: ${MODE}") +function(__arduino_read_cached_setting TOPIC) + if (NOT DEFINED __ARDUINO_${TOPIC}_DESCRIPTION + OR NOT DEFINED __ARDUINO_${TOPIC}_FILENAME + OR NOT DEFINED __ARDUINO_${TOPIC}_COMMAND) + message(FATAL_ERROR "Invalid topic: ${TOPIC}") return() endif() - string(TOLOWER "${MODE}" _mode) + set(_use_cache YES) - set(_use_property_cache YES) # <----------------------------------------- figure out if a cached version can be used - set(_cachefile_variable "__ARDUINO_PROPERTIES_${MODE}_CACHE") - - if (DEFINED "${_cachefile_variable}") - set(_arduino_cache_filepath "${${_cachefile_variable}}") - set(_cmake_dump_filepath) # do not dump already cached variables + if (__ARDUINO_${TOPIC}_CACHE) + set(_cache_filepath "${__ARDUINO_${TOPIC}_CACHE}") else() - set(_arduino_cache_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/properties-${_mode}.txt") - set(_cmake_dump_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/properties-${_mode}.cmake") + set(_cache_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/${__ARDUINO_${TOPIC}_FILENAME}") - if (NOT EXISTS "${_arduino_cache_filepath}" + if (NOT EXISTS "${_cache_filepath}" OR NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeCache.txt" - OR NOT "${_arduino_cache_filepath}" IS_NEWER_THAN "${CMAKE_BINARY_DIR}/CMakeCache.txt") - set(_use_property_cache NO) + OR NOT "${_cache_filepath}" IS_NEWER_THAN "${CMAKE_BINARY_DIR}/CMakeCache.txt") + set(_use_cache NO) endif() endif() - set("${_cachefile_variable}" "${_arduino_cache_filepath}" PARENT_SCOPE) + if (_use_cache) # <------------------------------------------------------------------ try to read cached information + message(STATUS "Reading ${__ARDUINO_${TOPIC}_DESCRIPTION} from ${_cache_filepath}") + set("__ARDUINO_${TOPIC}_ORIGIN" cache PARENT_SCOPE) - if (_use_property_cache) # <---------------------------------------------------------- try to read cached properties - message(STATUS "Reading ${_mode} build properties from ${_arduino_cache_filepath}") - file(READ "${_arduino_cache_filepath}" _properties) + file(READ "${_cache_filepath}" _content) else() # <------------------------------------------------------------------------------------- run arduino-cli tool - message(STATUS "Running android-cli to read ${_mode} build properties...") + message(STATUS "Running android-cli to read ${__ARDUINO_${TOPIC}_DESCRIPTION}") + set("__ARDUINO_${TOPIC}_ORIGIN" cli PARENT_SCOPE) execute_process( - COMMAND "${ARDUINO_CLI_EXECUTABLE}" - board details "--fqbn=${ARDUINO_BOARD}" - --show-properties=${_mode} --format=text + COMMAND "${ARDUINO_CLI_EXECUTABLE}" ${__ARDUINO_${TOPIC}_COMMAND} ENCODING UTF-8 COMMAND_ERROR_IS_FATAL ANY OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE _properties) + OUTPUT_VARIABLE _content) - file(WRITE "${_arduino_cache_filepath}" "${_properties}") + file(WRITE "${_cache_filepath}" "${_content}") endif() - if (NOT _property_list) - string(REPLACE ";" "\\;" _properties "${_properties}") # <------------------ split into lines; preserving semicolons - string(REGEX REPLACE "[ \t\r]*\n" ";" _property_list "${_properties}") + set("__ARDUINO_${TOPIC}" "${_content}" PARENT_SCOPE) + set("__ARDUINO_${TOPIC}_CACHE" "${_cache_filepath}" PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Collects build properties for the current board from arduino-cli, +# and stores them in prefixed CMake variables. +# +# See `arduino_get_property()` and `__arduino_property_to_variable()`. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_find_properties MODE) + if (MODE STREQUAL UNEXPANDED) # <---------------------------------------------------------- parse function arguments + set(_property_mode UNEXPANDED) + elseif (MODE STREQUAL EXPANDED) + set(_property_mode) + else() + message(FATAL_ERROR "Unsupported mode: ${MODE}") + return() endif() - if (NOT _use_property_cache) + __arduino_read_cached_setting("PROPERTIES_${MODE}") + set(_properties "${__ARDUINO_PROPERTIES_${MODE}}") + + string(REPLACE ";" "\\;" _properties "${_properties}") # <------------------ split into lines; preserving semicolons + string(REGEX REPLACE "[ \t\r]*\n" ";" _property_list "${_properties}") + + if (__ARDUINO_PROPERTIES_${MODE}_ORIGIN STREQUAL "cli") list(LENGTH _property_list _count) message(STATUS " ${_count} properties found") + + string(REPLACE ".txt" ".cmake" _cmake_cache_filepath "${__ARDUINO_PROPERTIES_${MODE}_CACHE}") + else() + unset(_cmake_cache_filepath) # do not dump already cached variables endif() - set(_variable_dump "") + unset(_cmake_variable_cache) foreach (_property IN LISTS _property_list) # <--------------------------------- set CMake variables from properties if (_property MATCHES "([^=]+)=(.*)") @@ -573,63 +599,41 @@ function(__arduino_find_properties MODE) endif() set("${_variable}" "${_property_value}" PARENT_SCOPE) - string(APPEND _property_dump "${_variable}=${_property_value}\n") + + string(REPLACE "\\" "\\\\" _escaped_value "${_property_value}") + string(REPLACE "\"" "\\\"" _escaped_value "${_escaped_value}") + string(APPEND _cmake_variable_cache "set(${_variable} \"${_escaped_value}\")\n") elseif (_property) message(FATAL_ERROR "Unexpected output from arduino-cli tool: ${_property}") return() endif() endforeach() - if ("${_cmake_dump_filepath}") # <---------------------------------------------- only dump after running arduino-cli - file(WRITE "${_cmake_dump_filepath}" "${_property_dump}") + if (_cmake_cache_filepath) # <------------------------------------------------ --only dump after running arduino-cli + file(WRITE "${_cmake_cache_filepath}" "${_cmake_variable_cache}") endif() + + set("__ARDUINO_PROPERTIES_${MODE}" "${__ARDUINO_PROPERTIES_${MODE}}" PARENT_SCOPE) + set("__ARDUINO_PROPERTIES_${MODE}_CACHE" "${__ARDUINO_PROPERTIES_${MODE}_CACHE}" PARENT_SCOPE) endfunction() # ---------------------------------------------------------------------------------------------------------------------- # Collects available libraries for the current board from arduino-cli. # ---------------------------------------------------------------------------------------------------------------------- function(__arduino_find_libraries) - set(_use_library_cache YES) # <------------------------------------------ figure out if a cached version can be used - - if (__ARDUINO_INSTALLED_LIBRARIES_CACHE) - set(_arduino_cache_filepath "${__ARDUINO_INSTALLED_LIBRARIES_CACHE}") - else() - set(_arduino_cache_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/libraries.json") - - if (NOT EXISTS "${_arduino_cache_filepath}" - OR NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeCache.txt" - OR NOT "${_arduino_cache_filepath}" IS_NEWER_THAN "${CMAKE_BINARY_DIR}/CMakeCache.txt") - set(_use_library_cache NO) - endif() - endif() - - if (_use_library_cache) # <------------------------------------------------------------ try to read cached libraries - message(STATUS "Reading installed Arduino libraries from ${_arduino_cache_filepath}") - file(READ "${_arduino_cache_filepath}" _json) - else() # <------------------------------------------------------------------------------------- run arduino-cli tool - message(STATUS "Running android-cli to read installed Arduino libraries...") - - execute_process( - COMMAND "${ARDUINO_CLI_EXECUTABLE}" - lib list "--fqbn=${ARDUINO_BOARD}" --format=json - - ENCODING UTF-8 - COMMAND_ERROR_IS_FATAL ANY - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE _json) - - file(WRITE "${_arduino_cache_filepath}" "${_json}") - endif() + __arduino_read_cached_setting(INSTALLED_LIBRARIES) - string(JSON _installed_libraries GET "${_json}" installed_libraries) # <-------------- parse the library information + string( # <--------------------------------------------------------------------------- parse the library information + JSON _installed_libraries + GET "${__ARDUINO_INSTALLED_LIBRARIES}" installed_libraries) - if (NOT _use_library_cache) + if (__ARDUINO_INSTALLED_LIBRARIES_ORIGIN STREQUAL "cli") string(JSON _count LENGTH "${_installed_libraries}") message(STATUS " ${_count} libraries found") endif() - set(__ARDUINO_INSTALLED_LIBRARIES "${_installed_libraries}" PARENT_SCOPE) - set(__ARDUINO_INSTALLED_LIBRARIES_CACHE "${_arduino_cache_filepath}" PARENT_SCOPE) + set(__ARDUINO_INSTALLED_LIBRARIES "${_installed_libraries}" PARENT_SCOPE) + set(__ARDUINO_INSTALLED_LIBRARIES_CACHE "${__ARDUINO_INSTALLED_LIBRARIES_CACHE}" PARENT_SCOPE) endfunction() # ====================================================================================================================== From f06ca9591e670ad7b4de669f5f6190c895cb02b5 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Fri, 23 Aug 2024 16:52:27 +0200 Subject: [PATCH 2/5] Read arduino-cli config and validate some paths --- .github/workflows/run-testsuite.yml | 5 ++ toolchain/arduino-cli-toolchain.cmake | 101 +++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-testsuite.yml b/.github/workflows/run-testsuite.yml index c31c59a..fabcbec 100644 --- a/.github/workflows/run-testsuite.yml +++ b/.github/workflows/run-testsuite.yml @@ -27,10 +27,15 @@ jobs: - name: Install platform run: | + New-Item -ItemType "directory" -Path "$env:USERPROFILE\Arduino" + New-Item -ItemType "directory" -Path "$env:LOCALAPPDATA\Arduino15\libraries" + arduino-cli config init arduino-cli config add board_manager.additional_urls https://arduino.esp8266.com/stable/package_esp8266com_index.json arduino-cli config add board_manager.additional_urls https://drazzy.com/package_drazzy.com_index.json arduino-cli config add board_manager.additional_urls https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json + arduino-cli config set directories.builtin.libraries "$env:LOCALAPPDATA\Arduino15\libraries" + arduino-cli config set directories.user "$env:USERPROFILE\Arduino" arduino-cli config dump arduino-cli core update-index diff --git a/toolchain/arduino-cli-toolchain.cmake b/toolchain/arduino-cli-toolchain.cmake index c26cd60..79acbf2 100644 --- a/toolchain/arduino-cli-toolchain.cmake +++ b/toolchain/arduino-cli-toolchain.cmake @@ -493,6 +493,10 @@ endfunction() # Internal utility functions that find Arduino components and configurations. # ====================================================================================================================== +set(__ARDUINO_CLI_CONFIG_DESCRIPTION "Arduino CLI configuration") +set(__ARDUINO_CLI_CONFIG_FILENAME "config.json") +set(__ARDUINO_CLI_CONFIG_COMMAND config dump --format=json) + set(__ARDUINO_PROPERTIES_EXPANDED_DESCRIPTION "expanded build properties") set(__ARDUINO_PROPERTIES_EXPANDED_FILENAME "properties-expanded.txt") set(__ARDUINO_PROPERTIES_EXPANDED_COMMAND board details "--fqbn=${ARDUINO_BOARD}" --format=text --show-properties=expanded) @@ -618,7 +622,8 @@ function(__arduino_find_properties MODE) endfunction() # ---------------------------------------------------------------------------------------------------------------------- -# Collects available libraries for the current board from arduino-cli. +# Reads available libraries for the current board from `arduino-cli` +# and stores the JSON in `__ARDUINO_INSTALLED_LIBRARIES`. # ---------------------------------------------------------------------------------------------------------------------- function(__arduino_find_libraries) __arduino_read_cached_setting(INSTALLED_LIBRARIES) @@ -636,6 +641,92 @@ function(__arduino_find_libraries) set(__ARDUINO_INSTALLED_LIBRARIES_CACHE "${__ARDUINO_INSTALLED_LIBRARIES_CACHE}" PARENT_SCOPE) endfunction() +# ---------------------------------------------------------------------------------------------------------------------- +# Reads configuration of `arduino-cli` and stores the JSON in `__ARDUINO_CLI_CONFIG`. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_find_config) + __arduino_read_cached_setting(CLI_CONFIG) + + set(__ARDUINO_CLI_CONFIG "${__ARDUINO_CLI_CONFIG}" PARENT_SCOPE) + set(__ARDUINO_CLI_CONFIG_CACHE "${__ARDUINO_CLI_CONFIG_CACHE}" PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Finds and verifies the location of user sketches. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_find_user_sketches_dirpath) + string( + JSON _user_sketches_dirpath ERROR_VARIABLE _error + GET "${__ARDUINO_CLI_CONFIG}" config directories user) + + if (NOT _error AND _user_sketches_dirpath) + cmake_path(ABSOLUTE_PATH _user_sketches_dirpath NORMALIZE) + + if (NOT IS_DIRECTORY "${_user_sketches_dirpath}") + set(_error_message + "Your arduino-cli is configured to use \"${_user_sketches_dirpath}\" " + "for user sketches and libraries, but this directory does not exist.") + endif() + else() + set(_error_message "Your arduino-cli doesn't know where to find user sketches and libraries.") + endif() + + if (_error_message) + list(APPEND _error_message + "\nYOUR BUILDS MIGHT FAIL!\nPlease consider running `arduino-cli config set " + "directories.user PATH-TO-YOUR-SKETCHES` to address this issue.") + + if (DEFINED ENV{USERPROFILE}) + list(APPEND _error_message "\nA typical path would be: \"$ENV{USERPROFILE}\\Arduino\"") + elseif (DEFINED ENV{HOME}) + list(APPEND _error_message "\nA typical path would be: \"$ENV{HOME}/Arduino\"") + endif() + + message(WARNING ${_error_message}) + set(_user_sketches_dirpath NOTFOUND) + endif() + + set(__ARDUINO_USER_SKETCHES_DIRPATH "${_user_sketches_dirpath}" PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Finds and verifies the location of IDE libraries. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_find_ide_libraries_dirpath) + string( + JSON _ide_libraries_dirpath ERROR_VARIABLE _error + GET "${__ARDUINO_CLI_CONFIG}" config directories builtin libraries) + + if (NOT _error AND _ide_libraries_dirpath) + cmake_path(ABSOLUTE_PATH _ide_libraries_dirpath NORMALIZE) + + if (NOT IS_DIRECTORY "${_ide_libraries_dirpath}") + set(_error_message + "Your arduino-cli is configured to use \"${_ide_libraries_dirpath}\" " + "for IDE provided libraries, but this directory does not exist.") + endif() + else() + set(_error_message "Your arduino-cli doesn't know where to find IDE provided libraries.") + endif() + + if (_error_message) + list(APPEND _error_message + "\nYOUR BUILDS MIGHT FAIL!\nPlease consider running `arduino-cli config set " + "directories.builtin.libraries PATH-TO-YOUR-IDE-LIBRARIES` to address this issue.") + + if (DEFINED ENV{LOCALAPPDATA}) + list(APPEND _error_message "\nA typical path would be: \"$ENV{LOCALAPPDATA}\\Arduino15\\libraries\"") + elseif (DEFINED ENV{HOME}) + list(APPEND _error_message "\nA typical path would be: \"$ENV{HOME}/.arduino15/libraries\"") + endif() + + message(WARNING ${_error_message}) + set(_user_sketches_dirpath NOTFOUND) + endif() + + set(__ARDUINO_IDE_LIBRARIES_DIRPATH "${_ide_libraries_dirpath}" PARENT_SCOPE) +endfunction() + # ====================================================================================================================== # Internal utility functions that inspect CMake targets. # ====================================================================================================================== @@ -1019,7 +1110,10 @@ find_program( # <--------------------------------------------------------------- [HKLM/SOFTWARE/Arduino CLI;InstallDir] "$ENV{PROGRAMFILES}/Arduino CLI") -__arduino_find_properties(EXPANDED) # <-------------------------------------- collect properties and installed libraries +__arduino_find_config() # <----------------------------------- collect configuration, properties and installed libraries +__arduino_find_user_sketches_dirpath() +__arduino_find_ide_libraries_dirpath() +__arduino_find_properties(EXPANDED) __arduino_find_properties(UNEXPANDED) __arduino_find_libraries() @@ -1079,7 +1173,8 @@ __arduino_run_hooks("recipe.hooks.prebuild") list( # <--------------------------------------------------------------------------------------- configure try_compile() APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES ARDUINO_BOARD # make it just work - __ARDUINO_PROPERTIES_EXPANDED_CACHE # make it MUCH faster + __ARDUINO_CLI_CONFIG_CACHE # make it MUCH faster + __ARDUINO_PROPERTIES_EXPANDED_CACHE __ARDUINO_PROPERTIES_UNEXPANDED_CACHE __ARDUINO_INSTALLED_LIBRARIES_CACHE __ARDUINO_IMPORTED_TARGET_CACHE) From d5968affe72a5b1565a97563ea23876387f516e8 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 22 Aug 2024 23:25:45 +0200 Subject: [PATCH 3/5] Scan preprocessed code for implicit dependencies Fixes: #5 --- CMakeLists.txt | 2 + toolchain/Scripts/CollectLibraries.cmake | 178 ++++++++++++++++++ .../Templates/ArduinoLibraryCMakeLists.txt.in | 4 + .../Templates/CollectLibrariesConfig.cmake.in | 4 + toolchain/arduino-cli-toolchain.cmake | 64 ++++++- 5 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 toolchain/Scripts/CollectLibraries.cmake create mode 100644 toolchain/Templates/CollectLibrariesConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index f92e265..9b7e62d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,10 @@ add_custom_target( toolchain/Arduino/RulesOverride.cmake toolchain/Arduino/ScriptMode.cmake toolchain/Platform/Arduino.cmake + toolchain/Scripts/CollectLibraries.cmake toolchain/Scripts/Preprocess.cmake toolchain/Templates/ArduinoLibraryCMakeLists.txt.in + toolchain/Templates/CollectLibrariesConfig.cmake.in toolchain/Templates/PreprocessConfig.cmake.in toolchain/arduino-cli-toolchain.cmake) diff --git a/toolchain/Scripts/CollectLibraries.cmake b/toolchain/Scripts/CollectLibraries.cmake new file mode 100644 index 0000000..299abbf --- /dev/null +++ b/toolchain/Scripts/CollectLibraries.cmake @@ -0,0 +1,178 @@ +include(Arduino/ScriptMode NO_POLICY_SCOPE) +include("${ARGUMENTS}" OPTIONAL) + +arduino_script_require( + COLLECT_LIBRARIES_CACHE + COLLECT_LIBRARIES_TARGET + COLLECT_LIBRARIES_OUTPUT + COLLECT_LIBRARIES_SOURCES) + +# ---------------------------------------------------------------------------------------------------------------------- +# Extracts include directives from the files in `SOURCES_LIST` and stores the filename list in `OUTPUT_VARIABLE`. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_collect_required_libraries SOURCES_LIST OUTPUT_VARIABLE) + unset(_required_includes) + + foreach(_filepath IN LISTS SOURCES_LIST) + message(STATUS " Scanning ${_filepath} for include directives") + + # FIXME actually run preprocessor on the file to handle conditional includes (#ifdef/#else) + file(STRINGS "${_filepath}" _include_directives REGEX "^${_hash}[ /t]*include") + + foreach(_line IN LISTS _include_directives) + if (_line MATCHES "${_hash}[ /t]*include[ /t]*<([^>]+\\.[Hh])>") + list(APPEND _required_includes "${CMAKE_MATCH_1}") + endif() + endforeach() + endforeach() + + list(REMOVE_DUPLICATES _required_includes) + list(REMOVE_ITEM _required_includes "Arduino.h") + + set("${OUTPUT_VARIABLE}" ${_required_includes} PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Filters the known installed libraries by `LOCATION` and reports the result in `OUTPUT_VARIABLE`. +# The result is a list of `(type, name, dirpath)` tuples separated by '|'. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_find_installed_libraries LOCATION OUTPUT_VARIABLE) + message(VERBOSE "Reading installed libraries from ${COLLECT_LIBRARIES_CACHE}") + file(READ "${COLLECT_LIBRARIES_CACHE}" _installed_libraries) + + string(JSON _installed_libraries GET "${_installed_libraries}" "installed_libraries") + string(JSON _count LENGTH "${_installed_libraries}") + math(EXPR _last "${_count} - 1") + + unset(_library_list) + + foreach(_library_index RANGE ${_last}) + string(JSON _dirpath GET "${_installed_libraries}" ${_library_index} "library" "source_dir") + string(JSON _type GET "${_installed_libraries}" ${_library_index} "library" "location") + string(JSON _name GET "${_installed_libraries}" ${_library_index} "library" "name") + + cmake_path(NORMAL_PATH _dirpath) + list(APPEND _library_list "${_type}|${_name}|${_dirpath}") + endforeach() + + set("${OUTPUT_VARIABLE}" ${_library_list} PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Splits a `LIBRARY` tuple into its components `(type, name, dirpath)`. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_split_library_tuple LIBRARY TYPE_VARIABLE NAME_VARIABLE DIRPATH_VARIABLE) + string(REGEX MATCH "^([^|]+)\\|([^|]+)\\|([^|]+)" _ "${_library}") + + set("${TYPE_VARIABLE}" "${CMAKE_MATCH_1}" PARENT_SCOPE) + set("${NAME_VARIABLE}" "${CMAKE_MATCH_2}" PARENT_SCOPE) + set("${DIRPATH_VARIABLE}" "${CMAKE_MATCH_3}" PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Tries to find the libraries that provide `REQUIRED_INCLUDES` +# and stores the identified library tuples in `OUTPUT_VARIABLE`. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_resolve_libraries REQUIRED_INCLUDES OUTPUT_VARIABLE) + # FIXME Read LINK_LIBRARIES of COLLECT_LIBRARIES_TARGET + + # Cluster the libraries reported by arduino-cli by location to implement the location priority + # described by https://arduino.github.io/arduino-cli/1.0/sketch-build-process/#location-priority + + __arduino_find_installed_libraries("user" _user_librarys) + __arduino_find_installed_libraries("platform" _platform_librarys) + __arduino_find_installed_libraries("ref-platform" _board_librarys) + __arduino_find_installed_libraries("ide" _ide_libraries) + + unset(_resolved_includes) + unset(_required_libraries) + unset(_unresolved_includes) + + while (REQUIRED_INCLUDES) + list(POP_FRONT REQUIRED_INCLUDES _next_include) + message(VERBOSE " Searching library that provides ${_next_include}") + + unset(_matching_library) + + foreach(_library IN LISTS _user_librarys _platform_librarys _board_librarys _ide_libraries) + __arduino_split_library_tuple("${_library}" _type _name _dirpath) + message(TRACE "Checking ${_type} library ${_name} at ${_dirpath}") + + if (EXISTS "${_dirpath}/${_next_include}" + AND NOT IS_DIRECTORY "${_dirpath}/${_next_include}") + set(_matching_library "${_library}") + break() + endif() + endforeach() + + if (_matching_library) + message(VERBOSE " Using ${_next_include} from ${_type} library ${_name} at ${_dirpath}") + + list(APPEND _resolved_includes "${_next_include}") + list(APPEND _required_libraries "${_matching_library}") + else() + list(APPEND _unresolved_includes "${_next_include}") + endif() + endwhile() + + if (_unresolved_includes) + list(JOIN _unresolved_includes ", " _unresolved_includes) + message(WARNING "Could not resolve all required libraries. Unresolved includes: ${_unresolved_includes}") + endif() + + list(REMOVE_DUPLICATES _required_libraries) + set("${OUTPUT_VARIABLE}" "${_required_libraries}" PARENT_SCOPE) +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Generates a CMake file that defines import libraries from `REQUIRED_LIBRARIES` and links `TARGET` with them. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_generate_library_definitions TARGET REQUIRED_LIBRARIES OUTPUT_FILEPATH) + set(_library_definitions "# Generated by ${CMAKE_SCRIPT_MODE_FILE}") + unset(_link_libraries) + + foreach(_library IN LISTS REQUIRED_LIBRARIES) # <--------------------- generate __arduino_add_import_library() calls + __arduino_split_library_tuple("${_library}" _ _name _dirpath) + string(REPLACE " " "_" _target_name "${_name}") + + if (_target_name MATCHES "[^A-Za-z0-9]_") + message(FATAL_ERROR "Unexpected character '${CMAKE_MATCH_0}' in library name '${_name}'") + return() + endif() + + list( + APPEND _library_definitions + "" + "if (NOT TARGET Arduino::${_target_name})" + " __arduino_add_import_library(${_target_name} \"${_dirpath}\")" + "endif()") + + list(APPEND _link_libraries "Arduino::${_target_name}") + endforeach() + + if (_link_libraries) # <-------------------------------------------- link `TARGET` with the defined import libraries + list(APPEND _library_definitions + "" + "target_link_libraries(\"${TARGET}\" PUBLIC ${_link_libraries})") + endif() + + list(JOIN _library_definitions "\n" _library_definitions) # <------------ write the definitions to `OUTPUT_FILEPATH` + + if (EXISTS "${OUTPUT_FILEPATH}") + file(READ "${OUTPUT_FILEPATH}" _previous_definitions) + else() + unset(_previous_definitions) + endif() + + if (NOT _library_definitions STREQUAL _previous_definitions) + message(STATUS "Generating ${OUTPUT_FILEPATH}") + file(WRITE "${OUTPUT_FILEPATH}" "${_library_definitions}") + endif() +endfunction() + +__arduino_collect_required_libraries("${COLLECT_LIBRARIES_SOURCES}" _required_includes) +__arduino_resolve_libraries("${_required_includes}" _required_libraries) + +__arduino_generate_library_definitions( + "${COLLECT_LIBRARIES_TARGET}" "${_required_libraries}" + "${COLLECT_LIBRARIES_OUTPUT}") diff --git a/toolchain/Templates/ArduinoLibraryCMakeLists.txt.in b/toolchain/Templates/ArduinoLibraryCMakeLists.txt.in index ba634f0..288ca92 100644 --- a/toolchain/Templates/ArduinoLibraryCMakeLists.txt.in +++ b/toolchain/Templates/ArduinoLibraryCMakeLists.txt.in @@ -10,3 +10,7 @@ add_library( target_include_directories( ${_libname} PUBLIC "${_quoted_library_directories}") + +if (NOT "${_libname}" STREQUAL "ArduinoCore") + target_link_libraries(${_libname} PUBLIC Arduino::Core) +endif() diff --git a/toolchain/Templates/CollectLibrariesConfig.cmake.in b/toolchain/Templates/CollectLibrariesConfig.cmake.in new file mode 100644 index 0000000..bbade31 --- /dev/null +++ b/toolchain/Templates/CollectLibrariesConfig.cmake.in @@ -0,0 +1,4 @@ +set(COLLECT_LIBRARIES_CACHE "${__ARDUINO_INSTALLED_LIBRARIES_CACHE}") +set(COLLECT_LIBRARIES_OUTPUT "${_required_libraries_include}") +set(COLLECT_LIBRARIES_SOURCES "${_preprocessed_sources_list}") +set(COLLECT_LIBRARIES_TARGET "${TARGET}") diff --git a/toolchain/arduino-cli-toolchain.cmake b/toolchain/arduino-cli-toolchain.cmake index 79acbf2..38a289c 100644 --- a/toolchain/arduino-cli-toolchain.cmake +++ b/toolchain/arduino-cli-toolchain.cmake @@ -957,7 +957,7 @@ function(__arduino_preprocess OUTPUT_VARIABLE OUTPUT_DIRPATH SOURCE_DIRPATH MODE "${OUTPUT_DIRPATH}" _output_filepath) string(MD5 _filepath_hash "${_output_filepath}") - set(_config_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/${_target}/preprocess-config-${_filepath_hash}.cmake") + set(_config_filepath "${CMAKE_BINARY_DIR}/ArduinoFiles/${_target}/preprocess-${_filepath_hash}.cmake") __arduino_add_code_generator( SCRIPT_OUTPUT "${_output_filepath}" @@ -996,6 +996,61 @@ function(__arduino_preprocess_sketch TARGET OUTPUT_DIRPATH SOURCE_DIRPATH SOURCE endforeach() endfunction() +# ---------------------------------------------------------------------------------------------------------------------- +# Remove obsolete files from preprocesses the sources files directory. +# Such step is neccessary as the prebuild hooks of various cores place files in this folder to implement dynamic +# dependency chains. Therefore this folder has to be searched for files to resolve dependencies, instead of using +# a computed list. For this search to succeed previous build-artifacts must be removed. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_remove_obsolete_sketch_files TARGET SKETCH_DIRPATH) + set(_source_list_cache "${CMAKE_BINARY_DIR}/ArduinoFiles/${TARGET}/sources.txt") + + if (EXISTS "${_source_list_cache}") # <----------------------------------- read target SOURCE list from previous run + file(READ "${_source_list_cache}" _cached_source_list) + else() + unset(_cached_source_list) + endif() + + get_property(_source_list TARGET "${TARGET}" PROPERTY SOURCES) # <---------- check if files got removed from SOURCES + + list(REMOVE_DUPLICATES _source_list) + list(REMOVE_ITEM _cached_source_list ${_source_list}) + file(WRITE "${_source_list_cache}" "${_source_list}") + + foreach(_filename IN LISTS _cached_source_list) # <------------------- delete preprocessed files for removed SOURCES + __arduino_resolve_preprocessed_filepath( + "${_source_dirpath}" "${_filename}" + "${SKETCH_DIRPATH}" _sketch_filepath) + + message(STATUS "Removing obsolete ${_filename}") + file(REMOVE "${_sketch_filepath}") + endforeach() +endfunction() + +# ---------------------------------------------------------------------------------------------------------------------- +# Scan the preprocessed source code of `TARGET` for #include directives to detect implicit library dependencies. +# ---------------------------------------------------------------------------------------------------------------------- +function(__arduino_link_implicit_libraries TARGET SKETCH_DIRPATH) + # Can't simple use a pre-computed source file list here, but have to list files in SKETCH_DIRPATH + # since the pre-build hooks of some platforms place generated files in the sketch folder to enable + # selective linking of system libraries. + __arduino_remove_obsolete_sketch_files("${_target}" "${SKETCH_DIRPATH}") + __arduino_collect_source_files(_preprocessed_sources_list "${SKETCH_DIRPATH}") + + set(_required_libraries_include "${CMAKE_BINARY_DIR}/ArduinoFiles/${_target}/libraries-include.cmake") + target_sources("${_target}" PRIVATE "${_required_libraries_include}") + + __arduino_add_code_generator( + SCRIPT_OUTPUT "${_required_libraries_include}" + SCRIPT_FILEPATH "${__ARDUINO_TOOLCHAIN_COLLECT_LIBRARIES}" + CONFIG_TEMPLATE "${ARDUINO_TOOLCHAIN_DIR}/Templates/CollectLibrariesConfig.cmake.in" + CONFIG_FILEPATH "${CMAKE_BINARY_DIR}/ArduinoFiles/${_target}/libraries-config.cmake" + COMMENT "Collecting required libraries for ${TARGET}" + DEPENDS ${_preprocessed_sources_list}) + + include("${_required_libraries_include}") +endfunction() + # ---------------------------------------------------------------------------------------------------------------------- # Iterates all subdirectories of the project and finalizes Arduino sketches. # ---------------------------------------------------------------------------------------------------------------------- @@ -1043,7 +1098,8 @@ function(__arduino_toolchain_finalize DIRECTORY) "${_target}" "${_sketch_dirpath}" "${_source_dirpath}" "${_source_list}") - target_link_libraries("${_target}" PUBLIC Arduino::Core) + target_link_libraries("${_target}" PUBLIC Arduino::Core) # <------------- link implicitly required libraries + __arduino_link_implicit_libraries("${_target}" "${_sketch_dirpath}") set_property(TARGET "${_target}" PROPERTY SUFFIX ".elf") # <----------------------- build the final firmware __arduino_add_firmware_target("${_target}" _firmware_filename) @@ -1100,9 +1156,11 @@ cmake_path(GET CMAKE_CURRENT_LIST_FILE PARENT_PATH ARDUINO_TOOLCHAIN_DIR) # <--- list(APPEND CMAKE_MODULE_PATH ${ARDUINO_TOOLCHAIN_DIR}) set(__ARDUINO_SKETCH_SUFFIX "\\.(ino|pde)\$") # <-------------------------------------------- generally useful constants -set(__ARDUINO_TOOLCHAIN_PREPROCESS "${ARDUINO_TOOLCHAIN_DIR}/Scripts/Preprocess.cmake") +set(__ARDUINO_TOOLCHAIN_COLLECT_LIBRARIES "${ARDUINO_TOOLCHAIN_DIR}/Scripts/CollectLibraries.cmake") +set(__ARDUINO_TOOLCHAIN_PREPROCESS "${ARDUINO_TOOLCHAIN_DIR}/Scripts/Preprocess.cmake") list(APPEND CMAKE_CONFIGURE_DEPENDS # <------------------------------------- rerun CMake when helper scripts are changed + "${__ARDUINO_TOOLCHAIN_COLLECT_LIBRARIES}" "${__ARDUINO_TOOLCHAIN_PREPROCESS}") find_program( # <-------------------------------------------------------------------------------------- find android-cli From f257a16eee614445d0a66ddcef421d85135686b0 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 22 Aug 2024 22:09:56 +0200 Subject: [PATCH 4/5] Show number of CPU cores available for testing --- tests/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3f68620..c6f989b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ include(platforms.cmake) cmake_host_system_information(RESULT _logical_cores QUERY NUMBER_OF_LOGICAL_CORES) +message(STATUS "${_logical_cores} logical CPU cores available for testing") set(CTEST_RESOURCE_SPEC_FILE "${CMAKE_BINARY_DIR}/CTestResources.json") configure_file(CTestResources.json.in "${CTEST_RESOURCE_SPEC_FILE}") From b3fc3d52b9ec543ab6633dc2754388dafae99c87 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Sun, 18 Aug 2024 01:20:30 +0200 Subject: [PATCH 5/5] Add more test cases --- .gitignore | 4 +- README.md | 15 +++ tests/CMakeLists.txt | 17 +++ tests/DigitalPotControl/CMakeLists.txt | 3 + tests/DigitalPotControl/DigitalPotControl.ino | 73 ++++++++++++ tests/EchoString/CMakeLists.txt | 3 + tests/EchoString/EchoString.ino | 44 +++++++ tests/LinkStatus/CMakeLists.txt | 3 + tests/LinkStatus/LinkStatus.ino | 44 +++++++ tests/TFTBitmapLogo/CMakeLists.txt | 3 + tests/TFTBitmapLogo/TFTBitmapLogo.ino | 108 ++++++++++++++++++ tests/TFTBitmapLogo/colors.bmp | Bin 0 -> 6966 bytes tests/TwoPortReceive/CMakeLists.txt | 3 + tests/TwoPortReceive/TwoPortReceive.ino | 85 ++++++++++++++ 14 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 tests/DigitalPotControl/CMakeLists.txt create mode 100644 tests/DigitalPotControl/DigitalPotControl.ino create mode 100644 tests/EchoString/CMakeLists.txt create mode 100644 tests/EchoString/EchoString.ino create mode 100644 tests/LinkStatus/CMakeLists.txt create mode 100644 tests/LinkStatus/LinkStatus.ino create mode 100644 tests/TFTBitmapLogo/CMakeLists.txt create mode 100644 tests/TFTBitmapLogo/TFTBitmapLogo.ino create mode 100644 tests/TFTBitmapLogo/colors.bmp create mode 100644 tests/TwoPortReceive/CMakeLists.txt create mode 100644 tests/TwoPortReceive/TwoPortReceive.ino diff --git a/.gitignore b/.gitignore index e68664e..a9edc36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -/CMakeLists.txt.user* /playground + +CMakeLists.txt.user* + diff --git a/README.md b/README.md index 2d6a347..5c5523a 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,21 @@ This project would not have been possible without all the previous hard work I took good inspiration from it, especially when it comes to making CMake's initial compiler detection accept Arduinos very special binary layout. +## Third-Party Code + +This project's test suites uses example code from third parties: + +* [DigitalPotControl](tests/DigitalPotControl/DigitalPotControl.ino) + by _Heather Dewey-Hagborg_ and _Tom Igoe_. +* [EchoString](tests/EchoString/EchoString.ino) + by unknown author: This example code is in the public domain. +* [LinkStatus](tests/LinkStatus/LinkStatus.ino) + by _Cristian Maglie_: This example code is in the public domain. +* [TFTBitmapLogo](tests/TFTBitmapLogo/TFTBitmapLogo.ino) + by _Enrico Gueli_: This example code is in the public domain. +* [TwoPortReceive](tests/TwoPortReceive/TwoPortReceive.ino) + by _Mikal Hart_ and _Tom Igoe_: this example code is in the public domain. + [arduino-avr]: https://github.com/arduino/ArduinoCore-avr diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c6f989b..6dc1a89 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -76,4 +76,21 @@ function(arduino_cli_toolchain_add_test NAME) endforeach() endfunction() +# ====================================================================================================================== +# the actual tests +# ====================================================================================================================== + +# A very minimal sketch without any additional dependencies arduino_cli_toolchain_add_test(CMakeBlink) + +# Some sketches from Arduino examples that use one single core library +arduino_cli_toolchain_add_test(DigitalPotControl SKIP attiny43) # some pins are mising for attiny43 +arduino_cli_toolchain_add_test(TwoPortReceive SKIP nano_33_iot nodemcu-32s) # no SoftwareSerial for samd and esp32 + +# Some sketches from Arduino examples that use core libraries which depend on other core libraries +arduino_cli_toolchain_add_test(EchoString) +arduino_cli_toolchain_add_test(LinkStatus) +arduino_cli_toolchain_add_test(TFTBitmapLogo) + +# TBD: A sketch which uses multiple independent libraries +# TDB: A sketch with complex directory structure: multiple .ino files, multiple .cpp files, src folder diff --git a/tests/DigitalPotControl/CMakeLists.txt b/tests/DigitalPotControl/CMakeLists.txt new file mode 100644 index 0000000..df4d544 --- /dev/null +++ b/tests/DigitalPotControl/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project(DigitalPotControl LANGUAGES CXX) +add_executable(DigitalPotControl DigitalPotControl.ino) diff --git a/tests/DigitalPotControl/DigitalPotControl.ino b/tests/DigitalPotControl/DigitalPotControl.ino new file mode 100644 index 0000000..39e5bf9 --- /dev/null +++ b/tests/DigitalPotControl/DigitalPotControl.ino @@ -0,0 +1,73 @@ +/* + Digital Pot Control + + This example controls an Analog Devices AD5206 digital potentiometer. + The AD5206 has 6 potentiometer channels. Each channel's pins are labeled + A - connect this to voltage + W - this is the pot's wiper, which changes when you set it + B - connect this to ground. + + The AD5206 is SPI-compatible,and to command it, you send two bytes, + one with the channel number (0 - 5) and one with the resistance value for the + channel (0 - 255). + + The circuit: + * All A pins of AD5206 connected to +5V + * All B pins of AD5206 connected to ground + * An LED and a 220-ohm resistor in series connected from each W pin to ground + * CS - to digital pin 10 (SS pin) + * SDI - to digital pin 11 (MOSI pin) + * CLK - to digital pin 13 (SCK pin) + + created 10 Aug 2010 + by Tom Igoe + + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 + +*/ + + +// include the SPI library: +#include + + +// set pin 10 as the slave select for the digital pot: +const int slaveSelectPin = 10; + +void setup() { + // set the slaveSelectPin as an output: + pinMode(slaveSelectPin, OUTPUT); + // initialize SPI: + SPI.begin(); +} + +void loop() { + // go through the six channels of the digital pot: + for (int channel = 0; channel < 6; channel++) { + // change the resistance on this channel from min to max: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, level); + delay(10); + } + // wait a second at the top: + delay(100); + // change the resistance on this channel from max to min: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, 255 - level); + delay(10); + } + } + +} + +void digitalPotWrite(int address, int value) { + // take the SS pin low to select the chip: + digitalWrite(slaveSelectPin, LOW); + delay(100); + // send in the address and value via SPI: + SPI.transfer(address); + SPI.transfer(value); + delay(100); + // take the SS pin high to de-select the chip: + digitalWrite(slaveSelectPin, HIGH); +} diff --git a/tests/EchoString/CMakeLists.txt b/tests/EchoString/CMakeLists.txt new file mode 100644 index 0000000..cc533ac --- /dev/null +++ b/tests/EchoString/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project(EchoString LANGUAGES CXX) +add_executable(EchoString EchoString.ino) diff --git a/tests/EchoString/EchoString.ino b/tests/EchoString/EchoString.ino new file mode 100644 index 0000000..e1651d5 --- /dev/null +++ b/tests/EchoString/EchoString.ino @@ -0,0 +1,44 @@ +/* + * Firmata is a generic protocol for communicating with microcontrollers + * from software on a host computer. It is intended to work with + * any host computer software package. + * + * To download a host software package, please click on the following link + * to open the list of Firmata client libraries in your default browser. + * + * https://github.com/firmata/arduino#firmata-client-libraries + */ + +/* This sketch accepts strings and raw sysex messages and echos them back. + * + * This example code is in the public domain. + */ +#include + +void stringCallback(char *myString) +{ + Firmata.sendString(myString); +} + + +void sysexCallback(byte command, byte argc, byte *argv) +{ + Firmata.sendSysex(command, argc, argv); +} + +void setup() +{ + Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION); + Firmata.attach(STRING_DATA, stringCallback); + Firmata.attach(START_SYSEX, sysexCallback); + Firmata.begin(57600); +} + +void loop() +{ + while (Firmata.available()) { + Firmata.processInput(); + } +} + + diff --git a/tests/LinkStatus/CMakeLists.txt b/tests/LinkStatus/CMakeLists.txt new file mode 100644 index 0000000..2e384e8 --- /dev/null +++ b/tests/LinkStatus/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project(LinkStatus LANGUAGES CXX) +add_executable(LinkStatus LinkStatus.ino) diff --git a/tests/LinkStatus/LinkStatus.ino b/tests/LinkStatus/LinkStatus.ino new file mode 100644 index 0000000..84651d0 --- /dev/null +++ b/tests/LinkStatus/LinkStatus.ino @@ -0,0 +1,44 @@ +/* + Link Status + + This sketch prints the Ethernet link status. When the + Ethernet cable is connected the link status should go to "ON". + NOTE: Only WIZnet W5200 and W5500 are capable of reporting + the link status. W5100 will report "Unknown". + Hardware: + - Ethernet shield or equivalent board/shield with WIZnet W5200/W5500 + Written by Cristian Maglie + This example is public domain. +*/ + +#include +#include + +void setup() { + // You can use Ethernet.init(pin) to configure the CS pin + //Ethernet.init(10); // Most Arduino shields + //Ethernet.init(5); // MKR ETH Shield + //Ethernet.init(0); // Teensy 2.0 + //Ethernet.init(20); // Teensy++ 2.0 + //Ethernet.init(15); // ESP8266 with Adafruit FeatherWing Ethernet + //Ethernet.init(33); // ESP32 with Adafruit FeatherWing Ethernet + + Serial.begin(9600); +} + +void loop() { + auto link = Ethernet.linkStatus(); + Serial.print("Link status: "); + switch (link) { + case Unknown: + Serial.println("Unknown"); + break; + case LinkON: + Serial.println("ON"); + break; + case LinkOFF: + Serial.println("OFF"); + break; + } + delay(1000); +} diff --git a/tests/TFTBitmapLogo/CMakeLists.txt b/tests/TFTBitmapLogo/CMakeLists.txt new file mode 100644 index 0000000..ee8eaac --- /dev/null +++ b/tests/TFTBitmapLogo/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project(TFTBitmapLogo LANGUAGES CXX) +add_executable(TFTBitmapLogo TFTBitmapLogo.ino) diff --git a/tests/TFTBitmapLogo/TFTBitmapLogo.ino b/tests/TFTBitmapLogo/TFTBitmapLogo.ino new file mode 100644 index 0000000..c6cb3c5 --- /dev/null +++ b/tests/TFTBitmapLogo/TFTBitmapLogo.ino @@ -0,0 +1,108 @@ +/* + + Arduino TFT Bitmap Logo example + + This example reads an image file from a micro-SD card + and draws it on the screen, at random locations. + + In this sketch, the Arduino logo is read from a micro-SD card. + There is a .bmp file included with this sketch. + - open the sketch folder (Ctrl-K or Cmd-K) + - copy the "colors.bmp" file to a micro-SD + - put the SD into the SD slot of the Arduino TFT module. + + This example code is in the public domain. + + Created 19 April 2013 by Enrico Gueli + + http://www.arduino.cc/en/Tutorial/TFTBitmapLogo + + */ + +// include the necessary libraries +#include +#include +#include // Arduino LCD library + +// pin definition for the Uno +#define sd_cs 4 +#define lcd_cs 10 +#define dc 9 +#define rst 8 + +// pin definition for the Leonardo +//#define sd_cs 8 +//#define lcd_cs 7 +//#define dc 0 +//#define rst 1 + +TFT TFTscreen = TFT(lcd_cs, dc, rst); + +// this variable represents the image to be drawn on screen +PImage logo; + + +void setup() { + // initialize the GLCD and show a message + // asking the user to open the serial line + TFTscreen.begin(); + TFTscreen.background(255, 255, 255); + + TFTscreen.stroke(0, 0, 255); + TFTscreen.println(); + TFTscreen.println(F("Arduino TFT Bitmap Example")); + TFTscreen.stroke(0, 0, 0); + TFTscreen.println(F("Open serial monitor")); + TFTscreen.println(F("to run the sketch")); + + // initialize the serial port: it will be used to + // print some diagnostic info + Serial.begin(9600); + while (!Serial) { + // wait for serial port to connect. Needed for native USB port only + } + + // clear the GLCD screen before starting + TFTscreen.background(255, 255, 255); + + // try to access the SD card. If that fails (e.g. + // no card present), the setup process will stop. + Serial.print(F("Initializing SD card...")); + if (!SD.begin(sd_cs)) { + Serial.println(F("failed!")); + return; + } + Serial.println(F("OK!")); + + // initialize and clear the GLCD screen + TFTscreen.begin(); + TFTscreen.background(255, 255, 255); + + // now that the SD card can be access, try to load the + // image file. + logo = TFTscreen.loadImage("colors.bmp"); + if (!logo.isValid()) { + Serial.println(F("error while loading colors.bmp")); + } +} + +void loop() { + // don't do anything if the image wasn't loaded correctly. + if (logo.isValid() == false) { + return; + } + + Serial.println(F("drawing image")); + + // get a random location where to draw the image. + // To avoid the image to be draw outside the screen, + // take into account the image size. + int x = random(TFTscreen.width() - logo.width()); + int y = random(TFTscreen.height() - logo.height()); + + // draw the image to the screen + TFTscreen.image(logo, x, y); + + // wait a little bit before drawing again + delay(1500); +} diff --git a/tests/TFTBitmapLogo/colors.bmp b/tests/TFTBitmapLogo/colors.bmp new file mode 100644 index 0000000000000000000000000000000000000000..993b2e17b2e0d1548152f891d4400e3398db1685 GIT binary patch literal 6966 zcmcgxTXHHn43)p9NTB9ts%8W8!y`X;0rL-pg^<8PAYmcA7D56GAqgwc9NTRp+uiOa z_ufezT(T^?53(ei&cDMSf0Oz9f%YGK2E|9wUq(+D|ML&~u?n;urY_T%Y0k7@wPiXn zotgNP_&~fTej%O`Pl)@(cWtHt(~#+zX~nc=dS|-8{6hRrye57nekL9gKM=Qxsm0W1 znlMe7UYPbw2d2+6@rig#yda(vkBPg)9hi3=pBdAVX`AQMx@UUG@YxWr1fTmHpQGb5 zlYGX;IcVqFKM9{*hqiQ&mziq{q<`x74=6wB=J+i2mW~=zAw$MV!w{AKF?)+)@Rd`@c@JjCg%JqjUT1s z`Qpy6Rqc6^_s^sG?s%LRAYZ#m%NBj&#_=y4)<;03l-1KFy!+1s^Q(vryL+);Gk@ zsjU9!Uz8RbCwNVuS69o(AnIEGjC?%bHS|x{?iZ#1s}})9T;Z(6YyC&K0WInOpGv6u_iKzyGnZ_QbIGZ_d~m1k4#T4o&!D$$ERzq z+xk}d`*5GTubxWd8B;9UPVkx4AX8*V?-K8h8z zjF;O&6Uovz8nS$P<{vANs}LFJu6Y;g?Y)5&WUFmL<8+qSK +// software serial #1: RX = digital pin 10, TX = digital pin 11 +SoftwareSerial portOne(10, 11); + +// software serial #2: RX = digital pin 8, TX = digital pin 9 +// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega +SoftwareSerial portTwo(8, 9); + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + + // Start each software serial port + portOne.begin(9600); + portTwo.begin(9600); +} + +void loop() { + // By default, the last initialized port is listening. + // when you want to listen on a port, explicitly select it: + portOne.listen(); + Serial.println("Data from port one:"); + // while there is data coming in, read it + // and send to the hardware serial port: + while (portOne.available() > 0) { + char inByte = portOne.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); + + // Now listen on the second port + portTwo.listen(); + // while there is data coming in, read it + // and send to the hardware serial port: + Serial.println("Data from port two:"); + while (portTwo.available() > 0) { + char inByte = portTwo.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); +}