Issue
I'm trying to write a CMakeLists.txt to compile my Arduino-Projects to get to know cmake better.
I defined the Arduino-Core library as an imported interface and try to link my own target against it. The problem is, that, when calling make
the avr-gcc is provided with the specified include-paths via -isystem
instead of -I
. This results in several errors.
CMakeLists.txt (minimal-version to reproduce the problem)
cmake_minimum_required(VERSION 3.1)
set(ARDUINO_DIR "/opt/arduino/arduino-1.8.13")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-gcc)
set(CMAKE_CXX_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-g++)
set(CMAKE_SYSTEM_NAME NONE)
set(CMAKE_SYSTEM_PROCESSOR NONE)
add_library(Arduino::Core INTERFACE IMPORTED)
target_include_directories(Arduino::Core INTERFACE
"${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/"
"${ARDUINO_DIR}/hardware/arduino/avr/variants/eightanaloginputs/"
)
file(GLOB_RECURSE ARDUINO_CORE_SRC "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.c[p]*")
file(GLOB_RECURSE ARDUINO_CORE_ASM "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.S")
target_sources(Arduino::Core INTERFACE ${ARDUINO_CORE_SRC} ${ARDUINO_CORE_ASM})
project(Blinky)
set(${PROJECT_NAME}_SRC
src/Blink.cpp
)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SRC})
target_link_libraries(${PROJECT_NAME} Arduino::Core)
Here is my Blink.cpp:
#include <Arduino.h>
void setup()
{
pinMode(13,OUTPUT);
}
void loop()
{
digitalWrite(13,HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
make --trace
gives me the following output:
[ 5%] Building CXX object CMakeFiles/Blinky.dir/src/Blink.cpp.obj
/opt/arduino/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/cores/arduino -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs -std=gnu++11 -o CMakeFiles/Blinky.dir/src/Blink.cpp.obj -c /tmp/so/src/Blink.cpp
As you can see, linking against the imported target includes the dependencies with -isystem
even though I haven't declared SYSTEM
anywhere? How can I prevent that?!
Is it, because it is an INTERFACE IMPORTED
target?
I tried taget_include_directories(Arduino::Core PRIVATE ${my_include_dirs})
but obviously that is not allowed for INTERFACE
-Targets.
Thanks in advance for every hint.
P.S. please note, that I'm aware, that this would not compile my arduino-code. This is just a mcve to show you my problem.
edit
I'm using Arduino-SDK 1.8.13 and cmake 3.18.2
Solution
It is because it is an imported target.
From the CMake docs on buildsystems at the section for "include directories and usage requirements" (one of the last paragraphs in the section):
When the
INTERFACE_INCLUDE_DIRECTORIES
of an imported target is consumed, the entries in the property are treated asSYSTEM
include directories, as if they were listed in theINTERFACE_SYSTEM_INCLUDE_DIRECTORIES
of the dependency. This can result in omission of compiler warnings for headers found in those directories. This behavior for Imported Targets may be controlled by setting theNO_SYSTEM_FROM_IMPORTED
target property on the consumers of imported targets, or by setting the IMPORTED_NO_SYSTEM target property on the imported targets themselves.
See the docs for include_directories
and target_include_directories
for other documentation on SYSTEM
.
As stated in the docs, you can solve this by modifying consumers of the imported target like set_target_property(${PROJECT_NAME} PROPERTIES NO_SYSTEM_FROM_IMPORTED TRUE)
or set_property(TARGET ${PROJECT_NAME} PROPERTY NO_SYSTEM_FROM_IMPORTED TRUE)
.
But there's another option not mentioned in the docs I quoted that I think may be better: In the docs for NO_SYSTEM_FROM_IMPORTED
, it says:
See the
IMPORTED_NO_SYSTEM
target property to set this behavior on the target providing the include directories rather than consuming them.
I think it's better because NO_SYSTEM_FROM_IMPORTED
will change the "system-ness" of all imported targets that the consumer links to, which may not be desirable. Perhaps a similar argument could be made against IMPORTED_NO_SYSTEM
, but I personally can't think of a good backing for such an argument at the moment.
Answered By - David Fong Answer Checked By - Cary Denson (WPSolving Admin)