PlatformIO with Neovim

Recently I got interested in EPS32 and ESP8266 programming and I found PlatformIO provides a framework to work with a wide range of devices using simpler code like in Arduino.

I started with VSCode as IDE but soon felt I want to move back to my original editor which is Neovim. I have everything set up according to my need and wanted to see whether PlatformIO can work with Neovim. To start of with I installed there cli tool which can be found here: https://docs.platformio.org/en/stable/core/index.html. After installing pio cli I created new ESP32 project using following command:

pio project init --board esp32dev --ide vim

which scaffolded basic project with following platform.ini file

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino

and after that created a new file in src directory named main.cpp but Neovim started showing multiple errors that it is not able to find Arduino.h. LSP I am using is Clangd and solving this was the easiest part of the whole journey. I need to run this command to generate compile_commands.json file that Clangd will look at find all necessary libraries.

 pio run -t compiledb

After I restarted my LSP i got few new errors about machine/endian.h not found and few unknown compiler flags but if I run pio run it successfully builds so its issue with LSP only. After scavenging internet for few hours I got a solution that works for me and here it is:

# platform.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
build_flags = -Ilib -Isrc # add this line

I also needed a bash script that generates and fixes flags in compile_commands.h

#!/bin/bash

# Compile the project
pio run -t compiledb

# Clean up existing define files
rm -f _compiler_defines.h compiler_defines.h clang_defines.h

# Generate defines for clang
clang -dM -xc++ /dev/null -c -v -E 2>/dev/null | sed "s/\([^[:space:]]\+[[:space:]]\+[^[:space:]]\+\)\(.*\)/\1/;s/#define/#undef/" >clang_defines.h

# Iterate through compile_commands.json and extract compiler defines
for comp in $(cat compile_commands.json | grep -E "\"command\": \"[^[:space:]]* -o" | sed 's:"command"\: "::g; s:-o.*::g' | sort | uniq); do
    set -x
    $comp -dM -E -xc++ /dev/null >>_compiler_defines.h
    set +x
done

# Combine defines from clang and extracted defines
cat clang_defines.h >compiler_defines.h
cat _compiler_defines.h | sort | uniq >>compiler_defines.h

# Clean up temporary define files
rm -f _compiler_defines.h clang_defines.h

# Update compile_commands.json with additional include flags
sed -i "s:.cpp\",:.cpp -include $${PWD}/compiler_defines.h\",:" compile_commands.json
sed -i "s:.c\",:.c -include $${PWD}/compiler_defines.h\",:" compile_commands.json

After running this when I restarted my LSP everything works except few things like Serail.println still throws an error. Except that last thing everything looks good. I will continue learning ESP32 programming in Neovim and if I find something to update I will add a new article as part 2 of this. Hope this article helps you.

Happy Coding

3
Subscribe to my newsletter

Read articles from Ratnadeep Bhattacharyya directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ratnadeep Bhattacharyya
Ratnadeep Bhattacharyya

I am developer from India, currently working remote as Software Engineer in Nagarro. Love to work on new technologies and experiment with bleeding edge one.