a9183756-gh / Arduino-CMake-Toolchain

CMake toolchain for all Arduino compatible boards
MIT License
135 stars 40 forks source link

Arduino due produces newline in build command #25

Closed RobertWilbrandt closed 4 years ago

RobertWilbrandt commented 4 years ago

I am currently unable to compile any project (including the provided examples) for the arduino Due board. I think i see (at least one place) where this comes from, but any help would be appreciated.

Problem Description

I successfully followed your Example and created a BoardOptions.cmake with the line for the arduino due uncommented:

set(ARDUINO_BOARD "Arduino Due (Programming Port) [sam.arduino_due_x_dbg]") # Arduino Due (Programming Port)

Running cmake again works correctly using the command:

cmake -D CMAKE_TOOLCHAIN_FILE=../Arduino-toolchain.cmake ../Examples

But now actually building the project fails:

>  cmake --build . --target upload-hello_world -- SERIAL_PORT=/dev/ttyUSB0
01_hello_world/CMakeFiles/_arduino_lib_core.dir/build.make:64: *** missing separator.  Stop.
CMakeFiles/Makefile2:157: recipe for target '01_hello_world/CMakeFiles/_arduino_lib_core.dir/all' failed
make[2]: *** [01_hello_world/CMakeFiles/_arduino_lib_core.dir/all] Error 2
CMakeFiles/Makefile2:132: recipe for target '01_hello_world/CMakeFiles/upload-hello_world.dir/rule' failed
make[1]: *** [01_hello_world/CMakeFiles/upload-hello_world.dir/rule] Error 2
Makefile:131: recipe for target 'upload-hello_world' failed
make: *** [upload-hello_world] Error 2

