Как править в CLion код любых проектов на С++, даже тех, в которых не используется CMake

20 ноября 2015

Злые языки говорят, что CLion подходит только для проектов, использующих CMake. Что даже проекты на CMake он может индексировать 12 часов, а потом упасть с out of memory. А если каким-то чудом CLion не упадет, то будет адски тормозить и подсвечивать весь код красным. Что единственной нормальной IDE для C++ якобы был и во веке веков останется Visual Studio. Сегодня мы с вами убедимся, что к таким выводам люди приходят не от большого ума, и что за пять минут несложных рассуждений в CLion можно успешно открыть любой проект — неважно насколько большой и используется ли в нем CMake.

Задумаемся ненадолго, что вообще представляет собой CMake? В сущности, это тот же make, только кроссплатформенный. То есть, в отличие от make, CMake не привязывается к компилятору, ОС, и так далее. Отсюда и название, а вовсе не от того, что CMake используется для C/C++. Поверх этого еще накручен поиск некоторых пакетов по их названию, но это для нас уже не так важно, так как реализуется на скриптах, идущими в комплекте с CMake. А раз идея та же, что и у make, значит по сути CMake задает, какие в проекте есть файлы исходного кода, где искать заголовочные файлы, и как из них получить исполняемые файлы.

Как это знание поможет нам использовать CLion для произвольного проекта? Да очень просто — нам же всего-то нужно сообщить CLion, какие файлы он должен проиндексировать. Сделать это можно, написав незамысловатый генератор файла CMakeLists.txt вроде такого:

#!/usr/bin/env python

# cmakegen.py
# (c) Aleksander Alekseev 2015
# http://eax.me/

import sys
import os
import re

include_dirs = set()
source_files = set()

def recursive_search(path):
    # print(path)
    for file in os.listdir(path):
        if (file == ".") or (file == ".."):
            continue

        full_name = os.path.join(path, file)
        if os.path.isdir(full_name) and not os.path.islink(path):
            recursive_search(full_name)

        if re.search("\\.(c|cpp|cxx)$", file) is not None:
            source_files.add(full_name)
        elif re.search("\\.(h|hpp)$", file) is not None:
            include_dirs.add(path)

if len(sys.argv) < 2:
    print("Usage " + sys.argv[0] + " <path>")
    sys.exit(1)

start_path = sys.argv[1]
recursive_search(start_path)

print("cmake_minimum_required(VERSION 2.8)")
print("project(dummy_project)")

skip_chars = len(start_path) + 1

for dir in sorted(include_dirs):
    print("include_directories(" + dir[skip_chars:] + ")")

print("add_executable(dummy_executable")
for file in sorted(source_files):
    print("  " + file[skip_chars:])
print(")")

Берем какой-нибудь проект. В том, что я взял для эксперимента, было более миллиона строк кода на C++. Генерируем приведенным скриптом на Python файл CMakeLists.txt, открываем проект в CLion, пару минут ждем окончания первой индексации — и вуаля!

Все автодополнения и переходы к определениям работают, вся документация и подсказки по аргументам отображаются, переименования методов и переменных отрабатывают, и так далее. Если IDE все равно подсвечивает что-то красным, можно понизить highlighting level (кликаем по мужику в каске в правом нижнем углу) или перевести IDE в power save mode. Также может потребоваться немного подправить руками сгенеренный CMakeLists.txt, тут все зависит от специфики вашего проекта.

Описанный прием может иметь смысл использовать не только в проектах, не использующих CMake, но и в проектах, в которых используется старая версия CMake, например, 2.4. Так как CLion использует более новый CMake, а где-то между версиями в CMake ломали обратную совместимость, то CLion может, к примеру, уходить в бесконечную рекурсию на старых проектах, заодно отжирая весь хип.

Конечно, компилировать и отлаживать проект из IDE описанный прием не позволяет, но зато в нашем распоряжении становится мощнейшее средство редактирования кода!

Дополнение: В комментариях отмечают, что CLion имеет функционал под названием Import Project from Sources. Он действительно есть, делает нечто похожее, но работает крайне скверно. Из сгенерированного CMakeList.txt CLion не может найти половины инклудов. В результате все исходники подсвечиваются красным цветом, ад и погибель.

Метки: , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.