├── .gitignore
├── .vscode
└── cmake-kits.json
├── CMakeLists.txt
├── LICENSE
├── README.md
├── blink.cpp
├── cmake
├── arduino_core.cmake
├── arduino_hex.cmake
├── arduino_upload.cmake
├── lto.cmake
└── toolchain
│ ├── avr.toolchain.cmake
│ ├── leonardo.toolchain.cmake
│ ├── mega.toolchain.cmake
│ └── uno.toolchain.cmake
└── images
├── selecting.png
└── uploading.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache
2 | build
--------------------------------------------------------------------------------
/.vscode/cmake-kits.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Leonardo",
4 | "toolchainFile": "${workspaceFolder}/cmake/toolchain/leonardo.toolchain.cmake"
5 | },
6 | {
7 | "name": "UNO",
8 | "toolchainFile": "${workspaceFolder}/cmake/toolchain/uno.toolchain.cmake"
9 | },
10 | {
11 | "name": "Mega 2560",
12 | "toolchainFile": "${workspaceFolder}/cmake/toolchain/mega.toolchain.cmake"
13 | }
14 | ]
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 | project(Blink LANGUAGES C CXX ASM)
3 |
4 | include(cmake/lto.cmake)
5 | include(cmake/arduino_core.cmake)
6 | include(cmake/arduino_hex.cmake)
7 | include(cmake/arduino_upload.cmake)
8 |
9 | add_executable(blink blink.cpp)
10 | target_link_libraries(blink PUBLIC ArduinoCore)
11 | target_compile_options(blink PRIVATE
12 | "-Wall"
13 | "-Wextra"
14 | "-pedantic"
15 | )
16 | arduino_avr_hex(blink)
17 |
18 | set(ARDUINO_PORT "/dev/ttyACM0"
19 | CACHE STRING "The serial port for uploading using avrdude")
20 | arduino_avr_upload(blink ${ARDUINO_PORT})
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 PieterP
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Arduino AVR CMake
2 |
3 | Compile Arduino AVR programs using CMake.
4 |
5 | ## Instructions
6 |
7 | 1. Clone this repository and open a terminal in the `Arduino-AVR-CMake` folder.
8 | 2. Ensure that the Arduino AVR core is installed correctly, this guide assumes
9 | that the core is in `~/.arduino15/packages/arduino/hardware/avr/1.8.6`,
10 | that the toolchain is in `~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7`,
11 | and that avrdude is in `~/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17`.
12 | If this is not the case, change it now in `cmake/toolchain/avr.toolchain.cmake`.
13 | 3. Configure the project using CMake by running the following command:
14 | ```sh
15 | cmake -S. -Bbuild \
16 | -D ARDUINO_PORT=/dev/ttyACM0 \
17 | -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/uno.toolchain.cmake \
18 | -D CMAKE_BUILD_TYPE=MinSizeRel
19 | ```
20 | Customize the port, toolchain file, and build type for your specific
21 | configuration.
22 | 4. Finally, build and upload the example “blink” program:
23 | ```sh
24 | cmake --build build -j -t upload-blink
25 | ```
26 | To compile the program without uploading, you can use
27 | ```sh
28 | cmake --build build -j -t blink
29 | ```
30 | If you're using an Arduino with a native USB interface (e.g. Leonardo),
31 | you'll have to press the reset button before uploading. You could
32 | automate this by opening its serial port at 1200 baud as part of the
33 | upload process.
34 |
35 | ## VSCode
36 |
37 | In VSCode, you can select the board you want to use using the
38 | `CMake: Select a Kit` command from the CMake Tools extension.
39 | Then select the right board as shown in the following image:
40 | 
41 |
42 | To build the sketch, you can either press F7 or click the `Build`
43 | button in the bottom ribbon or in the CMake side panel. To upload, you can use
44 | the `upload-blink` utility in the CMake side panel:
45 | 
46 |
--------------------------------------------------------------------------------
/blink.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | void setup() {
4 | Serial.begin(115200);
5 | delay(2000);
6 | Serial.println("Hello, world!");
7 | pinMode(LED_BUILTIN, OUTPUT);
8 | }
9 |
10 | void loop() {
11 | digitalWrite(LED_BUILTIN, HIGH);
12 | delay(500);
13 | digitalWrite(LED_BUILTIN, LOW);
14 | delay(500);
15 | }
16 |
--------------------------------------------------------------------------------
/cmake/arduino_core.cmake:
--------------------------------------------------------------------------------
1 | if(NOT ARDUINO_PATH)
2 | message(FATAL_ERROR "Arduino-specific variables are not set. \
3 | Did you select the right toolchain file?")
4 | endif()
5 |
6 | # Basic compilation flags
7 | add_library(ArduinoFlags INTERFACE)
8 | target_compile_options(ArduinoFlags INTERFACE
9 | "-fno-exceptions"
10 | "-ffunction-sections"
11 | "-fdata-sections"
12 | "$<$:-fno-threadsafe-statics>"
13 | "-mmcu=${ARDUINO_MCU}"
14 | )
15 | target_compile_definitions(ArduinoFlags INTERFACE
16 | "F_CPU=${ARDUINO_F_CPU}"
17 | "ARDUINO=${ARDUINO_VERSION}"
18 | "ARDUINO_${ARDUINO_BOARD}"
19 | "ARDUINO_ARCH_AVR"
20 | )
21 | target_link_options(ArduinoFlags INTERFACE
22 | "-mmcu=${ARDUINO_MCU}"
23 | "-fuse-linker-plugin"
24 | "LINKER:--gc-sections"
25 | )
26 | target_compile_features(ArduinoFlags INTERFACE cxx_std_11 c_std_11)
27 |
28 | # Arduino Core
29 | add_library(ArduinoCore STATIC
30 | ${ARDUINO_CORE_PATH}/abi.cpp
31 | ${ARDUINO_CORE_PATH}/CDC.cpp
32 | ${ARDUINO_CORE_PATH}/HardwareSerial0.cpp
33 | ${ARDUINO_CORE_PATH}/HardwareSerial1.cpp
34 | ${ARDUINO_CORE_PATH}/HardwareSerial2.cpp
35 | ${ARDUINO_CORE_PATH}/HardwareSerial3.cpp
36 | ${ARDUINO_CORE_PATH}/HardwareSerial.cpp
37 | ${ARDUINO_CORE_PATH}/IPAddress.cpp
38 | ${ARDUINO_CORE_PATH}/main.cpp
39 | ${ARDUINO_CORE_PATH}/new.cpp
40 | ${ARDUINO_CORE_PATH}/PluggableUSB.cpp
41 | ${ARDUINO_CORE_PATH}/Print.cpp
42 | ${ARDUINO_CORE_PATH}/Stream.cpp
43 | ${ARDUINO_CORE_PATH}/Tone.cpp
44 | ${ARDUINO_CORE_PATH}/USBCore.cpp
45 | ${ARDUINO_CORE_PATH}/WMath.cpp
46 | ${ARDUINO_CORE_PATH}/WString.cpp
47 | ${ARDUINO_CORE_PATH}/hooks.c
48 | ${ARDUINO_CORE_PATH}/WInterrupts.c
49 | ${ARDUINO_CORE_PATH}/wiring_analog.c
50 | ${ARDUINO_CORE_PATH}/wiring.c
51 | ${ARDUINO_CORE_PATH}/wiring_digital.c
52 | ${ARDUINO_CORE_PATH}/wiring_pulse.c
53 | ${ARDUINO_CORE_PATH}/wiring_shift.c
54 | ${ARDUINO_CORE_PATH}/wiring_pulse.S
55 | )
56 | target_link_libraries(ArduinoCore PUBLIC ArduinoFlags)
57 | target_compile_features(ArduinoCore PUBLIC cxx_std_11 c_std_11)
58 | target_include_directories(ArduinoCore PUBLIC
59 | ${ARDUINO_CORE_PATH}
60 | ${ARDUINO_AVR_PATH}/variants/${ARDUINO_VARIANT}
61 | )
62 | if(ARDUINO_USB)
63 | target_compile_definitions(ArduinoCore PUBLIC
64 | USB_VID=${ARDUINO_USB_VID}
65 | USB_PID=${ARDUINO_USB_PID}
66 | USB_MANUFACTURER=\"Unknown\"
67 | USB_PRODUCT=\"${ARDUINO_USB_PRODUCT}\"
68 | )
69 | endif()
--------------------------------------------------------------------------------
/cmake/arduino_hex.cmake:
--------------------------------------------------------------------------------
1 | # Transforms the target.elf file into target.eep (EEPROM) and target.hex files.
2 | # Also prints the size of each section in target.elf.
3 | function(arduino_avr_hex target)
4 | set_target_properties(${target} PROPERTIES SUFFIX ".elf")
5 | add_custom_command(TARGET ${target} POST_BUILD
6 | COMMAND ${CMAKE_SIZE} ARGS
7 | -A "$"
8 | USES_TERMINAL)
9 | add_custom_command(TARGET ${target} POST_BUILD
10 | BYPRODUCTS ${target}.eep
11 | COMMAND ${CMAKE_OBJCOPY} ARGS
12 | -O ihex -j .eeprom
13 | --set-section-flags=.eeprom=alloc,load
14 | --no-change-warnings --change-section-lma
15 | .eeprom=0
16 | "$"
17 | ${target}.eep)
18 | add_custom_command(TARGET ${target} POST_BUILD
19 | BYPRODUCTS ${target}.hex
20 | COMMAND ${CMAKE_OBJCOPY} ARGS
21 | -O ihex -R .eeprom
22 | "$"
23 | ${target}.hex)
24 | endfunction()
--------------------------------------------------------------------------------
/cmake/arduino_upload.cmake:
--------------------------------------------------------------------------------
1 | # Creates a target upload-target that uses avrdude to upload target.hex to the
2 | # given serial port.
3 | function(arduino_avr_upload target port)
4 | add_custom_target(upload-${target}
5 | COMMAND ${ARDUINO_AVRDUDE}
6 | -C${ARDUINO_AVRDUDE_CONF}
7 | -p${ARDUINO_MCU}
8 | -c${ARDUINO_AVRDUDE_PROTOCOL}
9 | -P${port}
10 | -b${ARDUINO_AVRDUDE_SPEED}
11 | -D
12 | "-Uflash:w:$.hex:i"
13 | USES_TERMINAL)
14 | add_dependencies(upload-${target} ${target})
15 | endfunction()
--------------------------------------------------------------------------------
/cmake/lto.cmake:
--------------------------------------------------------------------------------
1 | # Enables interprocedural optimization (link-time optimization) globally if
2 | # available.
3 | include(CheckIPOSupported)
4 | check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
5 | if(ipo_supported)
6 | set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
7 | else()
8 | message(STATUS "IPO / LTO not supported: ${ipo_error}")
9 | endif()
--------------------------------------------------------------------------------
/cmake/toolchain/avr.toolchain.cmake:
--------------------------------------------------------------------------------
1 | # Enter CMake cross-compilation mode
2 | set(CMAKE_SYSTEM_NAME Generic)
3 | set(CMAKE_SYSTEM_PROCESSOR avr)
4 |
5 | # User settings with sensible defaults
6 | set(ARDUINO_PATH "$ENV{HOME}/.arduino15/packages/arduino" CACHE PATH
7 | "Path of the Arduino packages folder, e.g. ~/.arduino15/packages/arduino.")
8 | set(ARDUINO_CORE_VERSION "1.8.6" CACHE STRING
9 | "Version of arduino/ArduinoCore-AVR")
10 | set(AVR_GCC_VERSION "7.3.0-atmel3.6.1-arduino7" CACHE STRING
11 | "Full version string of the GCC release shipped with the Arduino core.")
12 | set(AVRDUDE_VERSION "6.3.0-arduino17" CACHE STRING
13 | "Full version string of the avrdude release shipped with the Arduino core.")
14 | set(ARDUINO_VERSION "10815" CACHE STRING
15 | "Arduino IDE version (used for the macro with the same name)")
16 |
17 | # Derived paths
18 | set(ARDUINO_AVR_PATH ${ARDUINO_PATH}/hardware/avr/${ARDUINO_CORE_VERSION})
19 | set(ARDUINO_CORE_PATH ${ARDUINO_AVR_PATH}/cores/arduino)
20 | set(ARDUINO_TOOLS_PATH ${ARDUINO_PATH}/tools/avr-gcc/${AVR_GCC_VERSION}/bin)
21 | set(ARDUINO_AVRDUDE_PATH ${ARDUINO_PATH}/tools/avrdude/${AVRDUDE_VERSION})
22 | set(ARDUINO_AVRDUDE_CONF ${ARDUINO_AVRDUDE_PATH}/etc/avrdude.conf)
23 |
24 | # Toolchain paths
25 | set(CMAKE_C_COMPILER ${ARDUINO_TOOLS_PATH}/avr-gcc CACHE FILEPATH
26 | "Path to avr-gcc" FORCE)
27 | set(CMAKE_CXX_COMPILER ${ARDUINO_TOOLS_PATH}/avr-g++ CACHE FILEPATH
28 | "Path to avr-g++" FORCE)
29 | set(CMAKE_OBJCOPY ${ARDUINO_TOOLS_PATH}/avr-objcopy CACHE FILEPATH
30 | "Path to avr-objcopy" FORCE)
31 | set(CMAKE_SIZE ${ARDUINO_TOOLS_PATH}/avr-size CACHE FILEPATH
32 | "Path to avr-size" FORCE)
33 | set(ARDUINO_AVRDUDE ${ARDUINO_AVRDUDE_PATH}/bin/avrdude CACHE FILEPATH
34 | "Path to avrdude" FORCE)
35 |
36 | # Only look libraries etc. in the sysroot, but never look there for programs
37 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
38 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
39 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
40 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
41 |
--------------------------------------------------------------------------------
/cmake/toolchain/leonardo.toolchain.cmake:
--------------------------------------------------------------------------------
1 | set(ARDUINO_BOARD "AVR_LEONARDO")
2 | set(ARDUINO_MCU "atmega32u4")
3 | set(ARDUINO_F_CPU "16000000L")
4 | set(ARDUINO_VARIANT "leonardo")
5 | set(ARDUINO_AVRDUDE_PROTOCOL "avr109")
6 | set(ARDUINO_AVRDUDE_SPEED "57600")
7 | set(ARDUINO_USB On)
8 | set(ARDUINO_USB_VID "0x2341")
9 | set(ARDUINO_USB_PID "0x8036")
10 | set(ARDUINO_USB_PRODUCT "Arduino Leonardo")
11 |
12 | include(${CMAKE_CURRENT_LIST_DIR}/avr.toolchain.cmake)
--------------------------------------------------------------------------------
/cmake/toolchain/mega.toolchain.cmake:
--------------------------------------------------------------------------------
1 | set(ARDUINO_BOARD "AVR_MEGA2560")
2 | set(ARDUINO_MCU "atmega2560")
3 | set(ARDUINO_F_CPU "16000000L")
4 | set(ARDUINO_VARIANT "mega")
5 | set(ARDUINO_AVRDUDE_PROTOCOL "wiring")
6 | set(ARDUINO_AVRDUDE_SPEED "115200")
7 | set(ARDUINO_USB Off)
8 |
9 | include(${CMAKE_CURRENT_LIST_DIR}/avr.toolchain.cmake)
--------------------------------------------------------------------------------
/cmake/toolchain/uno.toolchain.cmake:
--------------------------------------------------------------------------------
1 | set(ARDUINO_BOARD "AVR_UNO")
2 | set(ARDUINO_MCU "atmega328p")
3 | set(ARDUINO_F_CPU "16000000L")
4 | set(ARDUINO_VARIANT "standard")
5 | set(ARDUINO_AVRDUDE_PROTOCOL "arduino")
6 | set(ARDUINO_AVRDUDE_SPEED "115200")
7 | set(ARDUINO_USB Off)
8 |
9 | include(${CMAKE_CURRENT_LIST_DIR}/avr.toolchain.cmake)
--------------------------------------------------------------------------------
/images/selecting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tttapa/Arduino-AVR-CMake/eb120a6a3cabedde245ffd673a91325a2ac5c998/images/selecting.png
--------------------------------------------------------------------------------
/images/uploading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tttapa/Arduino-AVR-CMake/eb120a6a3cabedde245ffd673a91325a2ac5c998/images/uploading.png
--------------------------------------------------------------------------------