• Как правильно организовать модульный проект с использованием CMake?

    @4rtzel
    Поскольку CMake позволяет получить один и тот же результат кучей разный способов, то я постараюсь описать подход, который использовал бы я сам.
    Структура:
    packages_test
    ├── .git
    ├── cmake // Папка с доп. CMake скриптами если в этом есть необходимость
    ├── build // Результат сборки
    │   └─ res.exe // Исполняемый файл
    ├── CMakeLists.txt // Конфигурация сборки проекта
    ├── src
    │   ├─ main.cpp // Точка входа, main()
    │   └─ ...// Прочие файлы проекта
    ├── dependencies // Зависимости (подключаются через механизм submodule)
    │   ├─ vendor_package_0 // У каждой зависимости своя внутренняя организация
    │   └─ vendor_package_1
    └── test // Тесты
        ├── CMakeLists.txt
        └── src
            └── test_main.cpp

    Теперь, как мы будем добавлять зависимости? Это зависит от того где расположены библиотеки и как они собираются. В вашем случае, как я понимаю, все vendor_package_x представляют из себя CMake проекты с использованием add_library и получаемые из git submodule'ей. Это значит, что мы можем использовать add_subdirectory для импорта их target'ов.

    | Note: find_package чаще всего используется для поиска установленных в системе библиотек с помощью FindXXX.cmake скриптов

    Главный CMakeLists.txt:
    cmake_minimum_required(VERSION 3.0)
    project(playrix_project VERSION 1.0 LANGUAGES CXX)
    add_executable(playrix src/main.cpp)
    
    # Импортируем наши зависимости. Это не приводит к сборке, но просто позволяет нам использовать target'ы этих проектов.
    add_subdirectory(dependencies/vendor_package_0)
    add_subdirectory(dependencies/vendor_package_1)
    
    # Забудьте про include_directories и link_directories! В современном CMake следует использовать targets и properties.
    # Опредеяем зависимости нашего проекта
    target_link_libraries(playrix # Имя нашего executable'а
        PRIVATE # Определяет область видимости зависимостей для внешних проектов
            vendor_package_0_target # Настоящее имя target'а надо смотреть в vendor_package_0 CMakeLists.txt (add_library)
            vendor_package_1_target
    )

    target_link_libraries позаботится о том, чтобы собрать все зависимости, слинковать (если надо) их с нашим проектом и инклюднуть необходимые директории. Теперь можно собирать проект!

    Дополнительные ссылки:
    Ответ написан
    2 комментария
  • Как и куда писать статьи с собственными размышлениями?

    gordon_shamway
    @gordon_shamway
    geektimes, свой блог
    Ответ написан
    Комментировать
  • Как правильно организовать проект, выкладываемый в open source?

    Да, возможно, это тоже важно. Библиотека написана на С++.

    Да, это важно. Мы тоже используем примерно ту же структуру проектов, и стараемся её придерживаться на всех используемых платформах, однако технические различия между ними диктуют и различия в структуре. Например, папка include в мире .net не нужна, т.к. вся необходимая информация о содержимом библиотеки находится в самой сборке. То же касается и Java-библиотек. В целом, я согласен с вами по структуре репозитория (единственная вкусовщина для меня - называть папки docs и tests во мн. числе :)).

    Другие папки - какие?

    Вот в последнее время считаю крайне полезной папку examples с кодом примеров по использованию библиотеки. Очень удобно, когда на основные сценарии использования либы есть по проекту/файлику с кодом примера. Очень быстро можно пробежаться по возможностям библиотеки, и оценить удобство использования (накануне сранивал таким образом json-либы для C++). И для вас это тоже своеобразные "тесты" на удобство. У этих "тестов" задача не покрыть логику на 100%, а показать, как взаимодействовать с библиотекой в основных, стандартных сценариях.

    Отмечу, что вы очень хорошо написали про API библиотеки в include. Многие разработчики почему-то кладут в эту папку и приватные хедеры тоже. Я лично в этом смысла не вижу - все приватные хедеры это часть основных исходников, а они находятся в /src.

    потом копи-пастой тащу папку include и папку с собранными бинами к себе в проект

    Вот это я не знаю честно говоря, зачем вы делаете - папки include и lib как раз на то и рассчитаны, чтобы их было удобно подключать к компилятору и линковщику - как раз пути к этим папкам и передаются при подключении зависимых библиотек. Единственное, что может быть нужно скопировать из папки библиотеки - собранные бинарники (dll/so) в случае динамической линковки, если нет возможности/желания прописывать пути к динамическим библиотекам. Ну и какие-нибудь файлы данных, если таковые есть.

    Тесты вообще должны собираться вместе с библиотекой (например, в папку /bin), также по идее ничего никуда копировать не надо.

    Вообще ваш вопрос сильно связан с организацией процесса сборки библиотеки и её подключения к другим проектам. В C++ к сожалению до сих пор нет стандартного или хотя бы популярного соглашения об управлении зависимостями, иными словами, пакетного менеджера. Многие библиотеки сегодня подключаются через системные пакетные менеджеры, если таковые присутствуют в ОС.

    Также, вы почему-то не указали используемую систему сборки. В том же CMake есть очень полезная фишка, называется find_package, которую грех не использовать.

    В целом, отмечу что копи-пасты должно быть минимум, include и lib копироваться не должны вообще, для этого у любого компилятора есть ключи (например, -I и -L). Даже если копирование неизбежно, его следует максимально автоматизировать в сборочных инструкциях. Многие системы сборки умеют определять, что некоторые файлы устарели (например, вы перекомпилили dll), и в этом случае их можно попросить скопировать эти файлы.

    Чем вы все-таки либу свою собираете? Это важно, т.к. даже для опытных разработчиков сборка незнакомой C++ библиотеки может стать целым делом.

    Да, кстати еще момент с include-ами: именно по причине того, что библиотеки обычно подключаются путем указания путей компилятору и линковщику (которые потом соберут содержимое всех include и lib-папок в единое пространство имён), есть популярная договоренность создавать в папке include подпапку с именем библиотеки, например: раз, два, три. Это даёт возможность инклудить так: #include <soci/blob.h>, а не так: #include <blob.h>. Это позволяет разработчику называть файлы коротко и так, как ему удобно (blob.h вместо soci_blob.h), и при этом сводить риск конфликта имен инклудов к минимуму.
    Ответ написан
    7 комментариев
  • Почему нельзя объявлять стековые объекты внешних классов для внутренних классов?

    @MiiNiPaa
    Класс считается complete когда при его парсинге достинается закрывающая скобка. При объявлении вложенного класса внутри внешнего, он ещё не полон и объявить член его типа нельзя. Указатель на неполный тип создавать можно, поэтому первый вариант компилируется.

    Поправить можно так:

    struct Outer 
    {
      struct Inner;
    };
    
    struct Outer::Inner 
    {
        Outer _outer;
        Inner() : _outer() { }
    };
    Ответ написан
    1 комментарий
  • Как правильно лицензировать библиотеку?

    littleguga
    @littleguga
    Не стыдно не знать, а стыдно не интересоваться.
    1. Лучше всего разместить библиотеку на github(Вы писали, что плаваете в git'e, вот курс, который займет всего 15 минут)
    В корень репозитория положить LICENSE или LICENSE.md/txt и т.д
    В readme дополнительно указать, что см файл лицензии

    2. По сути вы разрешаете ее любую модификацию для конечного пользователя, а глобальную(обновление в репозитории), только с Вашего разрешения или управляющих репозиторием(этот пункт отлично решается использованием github - pull requests и ответственные за репозиторий)

    3. Так и пропишите в файле лицензии, что я такой-то такой-то автор данной библиотеки оставляю за собой право на смену лицензии(если ориентируетесь не только на РУ сегмент, то напишите на английском)

    Вот эту ссылку Вы уже находили, в commercial use - other и прописываете, что Вам должны заплатить за использование.

    По сути, возьмите за основу MIT лицензию и измените нужные Вам пункты. Никто не мешает Вам создать свой тип лицензии.
    Ответ написан
    7 комментариев
  • Основные отличия habraharb, geektimes и megamozg?

    EvilsInterrupt
    @EvilsInterrupt
    System programming, Reversing Engineering, C++
    Лучше бы они сделали возможность голосовать за перенос между гиктаймзом, хабром и мегамозгом, а сообщество само бы приняло решение куда что поместить
    Ответ написан
    1 комментарий