История про CLion, docker, conan, cmake, ninja, cotire и gdb.

Небольшое предисловие


Разработкой на C++ я занимаюсь уже лет 15 и когда-то начинал с «Watcom С». О нем у меня остались самые теплые воспоминания. Но, так как мне больше приходилось писать для консоли UNIX, я перешел на vim в качестве IDE. В целом, он достаточно удобен. Его плагины творят чудеса, можно настроить autocomplete, просмотр иерархии классов, быстрый переход к определению или поиск, в общем всё, что должны уметь IDE, там можно поднять. Боль приходит в тот момент, когда ты пытаешься установить и освоить новый плагин. Это всё заводится не везде и не всегда, и, зачастую, жрет проц и память похлеще любой java.

Периодически я поглядывал на Qt Creator. Но так и не решился на него перейти.

Первое знакомство


imageИ вот, в один из таких моментов мне на глаза попался CLion. После конструктора под названием vim очень хотелось получить решение «из коробки». На первый взгляд, он мне очень понравился. Быстрые подсказки, удобная навигация, работа с cmake проектами, как с родными, поддержка режима vim (правда, в последствии, я её отключил).

Облом случился довольно скоро. Дело в том что, хоть пишу я на данный момент в основном под linux, в качестве рабочей станции у меня macbook pro. Да, я такой! И искренне считаю извращенцами людей, которые, купив ноутбук apple, устанавливают на него что-нибудь кроме macOS. Поэтому, для меня критически важна возможность удаленной сборки или сборки через docker. А её, сколько пользователи ни просили, в CLion пока нет. Первая попытка перехода закончилась ничем — ведь решения «из коробки» нет.

Вторая попытка


Но боль с настройкой vim никуда не ушла, и я решил дать CLion второй шанс — попробовать решить те проблемы, которые передо мной встали, самостоятельно. А это:

  1. Отсутствие локально установленный библиотек. CLion не может выдавать подсказки по классам, описания которых не видит
  2. Собственно сама сборка

До этого, я пользовался библиотеками, которые поставляются в пакетах вместе ОС. С CLion мне бы пришлось все заголовочные файлы ОС закидывать к себе на Mac, чего категорически не хотелось. Но тут меня выручил conan. Он хранит все собранные библиотеки в отдельном каталоге, который легко можно подложить себе.

Со вторым все оказалось не так просто. Я решил просто подменить cmake на свой скрипт, который выполнит сборку внутри docker контейнера. Мне не улыбалось каждый раз, когда я синхронизирую свой код из репозитория или вливаю его обратно, добавлять/удалять дополнительный Target в CMakeLists.txt, как мне советовали. Хотелось иметь возможность склонировать любой проект и тут же собраться без танцев с бубном. Это оказалось не так просто. Основную сложность вызвала сборка тестового проекта CLion, которую он выполняет при смене toolchain, и проброс параметров содержащих пробелы внутрь контейнера. Но я справился.

Если у вас всё хорошо — вы просто ещё не всё знаете


Казалось бы — у меня получилось!

Я был наслышан, что сборка на С++ с использованием С++14 или С++17 — довольно медленная штука, и, поначалу, всё списывал на медлительность компилятора. Но потом заметил, что удаленно на выделенном сервере собирается уж как-то слишком шустро. Чем больше становился проект — тем большие сомнения рождались в моей душе.

Докер оказался с двойным дном. Да, сервер поднимается шустро, вот только компиляция на osxfs работает, как оказалось в ТРИ раза медленнее, чем на overlay. Поэтому пришлось перейти на использование rsync. Так же, я открыл для себя настройки томов docker. Если использовать delegated — скорость сборки увеличивается процентов на 15. Подробнее.

Попутно померил время сборки через ninja против стандартного make — разница вышла практически вдвое. Правда CLion требует собираться именно через make, иначе, прощайте подсказки. Пришлось прогонять сборку дважды, один раз через make, для CLion, второй — через ninja. Выигрыш тут в том, что проект меняется довольно редко, а собираться надо часто.

Еще, я попробовал использовать прекомпилированные заголовки (cotire) — эффект оказался неоднозначным. К тому же, это требовало вручную формировать stdafx.h (или любой другой файл) и включать его во все .cpp. А это, в свою очередь, не очень нравится CLion. Он начинает считать все остальные include лишними. Это можно было обойти, но выигрыш был не такой значительный.

