YouCompleteMe can't find local header files

半城伤御伤魂 提交于 2021-02-19 07:43:30

问题


I currently have a project that is structured as so

project
|
|----src/
|   |
|   |----test.cpp
|
|----include/
|   |
|   |----test.hpp
|
|----.ycm_extra_conf.py

But I can't get YouCompleteMe to recognize test.hpp when it's include in test.cpp

#include "test.hpp"

This is the output of my :YcmDebugInfo

Printing YouCompleteMe debug information...                                                                                                                                                                                                   
-- Client logfile: /tmp/ycm_tcrryhfo.log                                                                                                                                                                                                      
-- Server Python interpreter: /usr/bin/python2.7                                                                                                                                                                                              
-- Server Python version: 2.7.14                                                                                                                                                                                                              
-- Server has Clang support compiled in: True                                                                                                                                                                                                 
-- Clang version: clang version 3.9.1 (tags/RELEASE_391/final)                                                                                                                                                                                
-- Extra configuration file found and loaded                                                                                                                                                                                                  
-- Extra configuration path: /home/jake/project/.ycm_extra_conf.py                                                                                                                                                                          
-- C-family completer debug information:                                                                                                                                                                                                      
--   Compilation database path: None                                                                                                                                                                                                          
--   Flags: ['-std=c++11', '-x', 'c++', '-Wall', '-I', 'include', '-isystem', '/usr/include', '-resource-dir=/home/jake/.local/share/nvim/plugged/YouCompleteMe/third_party/ycmd/ycmd/../clang_includes', '-fspell-checking']                 
-- Server running at: http://127.0.0.1:59337                                                                                                                                                                                                  
-- Server process ID: 21577                                                                                                                                                                                                                   
-- Server logfiles:                                                                                                                                                                                                                           
--   /tmp/ycmd_59337_stdout_kndkmx3g.log                                                                                                                                                                                                      
--   /tmp/ycmd_59337_stderr__xriaszp.log

There are no errors present in the server log files, but the client logfile has a few errors that ultimately begins with this:

Traceback (most recent call last):                                                                                                                                                                                                            
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/autoload/../python/ycm/client/base_request.py", line 214, in HandleServerException                                                                                                 
yield                                                                                                                                                                                                                                     
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/autoload/../python/ycm/youcompleteme.py", line 237, in CheckIfServerIsReady                                                                                                        
'ready' )                                                                                                                                                                                                                                 
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/autoload/../python/ycm/client/base_request.py", line 68, in GetDataFromHandler                                                                                                     
timeout ) )                                                                                                                                                                                                                               
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/autoload/../python/ycm/client/base_request.py", line 180, in JsonFromFuture                                                                                                        
response = future.result()                                                                                                                                                                                                                
  File "/usr/lib64/python3.4/concurrent/futures/_base.py", line 402, in result                                                                                                                                                                
return self.__get_result()                                                                                                                                                                                                                
  File "/usr/lib64/python3.4/concurrent/futures/_base.py", line 354, in __get_result                                                                                                                                                          
raise self._exception                                                                                                                                                                                                                     
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/autoload/../python/ycm/unsafe_thread_pool_executor.py", line 43, in run                                                                                                            
result = self.fn(*self.args, **self.kwargs)                                                                                                                                                                                               
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/third_party/ycmd/third_party/requests/requests/sessions.py", line 468, in request                                                                                                  
resp = self.send(prep, **send_kwargs)                                                                                                                                                                                                     
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/third_party/ycmd/third_party/requests/requests/sessions.py", line 576, in send                                                                                                     
r = adapter.send(request, **kwargs)                                                                                                                                                                                                       
  File "/home/jake/.local/share/nvim/plugged/YouCompleteMe/third_party/ycmd/third_party/requests/requests/adapters.py", line 437, in send                                                                                                     