Running the whole thing with Ninja instead of make (i.e. append ```-G Ninja to the cmake commands) yields the error

ninja: error: rules.ninja:29: expected '=', got identifier
 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0...
                   ^ near here

Incorrectly generated files

Checking the file from the make error description actually shows an incorrectly generated command:

[...]
59 
60 01_hello_world/CMakeFiles/_arduino_lib_core.dir/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c.o: 01_hello_world/CMakeFiles/_arduino_lib_core.dir/flags.make
61 01_hello_world/CMakeFiles/_arduino_lib_core.dir/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c.o: /home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c
62  @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/wilbrandt/projects/tracked_robot/arduino_firmware/Arduino-CMake-Toolchain/Examples_build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object 62 01_hello_world/CMakeFiles/_arduino_lib_core.dir/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c.o"
63  cd /home/wilbrandt/projects/tracked_robot/arduino_firmware/Arduino-CMake-Toolchain/Examples_build/01_hello_world && /home/wilbrandt/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc  -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf -MMD -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=2:10005+dfsg2-401
64  -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON "-DUSB_MANUFACTURER=\"Arduino LLC\"" "-DUSB_PRODUCT=\"Arduino Due\"" -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/libsam -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/CMSIS/Include/ -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/Device/ATMEL/ $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) /home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c -o CMakeFiles/_arduino_lib_core.dir/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/cores/arduino/WInterrupts.c.o
65 
[...]

(Notice the line break before the -DARDUINO_SAM_DUE flag). The ninja.rules file shows a similar error:

[...]
24 
25 rule CXX_COMPILER__hello_world
26   depfile = $DEP_FILE
27   deps = gcc
28   command = /home/wilbrandt/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-g++  -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=2:10005+dfsg2-401
29  -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON "-DUSB_MANUFACTURER=\"Arduino LLC\"" "-DUSB_PRODUCT=\"Arduino Due\"" -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/libsam -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/CMSIS/Include/ -I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/Device/ATMEL/ $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE $in -o $out
30   description = Building CXX object $out
[...]

Suspected Error Source

After browsing through the toolchain files i found this message call. Uncommenting it already showed the same problem:

> cmake -D CMAKE_TOOLCHAIN_FILE=../Arduino-toolchain.cmake ../Examples
-- Found Arduino Platform: /home/wilbrandt/.arduino15/packages/arduino/hardware/avr/1.8.2
-- Found Arduino Platform: /home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12
-- Selected Arduino Board: Arduino Due (Programming Port) [sam.arduino_due_x_dbg]
ARDUINO_RULE_recipe.c.o.pattern:"/home/wilbrandt/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc" -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf -MMD -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=2:10005+dfsg2-401
 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' "-I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/libsam" "-I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/CMSIS/Include/" "-I/home/wilbrandt/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/Device/ATMEL/" {includes} "{source_file}" -o "{object_file}"
-- The C compiler identification is GNU 4.8.3
-- The CXX compiler identification is GNU 4.8.3
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Detecting C compile features
-- Detecting C compile features - failed
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - failed
-- Detecting CXX compile features
-- Detecting CXX compile features - failed
-- The ASM compiler identification is GNU
-- Found assembler: /home/wilbrandt/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/wilbrandt/projects/tracked_robot/arduino_firmware/Arduino-CMake-Toolchain/Examples_build

This (and also testing the written CMAKE_C_COMPILE_OBJECT, which also has the newline) leads me to believe that the _resolve_build_rule_properties function doesn't handle newlines in its input correctly.

System

I am not quite sure which information is relevant to you, so i'll just post some system information here. I work on an ubuntu 18.04.4.

> cmake --version
cmake version 3.10.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).

I use the current Arduino IDE with version 1.8.12.

Miscellaneous

As i don't know too much about low-level CMake witchery any help would be appreciated. Thank you for providing this solution, it seems to be very neatly integrated (once it works for me) and looks like exactly the solution i was looking for.

a9183756-gh commented 4 years ago

Hey, Thanks for your analysis.

I tried "Arduino Due (Programming Port) [sam.arduino_due_x_dbg]" here and seems to be working well (with make). *** missing separator error seems cryptic. Wondering why there is a new line you reported. Suggest you to attach ArduinoSystem.cmake file (generated in the build directory). Will look for any inconsistencies there.

Regarding ninja, I wasn't successful with it on Windows earlier, and remember having some command line issues; but did not follow it up. Will check this when I find time, but let us try to resolve the issue with make first.

RobertWilbrandt commented 4 years ago

Hey,

i just dove deep into the BoardToolchain.cmake file and found i was kind of following the wrong lead. Looking at ArduinoSystem.cmake and stepping upwards from the _resolve_build_rule_properties calls, i found the actual source for this problem: The runtime.ide.version contained a newline at the end, which lead to multline commands at multiple recipes. This variable is read (almost) directly from ${ARDUINO_INSTALL_PATH}/lib/version.txt, which happens to end on a newline for me. You said you tried reproducing on windows - this seems like exactly the kind of bug that appears inconsistently between the platforms. I will create a PR for this shortly.

Fixing this issue lead to a new problem however, which for now actually appears to be due-specific: Now that the project successfully builds, i tried uploading to the board as described and got the following error message:

$ cmake --build . --target upload-hello_world -- SERIAL_PORT=/dev/ttyUSB0
[ 91%] Built target _arduino_lib_core
[ 97%] Built target hello_world
Scanning dependencies of target upload-hello_world
[100%] Uploading 'hello_world'
CMake Error at /home/wilbrandt/projects/tracked_robot/arduino_firmware/Arduino-CMake-Toolchain/Examples_build/FirmwareUpload.cmake:79 (message):

  Expected environment variable(s) not provided.  Usage as follows:

  Serial Upload: 'make SERIAL_PORT=<port> SERIAL_PORT_FILE=<serial.port.file>
  UPLOAD_VERIFY=<upload.verify> upload-hello_world'

  Network Upload: 'make upload-hello_world'

01_hello_world/CMakeFiles/upload-hello_world.dir/build.make:57: recipe for target '01_hello_world/CMakeFiles/upload-hello_world' failed
make[3]: *** [01_hello_world/CMakeFiles/upload-hello_world] Error 1
CMakeFiles/Makefile2:125: recipe for target '01_hello_world/CMakeFiles/upload-hello_world.dir/all' failed
make[2]: *** [01_hello_world/CMakeFiles/upload-hello_world.dir/all] Error 2
CMakeFiles/Makefile2:132: recipe for target '01_hello_world/CMakeFiles/upload-hello_world.dir/rule' failed
make[1]: *** [01_hello_world/CMakeFiles/upload-hello_world.dir/rule] Error 2
Makefile:131: recipe for target 'upload-hello_world' failed
make: *** [upload-hello_world] Error 2

Looking at my ArduinoSystem.cmake.txt (.txt ending as github doesn't like some file types), it seems that the {serial.port.file} variable isn't expanded properly. When looking at the different platform.txt files for avr and sam i am also not sure whether {upload.verify} is set correctly, as avr seems to have some special-casing for it. I will try looking into this further, if you have any insights please let me know.

a9183756-gh commented 4 years ago

Excellent find!!! Looks like the version file is not having new line in my installation. After opening and saving the file in Vim, newline got introduced and I could reproduce the same issue.

Regarding the upload issue, I think you may get further errors even if you try to fix the current issue. This is because of bossac tool used during upload, and this tool got fixed only in release-1.1-dev. Suggest you to clone release-1.1-dev and try this out.

git clone https://github.com/a9183756-gh/Arduino-CMake-Toolchain.git -b release-1.1-dev

You need to pass SERIAL_PORT_FILE=<port>, and not SERIAL_PORT=<port> The difference is that SERIAL_PORT_FILE takes only file part of device files i.e. it takes ttyUSB0 instead of /dev/ttyUSB0. Haven't tried this, but try both values and see which one works for you. It is possible to introduce a change to take SERIAL_PORT and transform it to SERIAL_PORT_FILE, rather than having to document this SERIAL_PORT_FILE variable.

RobertWilbrandt commented 4 years ago

Hey, thanks for the help. I am now a step further and can actually manually upload code to the arduino (using the 1.1 branch).

The problem i experience right now is the following:

$ cmake --build . --target upload -- TARGET=hello_world SERIAL_PORT_FILE=ttyACM0          
[100%] Uploading
[  3%] Built target _arduino_lib_core_vobjects_
[ 90%] Built target _arduino_lib_core_cobjects_
[ 93%] Built target _arduino_lib_core
[100%] Built target hello_world
Send auto-baud
Set binary mode
No device found on ttyACM0
CMake Error at .scripts/upload.cmake:374 (message):
  *** upload failed!

For completeness, here is the full bossac command used (shown using VERBOSE=1):

/home/wilbrandt/.arduino15/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i -d --port=ttyACM0 -U false -e -w -v -b "/home/wilbrandt/projects/tracked_robot/arduino_firmware/Arduino-CMake-Toolchain/Examples_build/01_hello_world/hello_world.bin" -R

But i was able to get it to upload using a command from this issue:

stty -F /dev/ttyACM0 speed 1200

consistently makes my upload work. I also checked the current BOSSA and arduino and master branch (the later required one changed argument) with the same results.

So for now i'll just run

stty -F /dev/ttyACM0 speed 1200 && cmake --build . --target upload -- TARGET=hello_world SERIAL_PORT_FILE=ttyACM0

, but it would be nice if this worked just from cmake (after all the ide upload works consistently and also states Forcing reset using 1200bps open/close on port /dev/ttyACM0 in its log). Do you have any idea how that could work?

a9183756-gh commented 4 years ago

1200bps reset is a gap in the toolchain and not yet supported. Supporting serial port related features (like serial port monitor, 1200bps reset etc.) in CMake (possibly using external tools) in a portable way is still in study. Since you have already come up with a solution using stty on Linux, I can try to do a quick feature for executing the stty command. Suggest you to raise another issue to track this. We can keep the current issue to resolve the newline issue.

RobertWilbrandt commented 4 years ago

That sounds reasonable. I'll just add a PR fixing this issue on release-1.1-dev too.

a9183756-gh commented 4 years ago

Newline issue fixed in both master and release-1.1-dev branches. Closing this issue. Please open another issue for the 1200bps reset.