Последнее, что я сделал — отказался от ccache. В моем случае, он давал задержку примерно в секунду. Да, если подходящий файл найден, это ускоряет сборку. Но такое не часто случается, когда ты пишешь новый код.

Аппетит приходит во время еды


Раз уж сборка у меня завелась, почему бы не попробовать растолкать и отладку!
Раньше я считал, что gdb внутри docker запустить невозможно. Оказалось, что это не так. Параметр --security-opt seccomp:unconfined снимает данную проблему. А статья подробно описывает, как и что надо настраивать. Но, и тут случился непредвиденный облом. Я собирался через clang (что логично), а для отладки надо использовать gcc. В противном случае, запустить приложение в отладчике вы сможете, но вот посмотреть значения внутри stl контейнеров уже нет. В принципе, собрать через gcc — не проблема. Тогда, и правда всё работает.

Эпилог


Мыши плакали, кололись, но продолжали есть кактус… Ждем! Ждем удаленную сборку. Ждем полноценную поддержку C++17. JetBrains и JFrog в своих рассылках постоянно поминают друг друга, но какой-либо интеграции пока нет. Даже, собираясь локально, придется вводить команды conan вручную. Ждёмс!

Еще было бы неплохо заполучить поддержку сборки через ninja. 50% производительности на дороге валяются.

Кому интересно, мои скрипты и Dockerfile для сборки шаблона можно найти на GitHub.
Поделиться с друзьями
-->

Комментарии (24)


  1. knstqq
    25.07.2017 15:23

    Последнее, что я сделал — отказался от ccache. В моем случае, он давал задержку примерно в секунду. Да, если подходящий файл найден, это ускоряет сборку. Но такое не часто случается, когда ты пишешь новый код.


    ccache больше подходит не для случая, если вы занимаетесь разработкой, а для случая, если это build-сервер, который собирает десятки-сотни-тысячи проектов регулярно и не все из них изменяются.
    Или если у вас source-based дистрибутив linux, например gentoo.

    А так системы сборки, умеющие «инкрементально» дают намного больше пользы


    1. Doktor3lo
      25.07.2017 17:06
      +1

      ccache может сильно помогать, если вы работаете с несколькими ветками git одновременно и при сборке rpm или deb пакетов.

      В данном случае он был добавлен скорее по привычке — обычно проблем от него нет.


      1. knstqq
        25.07.2017 17:08

        да, действительно, в случае нескольких git-веток помогать должен


  1. yarric
    25.07.2017 15:32
    -3

    Почему бы не использовать Xcode?


    1. eugenebabichenko
      25.07.2017 16:48
      +1

      Потому что автор использует Linux. Ещё многим просто не нравится Xcode, не поверите :)


    1. Doktor3lo
      25.07.2017 17:15
      +1

      Я думал о нем, но не встретил ни одного человека, который бы мне сказал — это круто, попробуй!
      Зато многие отговаривали. В общем, имидж у него не очень :)


      1. yarric
        25.07.2017 17:32

        Ну считайте один есть :) А вообще в свежей версии вроде пофиксили много чего и улучшили.


    1. klirichek
      25.07.2017 20:54

      Там есть большая подляна.
      Вроде всё подсвечивается и собирается (можно из проекта CMake, на котором живёт CLion создать билд-солюшн XCode, и даже открыть его...)
      Но! Как только пытаешься редактировать новый код, Он через мгновение очухивается и говорит: а… это не Objective C? Ну тогда я умываю руки… И отключает множество фичей, вроде подсказок и т.д.


      1. yarric
        25.07.2017 21:42

        Это какая-то проблема именно при импорте CMake? Какая версия Xcode?


        1. eugenebabichenko
          26.07.2017 10:28

          Это какая-то проблема с C++. Когда я работал над проектом под macOS, в котором портируемое между системами ядро было написано на C++, поддержка его была довольно урезанной. Потому как это было давно, уже точно и не вспомню, что конкретно там было вырезано, но в итоге выяснилось, что со всеми задачами, кроме рисования интерфейса, гораздо лучше справляется AppCode.


          1. yarric
            29.07.2017 15:19

            Вчера сделал проект на C++ в свежем Xcode — подсказки и всё прочее работает. Судить о новом Xcode по какому-нибудь Xcode времён Objective-C как-то странно.


            1. eugenebabichenko
              29.07.2017 19:05

              Так всё, что вы сказали, у меня работало. А вот рефакторинга не было, и это было печально. Речь идёт об Xcode образца зимы этого года.


              1. yarric
                29.07.2017 20:53

                Вот выбрал класс, нажал меню — Refactor -> Rename, Extract, Create Superclass и так далее, чего не хватает?


                1. eugenebabichenko
                  29.07.2017 20:59

                  Занятно, мне он упорно утверждал, что "Xcode can only refactor C and Objective-C code"


                  1. yarric
                    29.07.2017 23:48

                    Сорри, действительно есть такое. Тем не менее в 9-м уже всё должно быть.


  1. anastasiak2512
    25.07.2017 15:43

    Я оставлю это здесь http://nevkontakte.com/2015/rogue-ninja-support-in-clion.html. На тему CLion + ninja, там слинкован некий скрипт, который позволяет такой вариант «двойной» сборки автоматизировать. Раньше вроде работало.

    А вообще надеюсь, что скоро сможем ninja поддержать как генератор в CLion/CMake.


    1. klirichek
      25.07.2017 20:55

      ну, вообще-то как генератор в Cmake он давно уже поддерживается.
      И если проект CLion рассматривать вне IDE, а просто как проект CMake — аналогично.


      1. anastasiak2512
        26.07.2017 00:48

        Я имею в виду поддержать ninja как генератор CMake в CLion. То, что он просто как генератор в CMake уже давно есть, это понятно. Но CLion сейчас рассчитывает, что используется Makefiles генератор, мало того, он и запускает CMake, передавая соответствующий параметр.


  1. apro
    25.07.2017 17:13
    +1

    Как-то все схематично описано, часть контекста очевидного автору мне совершенно непонятна.


    Например,


    Его плагины творят чудеса, можно настроить autocomplete, просмотр иерархии классов, быстрый >переход к определению или поиск, в общем всё, что должны уметь IDE, там можно поднять. Боль >приходит в тот момент, когда ты пытаешься установить и освоить новый плагин. Это всё >заводится не везде и не всегда, и, зачастую, жрет проц и память похлеще любой java.

    Сколько машин у автора и зачем на них перенастраивать каждый день YouCompleteMe?


    До этого, я пользовался библиотеками, которые поставляются в пакетах вместе ОС. С CLion мне >бы пришлось все заголовочные файлы ОС закидывать к себе на Mac, чего категорически не >хотелось

    А зачем это вообще нужно? Почему не собрать для mac os x, протестировать на нем,
    а потом отправить патч в CI для тестирования на linux. Все-таки системы (mac os x и linux) очень близки в плане API для серверного ПО.


    Мне не улыбалось каждый раз, когда я синхронизирую свой код из репозитория или вливаю его >обратно, добавлять/удалять дополнительный Target в CMakeLists.txt, как мне советовали. Хотелось >иметь возможность склонировать любой проект и тут же собраться без танцев с бубном.

    Почему не (псевдокод)


    if(DEFINED ENV{LOCAL_EXT})
    include(${LOCAL_EXT})
    endif()

    ?
    выставили бы один раз в ~/.basrc путь до нужного скрипта добавляющего нужный
    вам target и горя не знали


    Попутно померил время сборки через ninja против стандартного make — разница вышла практически вдвое. Правда CLion требует собираться именно через make, иначе, прощайте подсказки. Пришлось прогонять сборку дважды, один раз через make, для CLion, второй — через ninja

    Т.е. вместо 2X время сборки увеличилось до 3X, а ради чего?


    1. Doktor3lo
      25.07.2017 17:36

      Просто, статья не про настройку vim. Я пользовался YCM. У меня есть конфиг для vim, который я, как правило, просто копировал на новое место (+установка некоторого количества плагинов, типа YCM). Как правило проблемы начинаются, когда требуется сложная навигация между файлами. Попробуйте поискать какое-нибудь имя по всему проекту? grep? Может конечно есть плагин. Но сколько сочетаний клавиш вы храните в памяти постоянно? Если забыл — никакого контекстного меню, только хардкор! Я даже, одно время autocomplete не пользовался — память тренировал, пока с boost не столкнулся :)

      macOS — это FreeBSD, а это совсем не linux. Например, там нет proc, абсолютно другая логика работы с shared library ну и еще по мелочам, которые, тем не менее, вполне могут испортить жизнь. + я не люблю засорять собственную ОС, предпочитая работать через chroot, virtualbox или docker.

      Потому что, это, как ни крути, изменения проекта чисто под себя, чего я делать не хотел.

      Возможно я не совсем точно сформулировал мысль. Да, при добавлении новый файлов cmake отрабатывает дольше, за счет двойной работы. Но это небольшая плата за возможность экономить 50% времени, при отладке.

      ЗЫ
      Я не против vim, до сих пор кое что правлю в нем. Его, в отличие от CLion, можно легко запустить удаленно. Он быстрее грузится. Глупо открывать проект в CLion, чтобы поправить пару строк :)


      1. apro
        25.07.2017 20:38
        +1

        У меня есть конфиг для vim, который я, как правило, просто копировал на новое место (+установка некоторого количества плагинов, типа YCM)

        Так в этом и вопрос, ноутбуков с ретиной слишком много? Сколько раз нужно перенастраивать чтобы почувствовать боль и желание что-то изменить, я думаю ноутбуков с ретиной должно быть штук 10?


        Как правило проблемы начинаются, когда требуется сложная навигация между файлами. >Попробуйте поискать какое-нибудь имя по всему проекту? grep?

        :! find . -name x
        :! grep -r x *

        или просто открыть директорию в буфере и начать путешествие
        как в обычном файловом менеджере,
        по-моему при условии забытого сочетания клавиш намного быстрее
        чем в любой IDE, а если сочетание клавиш помнишь то одинаково быстро
        в любом редакторе/IDE.


        macOS — это FreeBSD, а это совсем не linux. Например, там нет proc, абсолютно другая логика работы с shared library ну и еще по мелочам, которые, тем не менее, вполне могут испортить жизнь.

        я знаю, а еще там kqueue вместо epoll, и что? действительно пишете софт который читает /proc, причем каждый день, никаких кроссплатформенных оберток которые прячут эти различия?


        я не люблю засорять собственную ОС, предпочитая работать через chroot, virtualbox или docker.

        да, пакетные менеджеры под mac os не настолько крутые как под linux,
        но они есть и неплохо работают, зачем засорять-то?


        1. Doktor3lo
          26.07.2017 03:42

          Какая-то классовая ненависть в голосе…

          Повторюсь, vim мне нравится, я им пользуюсь. Но, например, межфайловая навигация в нем — ужасна. Копирование через буфер обмена — тоже та еще рулетка. Нет, всё решаемо, но требует определенного напряжения.

          Да, я пишу софт для настройки этой самой ОС и обертки тут не всегда помогают. Отсюда же нежелание запускать что-либо на своей ОС — можно поиметь кучу лишнего геморроя. Даже, когда вместо Mac у меня был Linux, я так не делал.

          В процессе экспериментов в ОС скапливается туча ненужных пакетов и каких-то настроек. Создается неповторимое окружение, которое порождает неповторимые сборки (про запуск я вообще молчу). Это как раз тот случай, когда только у разработчика «всё работает».


  1. ElijahTh
    26.07.2017 11:26

    Я так понял, у вас нет завязанности на определённую IDE.

    В NetBeans из коробки есть поддержка сценариев «хочу работать из локальной IDE с проектом, который лежит за тридевять земель и собирать его (само-собой) под ОС удалённой машины».

    Она называется Remote Development. Небольшое описание здесь [1] и про виды этого Remote Development здесь [2] (отличаются способы доступа к сорцам проекта: можно настроить авто-синхронизацию, можно использовать более щадящий режим, когда машины видят друг друга через NFS/SMB/...).

    Собственно, Docker и Conan в этой связке становится не нужен. Поддержка ninja тоже есть из коробки, достаточно указать директорию с build.ninja при создании C/C++ Project With Existing Sources.

    [1] https://netbeans.org/kb/docs/cnd/remotedev-tutorial.html
    [2] https://netbeans.org/kb/docs/cnd/remote-modes.html


    1. Doktor3lo
      26.07.2017 11:33

      Спасибо — посмотрю.
      Последний раз я смотрел на него довольно давно — это был жуткий тормоз…
      Правда, и CLion поначалу был тот еще тормоз :)