raise ConnectionError(e, request=request)                                                                                                                                                                                                 
requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=34155): Max retries exceeded with url: /ready (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f32a77aa048>: Failed to establish a new connection: [Errno 111] Connection refused',))

Other than this everything seems to be working although it will offer variables that are out of scope as suggestions when autocompleting (Suggests member variables of different classes).

I followed the full installation guide and set my external clang to /usr/lib/libclang.so

I have no idea what's causing this.


回答1:


The default .ycm_extra_conf.py doesn't look for headers in nearby include directories.

This lookup is done in JDevlieghere's configuration, which I adapted to also add a flag for the include path root (in function FlagsForInclude):

import os
import os.path
import fnmatch
import logging
import ycm_core
import re

BASE_FLAGS = [
        '-Wall',
        '-Wextra',
        '-Werror',
        '-Wno-long-long',
        '-Wno-variadic-macros',
        '-fexceptions',
        '-ferror-limit=10000',
        '-DNDEBUG',
        '-std=c++1z',
        '-xc++',
        '-I/usr/lib/',
        '-I/usr/include/'
        ]

SOURCE_EXTENSIONS = [
        '.cpp',
        '.cxx',
        '.cc',
        '.c',
        '.m',
        '.mm'
        ]

SOURCE_DIRECTORIES = [
        'src',
        'lib'
        ]

HEADER_EXTENSIONS = [
        '.h',
        '.hxx',
        '.hpp',
        '.hh'
        ]

HEADER_DIRECTORIES = [
        'include'
        ]

BUILD_DIRECTORY = 'build';

def IsHeaderFile(filename):
    extension = os.path.splitext(filename)[1]
    return extension in HEADER_EXTENSIONS

def GetCompilationInfoForFile(database, filename):
    if IsHeaderFile(filename):
        basename = os.path.splitext(filename)[0]
        for extension in SOURCE_EXTENSIONS:
            # Get info from the source files by replacing the extension.
            replacement_file = basename + extension
            if os.path.exists(replacement_file):
                compilation_info = database.GetCompilationInfoForFile(replacement_file)
                if compilation_info.compiler_flags_:
                    return compilation_info
            # If that wasn't successful, try replacing possible header directory with possible source directories.
            for header_dir in HEADER_DIRECTORIES:
                for source_dir in SOURCE_DIRECTORIES:
                    src_file = replacement_file.replace(header_dir, source_dir)
                    if os.path.exists(src_file):
                        compilation_info = database.GetCompilationInfoForFile(src_file)
                        if compilation_info.compiler_flags_:
                            return compilation_info
        return None
    return database.GetCompilationInfoForFile(filename)

def FindNearest(path, target, build_folder=None):
    candidate = os.path.join(path, target)
    if(os.path.isfile(candidate) or os.path.isdir(candidate)):
        logging.info("Found nearest " + target + " at " + candidate)
        return candidate;

    parent = os.path.dirname(os.path.abspath(path));
    if(parent == path):
        raise RuntimeError("Could not find " + target);

    if(build_folder):
        candidate = os.path.join(parent, build_folder, target)
        if(os.path.isfile(candidate) or os.path.isdir(candidate)):
            logging.info("Found nearest " + target + " in build folder at " + candidate)
            return candidate;

    return FindNearest(parent, target, build_folder)

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 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 FlagsForClangComplete(root):
    try:
        clang_complete_path = FindNearest(root, '.clang_complete')
        clang_complete_flags = open(clang_complete_path, 'r').read().splitlines()
        return clang_complete_flags
    except:
        return None

def FlagsForInclude(root):
    try:
        include_path = FindNearest(root, 'include')
        flags = []
        for dirroot, dirnames, filenames in os.walk(include_path):
            flags = flags + ["-I" + dirroot]
            for dir_path in dirnames:
                real_path = os.path.join(dirroot, dir_path)
                flags = flags + ["-I" + real_path]
        return flags
    except:
        return None

def FlagsForCompilationDatabase(root, filename):
    try:
        # Last argument of next function is the name of the build folder for
        # out of source projects
        compilation_db_path = FindNearest(root, 'compile_commands.json', BUILD_DIRECTORY)
        compilation_db_dir = os.path.dirname(compilation_db_path)
        logging.info("Set compilation database directory to " + compilation_db_dir)
        compilation_db =  ycm_core.CompilationDatabase(compilation_db_dir)
        if not compilation_db:
            logging.info("Compilation database file found but unable to load")
            return None
        compilation_info = GetCompilationInfoForFile(compilation_db, filename)
        if not compilation_info:
            logging.info("No compilation info for " + filename + " in compilation database")
            return None
        return MakeRelativePathsInFlagsAbsolute(
                compilation_info.compiler_flags_,
                compilation_info.compiler_working_dir_)
    except:
        return None

def FlagsForFile(filename):
    root = os.path.realpath(filename);
    compilation_db_flags = FlagsForCompilationDatabase(root, filename)
    if compilation_db_flags:
        final_flags = compilation_db_flags
    else:
        final_flags = BASE_FLAGS
        clang_flags = FlagsForClangComplete(root)
        if clang_flags:
            final_flags = final_flags + clang_flags
        include_flags = FlagsForInclude(root)
        if include_flags:
            final_flags = final_flags + include_flags
    return {
            'flags': final_flags,
            'do_cache': True
            }


来源:https://stackoverflow.com/questions/47246209/youcompleteme-cant-find-local-header-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!