From 8173b618dc93bf8e702bc7e4ff5af0542bd1e944 Mon Sep 17 00:00:00 2001 From: Adrien Oliva <aoliva@sefas.com> Date: Thu, 14 Apr 2022 09:32:01 +0200 Subject: [PATCH] Support YCM vim plugin Run once a new file is created to update compilation database --- .compile_commands.json | 67 +++++++++++++++++++++++++++++ .ycm_extra_conf.py | 96 ++++++++++++++++++++++++++++++++++++++++++ cmake/00_config.cmake | 6 +++ 3 files changed, 169 insertions(+) create mode 100644 .compile_commands.json create mode 100644 .ycm_extra_conf.py diff --git a/.compile_commands.json b/.compile_commands.json new file mode 100644 index 0000000..9052385 --- /dev/null +++ b/.compile_commands.json @@ -0,0 +1,67 @@ +[ +{ + "directory": "<bindir>/src", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/fcb1010edit_gui_autogen/mocs_compilation.cpp.o -c <bindir>/src/fcb1010edit_gui_autogen/mocs_compilation.cpp", + "file": "<bindir>/src/fcb1010edit_gui_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/src", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/Fcb1010Edit.cpp.o -c <srcdir>/src/Fcb1010Edit.cpp", + "file": "<srcdir>/src/Fcb1010Edit.cpp" +}, +{ + "directory": "<bindir>/src", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/mainView.cpp.o -c <srcdir>/src/mainView.cpp", + "file": "<srcdir>/src/mainView.cpp" +}, +{ + "directory": "<bindir>/src", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit.dir/fcb1010edit_autogen/mocs_compilation.cpp.o -c <bindir>/src/fcb1010edit_autogen/mocs_compilation.cpp", + "file": "<bindir>/src/fcb1010edit_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/src", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit.dir/main.cpp.o -c <srcdir>/src/main.cpp", + "file": "<srcdir>/src/main.cpp" +}, +{ + "directory": "<bindir>/src/controller", + "command": "/usr/bin/c++ -DQT_CORE_LIB -D__DEBUG -I<bindir>/src/controller -I<srcdir>/src/controller -I<bindir>/src/controller/midi_controller_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/midi_controller.dir/midi_controller_autogen/mocs_compilation.cpp.o -c <bindir>/src/controller/midi_controller_autogen/mocs_compilation.cpp", + "file": "<bindir>/src/controller/midi_controller_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/src/controller", + "command": "/usr/bin/c++ -DQT_CORE_LIB -D__DEBUG -I<bindir>/src/controller -I<srcdir>/src/controller -I<bindir>/src/controller/midi_controller_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/midi_controller.dir/rtmidi_controller.cpp.o -c <srcdir>/src/controller/rtmidi_controller.cpp", + "file": "<srcdir>/src/controller/rtmidi_controller.cpp" +}, +{ + "directory": "<bindir>/unittests", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestFcb1010Edit_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestFcb1010Edit.dir/TestFcb1010Edit_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/TestFcb1010Edit_autogen/mocs_compilation.cpp", + "file": "<bindir>/unittests/TestFcb1010Edit_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/unittests", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestFcb1010Edit_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestFcb1010Edit.dir/TestFcb1010Edit.cpp.o -c <srcdir>/unittests/TestFcb1010Edit.cpp", + "file": "<srcdir>/unittests/TestFcb1010Edit.cpp" +}, +{ + "directory": "<bindir>/unittests", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestMainView_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestMainView.dir/TestMainView_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/TestMainView_autogen/mocs_compilation.cpp", + "file": "<bindir>/unittests/TestMainView_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/unittests", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestMainView_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestMainView.dir/TestMainView.cpp.o -c <srcdir>/unittests/TestMainView.cpp", + "file": "<srcdir>/unittests/TestMainView.cpp" +}, +{ + "directory": "<bindir>/unittests/mock", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests/mock\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests/mock\\\" -DQT_TESTLIB_LIB -D__DEBUG -Dcontroller_mock_EXPORTS -I<bindir>/unittests/mock -I<srcdir>/unittests/mock -I<bindir>/unittests/mock/controller_mock_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtTest -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -fPIC -std=gnu++17 -o CMakeFiles/controller_mock.dir/controller_mock_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/mock/controller_mock_autogen/mocs_compilation.cpp", + "file": "<bindir>/unittests/mock/controller_mock_autogen/mocs_compilation.cpp" +}, +{ + "directory": "<bindir>/unittests/mock", + "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests/mock\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests/mock\\\" -DQT_TESTLIB_LIB -D__DEBUG -Dcontroller_mock_EXPORTS -I<bindir>/unittests/mock -I<srcdir>/unittests/mock -I<bindir>/unittests/mock/controller_mock_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtTest -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -fPIC -std=gnu++17 -o CMakeFiles/controller_mock.dir/controller.cpp.o -c <srcdir>/unittests/mock/controller.cpp", + "file": "<srcdir>/unittests/mock/controller.cpp" +} +] \ No newline at end of file diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 0000000..23133d7 --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,96 @@ +import os +import json +import typing + + +def get_root_absolute_path() -> str: + """Retrieve project root directory.""" + return os.path.dirname(os.path.abspath(__file__)) + + +def get_compile_command_database() -> str: + """Retrieve compile_commands file as created by `ycm` target.""" + return os.path.join(get_root_absolute_path(), '.compile_commands.json') + + +class MyDatabase: + + builddir = os.environ.get('CMAKE_BUILDDIR', os.path.join( + get_root_absolute_path(), 'build' + )) + + def __init__(self, compile_command_path: str): + with open(compile_command_path, 'r', encoding='utf-8') as cc_fh: + self.__compile_command = json.load(cc_fh) + self.__memo = {} + + def get_info_for_file( + self, + filename: str + ) -> typing.Tuple[str, typing.Iterable[str]]: + if filename in self.__memo: + return self.__memo[filename] + + absolute_filename = os.path.normpath(os.path.abspath(filename)) + for entry in self.__compile_command: + entry_filename = entry['file'] + entry_filename = entry_filename.replace( + '<srcdir>', get_root_absolute_path() + ).replace( + '<bindir>', self.builddir + ) + entry_filename = os.path.normpath(entry_filename) + if absolute_filename == entry_filename: + cwd = entry['directory'] + flags = [ + arg.replace( + '<srcdir>', get_root_absolute_path() + ).replace( + '<bindir>', self.builddir + ) + for arg in entry['command'].split(' ')[1:] + ] + self.__memo[filename] = cwd, flags + return self.__memo[filename] + + return os.path.dirname(absolute_filename), [] + + +SOURCE_EXTENSIONS = ['.cpp'] +DATABASE = MyDatabase(get_compile_command_database()) + + +def is_header_file(filename): + extension = os.path.splitext(filename)[1] + return extension in ['.h'] + + +def get_compilation_info_for_file(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 is_header_file(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.get_info_for_file( + replacement_file + ) + return compilation_info + return DATABASE.get_info_for_file(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 = get_compilation_info_for_file(filename) + + return { + 'flags': compilation_info[1], + 'do_cache': True + } diff --git a/cmake/00_config.cmake b/cmake/00_config.cmake index c44cc49..db6ab03 100644 --- a/cmake/00_config.cmake +++ b/cmake/00_config.cmake @@ -24,4 +24,10 @@ if(NOT DEFINED 00_CONFIG_CMAKE) set(INTERNAL_SOURCE_DIRECTORIES "src") + # Export compilation command, use to create .ycm_extra_config.py + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + add_custom_target(ycm + COMMAND cp "${CMAKE_BINARY_DIR}/compile_commands.json" "${CMAKE_SOURCE_DIR}/.compile_commands.json" + COMMAND sed -i "\"s|${CMAKE_BINARY_DIR}|<bindir>|g;s|${CMAKE_SOURCE_DIR}|<srcdir>|g\"" "${CMAKE_SOURCE_DIR}/.compile_commands.json" + ) endif() -- GitLab