Skip to content
Permalink
Browse files

cmake: Add Arduino cross-compiling and package gen

Add a `hydrogen-arduino-package` target which generates
`hydrogen-crypto.zip` for inclusion into Arduino Sketch projects.

Add a toolchain file for Arduino/AVR. Passing
`-DCMAKE_TOOLCHAIN_FILE=cmake/arduino-avr-toolchain.cmake` to the CMake
command line configures cross-compilation for Arduino. A target device
identifier can be specified via `-DARDUINO_AVR_TARGET_DEVICE=...`
(default: `atmega328p`), which configures -mmcu=... and enables the
appropriate `HYDRO_TARGET_DEVICE_*` C preprocessor flag (e.g.,
`HYDRO_TARGET_DEVICE_ATMEGA328`). The path to the Arduino SDK home
directory can be specified via `-DARDUINO_AVR_SDK_DIR=...`; if not set,
the toolchain file checks for the `ARDUINO_SDK_PATH` environment
variable, and then guesses a few locations based on the host OS (e.g.,
`/Applications/Arduino.app/Contents/Java` for macOS).
  • Loading branch information...
spinda committed Apr 29, 2019
1 parent c96f387 commit da795dafb7265e1bd06683b747a3b0d2284fa7d0
Showing with 145 additions and 1 deletion.
  1. +0 −1 .gitignore
  2. +19 −0 CMakeLists.txt
  3. +126 −0 cmake/arduino-avr-toolchain.cmake
@@ -1,5 +1,4 @@
*.bc
*.cmake
*.dSYM
*.done
*.final
@@ -37,6 +37,9 @@ set(header_files
set(test_files
"tests/tests.c")

set(arduino_files
"library.properties")

# Compile options

get_setting(target_arch STRING "Target system architecture (fed to the compiler's -march=...).")
@@ -77,6 +80,7 @@ endfunction()
prefix_project_paths(source_files)
prefix_project_paths(header_files)
prefix_project_paths(test_files)
prefix_project_paths(arduino_files)

# Main library

@@ -163,3 +167,18 @@ else()
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
add_custom_target("${tests_run_target}" ALL DEPENDS "${tests_run_file}")
endif()

# Generate Arduino package

set(arduino_package_file "${PROJECT_BINARY_DIR}/hydrogen-crypto.zip")

# Use the relative versions of the file path lists or else the full paths will
# end up in the generated archive.
add_custom_command(OUTPUT "${arduino_package_file}"
COMMAND cmake
ARGS -E tar cf "${arduino_package_file}" --format=zip
-- ${source_files} ${header_files} ${arduino_files}
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}")

add_custom_target("${PROJECT_NAME}-arduino-package"
DEPENDS "${arduino_package_file}")
@@ -0,0 +1,126 @@
# Cross-compilation file for the Arduino/AVR toolchain.

# To use, pass -DCMAKE_TOOLCHAIN_FILE=cmake/arduino-avr-toolchain.cmake in your
# CMake command line.

cmake_minimum_required(VERSION 3.12)

set(setting_prefix ARDUINO_AVR)
function(get_setting setting_name setting_type setting_description)
string(TOUPPER "${setting_prefix}_${setting_name}" setting_external_name)
set("${setting_external_name}" "" CACHE "${setting_type}" "${setting_description}")
set("${setting_name}" "${${setting_external_name}}" PARENT_SCOPE)
endfunction()

# Target device setting

get_setting(target_device STRING "Target Arduino device MCU identifier.")
if(NOT target_device)
set(target_device atmega328p)
endif()

if("${target_device}" STREQUAL atmega328p)
set(hw_type ATMEGA328)
else()
message(FATAL_ERROR "Unrecognized ${setting_prefix}_TARGET_DEVICE value ${target_device}")
endif()

# Find Arduino SDK home

get_setting(sdk_dir PATH "Arduino SDK home directory.")

# Try ARDUINO_SDK_PATH environment variable.
if(NOT sdk_dir)
if(DEFINED ENV{ARDUINO_SDK_PATH})
set(sdk_dir "$ENV{ARDUINO_SDK_PATH}")
endif()
endif()

# Try some platform-specific guesses.
if(NOT sdk_dir)
# Windows
if(WIN32)
list(APPEND arduino_home_dir_guesses
"C:/Program Files (x86)/Arduino"
"C:/Program Files/Arduino")
endif()

# macOS
if(APPLE)
list(APPEND arduino_home_dir_guesses
"/Applications/Arduino.app/Contents/Java")
endif()

# Linux/Unix
if(UNIX AND NOT APPLE)
list(APPEND arduino_home_dir_guesses
"/usr/share/arduino"
"/usr/local/share/arduino")
endif()

if(DEFINED arduino_home_dir_guesses)
foreach(arduino_home_dir_guess IN LISTS arduino_home_dir_guesses)
if(IS_DIRECTORY "${arduino_home_dir_guess}")
set(sdk_dir "${arduino_home_dir_guess}")
break()
endif()
endforeach()
endif()
endif()

if(NOT sdk_dir)
message(FATAL_ERROR
"Couldn't determine Arduino SDK home directory. "
"Try passing -D${setting_prefix}_SDK_DIR=... to the CMake command line, or "
"set the ARDUINO_SDK_PATH environment variable.")
endif()

# Locate toolchain programs

set(arduino_tools_dir "${sdk_dir}/hardware/tools/avr/bin")
set(program_prefix "${setting_prefix}_PROGRAM")
function(find_in_toolchain program_name)
string(TOUPPER "${program_prefix}_${program_name}" program_external_name)
string(REPLACE "_" "-" program_file_name "${program_name}")

find_program("${program_external_name}" "${program_file_name}"
PATHS "${arduino_tools_dir}" NO_DEFAULT_PATH)

if("${${program_external_name}}" STREQUAL "${program_external_name}-NOTFOUND")
message(FATAL_ERROR
"Couldn't find program ${program_file_name} "
"in Arduino/AVR toolchain at ${arduino_tools_dir}")
else()
set("${program_name}" "${${program_external_name}}" PARENT_SCOPE)
endif()
endfunction()

find_in_toolchain(avr_gcc)
find_in_toolchain(avr_gcc_ranlib)
find_in_toolchain(avr_gcc_ar)

# Configure CMake toolchain settings

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER "${avr_gcc}")
set(CMAKE_ASM_COMPILER "${avr_gcc}")
set(CMAKE_RANLIB "${avr_gcc_ranlib}")
set(CMAKE_AR "${avr_gcc_ar}")

SET(CMAKE_C_OUTPUT_EXTENSION .o)
SET(CMAKE_ASM_OUTPUT_EXTENSION .o)

# Add compile flags

string(APPEND CMAKE_C_FLAGS
" -mmcu=${target_device} -Os -mcall-prologues -fno-exceptions"
" -ffunction-sections -fdata-sections -flto"
" -DHYDRO_TARGET_DEVICE_${hw_type}")

# Add include directories

include_directories(SYSTEM
"${sdk_dir}/hardware/arduino/avr/cores/arduino"
"${sdk_dir}/hardware/arduino/avr/variants/standard"
"${sdk_dir}/hardware/arduino/cores/arduino"
"${sdk_dir}/hardware/arduino/variants/standard")

0 comments on commit da795da

Please sign in to comment.
You can’t perform that action at this time.