Skip to content

Instantly share code, notes, and snippets.

@ajford
Last active April 12, 2021 11:55
Show Gist options
  • Save ajford/f551b2b6fd4d6b6e1ef2 to your computer and use it in GitHub Desktop.
Save ajford/f551b2b6fd4d6b6e1ef2 to your computer and use it in GitHub Desktop.
PlatformIO/YouCompleteMe Integration
"""
YouCompleteMe extra configuration for Platformio based
projects.
Based on the `.ycm_extra_conf.py` by @ladislas in his Bare-Arduino-Project.
Anthony Ford <github.com/ajford>
"""
import os
import ycm_core
import logging
# Logger for additional logging.
# To enable debug logging, add `let g:ycm_server_log_level = 'debug'` to
# your .vimrc file.
logger = logging.getLogger('ycm-extra-conf')
# Platformio Autogen libs.
## Platformio automatically copies over the libs you use after your first run.
## Be warned that you will not receive autocompletion on libraries until after
## your first `platformio run`.
PlatformioAutogen = ".pioenvs/"
# All Platformio Arduin Libs
## This will link directly to the Platformio Libs for Arduino.
## Be warned that this can polute your namespace (in #include)
## and slightly increase startup time (while crawling the lib
## dir for header files). This will however allow you to
## complete for header files you haven't included yet.
PlatformioArduinoLibs = "~/.platformio/packages/framework-arduinoavr/libraries/"
# Platformio Arduino Core
## This links to the Platformio Arduino Cores. This provides
## the core libs, such as Arduino.h and HardwareSerial.h
PlatformioArduinoCore = "~/.platformio/packages/framework-arduinoavr/cores/arduino/"
# Platformio Arduino Std Libs
## Arduino Std libs from .platformio packages. Provides stdlib.h and such.
PlatformioArduinoSTD = '~/.platformio/packages/toolchain-atmelavr/avr/include'
# This is the list of all directories to search for header files.
# Dirs in this list can be paths relative to this file, absolute
# paths, or paths relative to the user (using ~/path/to/file).
libDirs = [
"lib"
,PlatformioAutogen
,PlatformioArduinoCore
,PlatformioArduinoLibs
,PlatformioArduinoSTD
]
flags = [
# General flags
'-Wall'
,'-x'
,'c++'
,'-ansi'
# Customize microcontroler and Arduino version
,'-mmcu=atmega328p'
,'-DF_CPU=16000000L'
,'-DARDUINO_ARCH_AVR'
,'-DARDUINO_AVR_DUEMILANOVE'
,'-DARDUINO=106000'
# ,'-MMD -DUSB_VID=null'
# ,'-DUSB_PID=null'
]
compilation_database_folder = ''
if os.path.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )
else:
database = None
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.ino', '.m', '.mm' ]
def DirectoryOfThisScript():
return os.path.dirname( os.path.abspath( __file__ ) )
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
if not working_directory:
return list( flags )
new_flags = []
make_next_absolute = False
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
for libDir in libDirs:
# dir is relative to $HOME
if libDir.startswith('~'):
libDir = os.path.expanduser(libDir)
# dir is relative to `working_directory`
if not libDir.startswith('/'):
libDir = os.path.join(working_directory,libDir)
# Else, assume dir is absolute
for path, dirs, files in os.walk(libDir):
# Add to flags if dir contains a header file and is not
# one of the metadata dirs (examples and extras).
if any(IsHeaderFile(x) for x in files) and\
path.find("examples") is -1 and path.find("extras") is -1:
logger.debug("Directory contains header files - %s"%path)
flags.append('-I'+path)
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith( '/' ):
new_flag = os.path.join( working_directory, flag )
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith( path_flag ):
path = flag[ len( path_flag ): ]
new_flag = path_flag + os.path.join( working_directory, path )
break
if new_flag:
new_flags.append( new_flag )
return new_flags
def IsHeaderFile( filename ):
extension = os.path.splitext( filename )[ 1 ]
return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
def GetCompilationInfoForFile( filename ):
# The compilation_commands.json file generated by CMake does not have entries
# for header files. So we do our best by asking the db for flags for a
# corresponding source file, if any. If one exists, the flags for that file
# should be good enough.
if IsHeaderFile( filename ):
basename = os.path.splitext( filename )[ 0 ]
for extension in SOURCE_EXTENSIONS:
replacement_file = basename + extension
if os.path.exists( replacement_file ):
compilation_info = database.GetCompilationInfoForFile(
replacement_file )
if compilation_info.compiler_flags_:
return compilation_info
return None
return database.GetCompilationInfoForFile( filename )
def FlagsForFile( filename, **kwargs ):
if database:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = GetCompilationInfoForFile( filename )
if not compilation_info:
return None
final_flags = MakeRelativePathsInFlagsAbsolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_ )
# NOTE: This is just for YouCompleteMe. it's highly likely that your project
# does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR
# ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT.
#try:
# final_flags.remove( '-stdlib=libc++' )
#except ValueError:
# pass
else:
relative_to = DirectoryOfThisScript()
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
return {
'flags': final_flags,
'do_cache': True
}
@ajford
Copy link
Author

ajford commented Mar 12, 2015

I've added -ansi as a flag, as AVR-C is based on ANSI C, and this gets Syntastic to stop complaining about some things that are deprecated in later standards.

@HeLiBloks
Copy link

clang does not seem to accept
-mmcu=atmega328p
out of the box, i dont think it has support for avr? is there a compiled version of clang that does this? or will i have to recompile it from source?

@MarcelRobitaille
Copy link

MarcelRobitaille commented Jul 28, 2017

Sorry for the stupid question but where do I put this?

Update: Put it in your project directory or put it in your dotfiles and modify g:ycm_global_ycm_extra_conf accordingly.

@hihosilvers
Copy link

hihosilvers commented Aug 6, 2017

@ajford all the files in my .pioenvs folder are .o files. Header, .h, files for non-built-in libraries are saved in .piolibdeps
Thanks for the example.

@okooo5km
Copy link

@ajford Thanks for this example, my arduino code can go the function declaration, but can't go to function definition, would you give some idea?

@ladislas
Copy link

@ajford very nice! Glad the Bare Arduino Project was helpful ;) I'm now considering moving to platformio instead of Arduino Makefile, it looks a lot simpler and powerful

@hashworks
Copy link

For custom libraries and my dependencies I need to add them manually:

libDirs = [
           "~/.platformio/lib/Drive"
           ,".piolibdeps/Ultrasonic_ID1507/src"
           ,"lib"
           ,PlatformioAutogen
[...]

Any idea how to improve this? I can't just add .piolibdeps and ~/.platformio/lib, it basically needs to traverse those folders. Same for lib.

@neophytos-theodorou
Copy link

neophytos-theodorou commented Jun 26, 2018

Have tried to use YouCompleteMe with platformio and vim many times but I always fail.
This time YouCompleteMe does not recognise Serial altought I have included Arduino.h
Also YcmDiags give me this errors:
/home/neophytos/.platformio/packages/toolchain-atmelavr/avr/include/avr/io.h|625 col 6 warning| "device type not defined" /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|163 col 23 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|164 col 23 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|165 col 23 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|167 col 22 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|169 col 22 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|170 col 22 warning| unknown attribute '__progmem__' ignored /home/neophytos/.platformio/packages/toolchain-atmelavr/avr/include/avr/eeprom.h|41 col 3 warning| "Device does not have EEPROM available." /home/neophytos/.platformio/packages/toolchain-atmelavr/avr/include/util/delay_basic.h|108 col 5 error| invalid output constraint '=w' in asm /home/neophytos/.platformio/packages/toolchain-atmelavr/avr/include/util/delay.h|112 col 3 warning| "Compiler optimizations disabled; functions from <util /delay.h> won't work as designed" /home/neophytos/.platformio/packages/framework-arduinoavr/cores/arduino/Arduino.h|257 col 10 error| 'pins_arduino.h' file not found src/main.cpp|6 col 5 error| use of undeclared identifier 'Serial'
Any help will be highly appreciated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment