Войти
ПрограммированиеФорумОбщее

Организация личных C++ проектов (модулей) (4 стр)

Страницы: 1 2 3 4
#45
(Правка: 1:26) 1:25, 22 янв. 2021

pahaa
я предполагал такую логику:
1) создаем репу myTrunk(develop)
2) кладем в него engineV1(это наш движок он шарится между всеми)
3) заливаем в git
4) например пишем сразу три игры, делаем три бренча(branch v1), (branch v2), (branch v3)
5) в каждой ветке пишем код специфичный для этой игры(myCore1, myCore2, myAnotherCore)
6) в случае правки общего кода и если это нужно(engineV1) реинтегрируем его в myTrunk
7) если нужно втянуть эти изменения в другие проекты делаем у них rebase(чтобы к ним подтянулись последние изменения из myTrunk)
8) завершая какой либо из проектов, делаем у него ребейз и реинтегрируем проектно-специфичный код(myCore1, myCore2, myAnotherCore) и/или общий код engineV1 в myTrunk, ну или вообще не делаем ни одного ни другого.
9) в myTrunk делаем рефакторинг готовим все для нового проекта
10) идем к п.4

#46
(Правка: 1:47) 1:27, 22 янв. 2021

xDimka
> ну почему же жесть, это называется форк.

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

1. внесения своих изменений в чужой проект. мы форкаем, вносим правки, а потом пулл-реквестами портируем изменения обратно в исходный репозиторий. собственно именно так разрабатывается линукс, для которого и был создан Git, и куча других проектов.

2. разработка своего собственного продукта, взяв за основу код исходного репозитория. обычно это просто развитие своей версии некой библиотеки, взаимодействие с которой по первому пункту неудобно или невозможно - например нужные изменения не соответствуют уровню качества исходника или его философии, или оригинальный разраб просто забросил библиотеку. но иногда благодаря форку появляется продукт конкурент. в подавляющем кол-ве случаев "класс" продукта после форка не меняется.

Cocos2dx, формально - это второй пункт. но он выбивается из тренда, т.к. на выходе мы получаем продукт другого "класса". я не говорю что это плохо - выглядит очень удобно в случае если движок хорошо заточен под определенные задачи (как раз тот случай). но это далеко не эталонный пример работы форков.

#47
(Правка: 1:43) 1:39, 22 янв. 2021

xDimka

я предполагал такую логику:
1) создаем репу myTrunk(develop)
2) кладем в него engineV1(это наш движок он шарится между всеми)
3) заливаем в git
4) например пишем сразу три игры, делаем три бренча(branch v1), (branch v2), (branch v3)
5) в каждой ветке пишем код специфичный для этой игры(myCore1, myCore2, myAnotherCore)
6) в случае правки общего кода и если это нужно(engineV1) реинтегрируем его в myTrunk
7) если нужно втянуть эти изменения в другие проекты делаем у них rebase(чтобы к ним подтянулись последние изменения из myTrunk)
8) завершая какой либо из проектов, делаем у него ребейз и реинтегрируем проектно-специфичный код(myCore1, myCore2, myAnotherCore) и/или общий код engineV1 в myTrunk, ну или вообще не делаем ни одного ни другого.
9) в myTrunk делаем рефакторинг готовим все для нового проекта
10) идем к п.4

теперь понял вашу схему, спасибо за пример!

но ведь я бы хотел оставить и myCore1 и myCore2, так чтобы любой из моих прототипов мог использовать любой из них.
а также оставить myRender1 и myRender2, чтобы любой прототип мог использовать любой из них с любым из myCore1 и myCore2.

как это сделать, не вливая myCore1, myCore2, myRender1 и myRender2 в транк?

#48
(Правка: 6:19) 3:23, 22 янв. 2021

kkolyan
>
> как это сделать, не вливая myCore1, myCore2, myRender1 и myRender2 в транк

Никак. В этом и суть, trunk или develop это сборная солянка для всего. Все выходит из неё и если что-то будет нужно то и возвращается в неё. Технически делается полный мерж всего бранча в myTrunk. После этого проще всего бранч пересоздать из myTrunk заново. Черри пики из бранчей в myTrunk недопускаются, только полный мерж. Из myTrunk в бранчи - допустимо, но разумней ребейз.
Вообщем мало помалу вот так и строится continuous integration.

#49
7:17, 22 янв. 2021

xDimka
> в каждой ветке пишем код специфичный для этой игры(myCore1, myCore2,
> myAnotherCore)
Этот подход исключает вариант, когда некоторый код делится только с НЕКОТОРЫМИ проектами. У меня в примере не зря myCore был без цифры. Это код, специфичный для кор-механики, а не для игры. И я эту механику хочу затащить в 2 разные игры, но не в третью. У всех трёх игр разная мета, но у первых двух одинаковый кор-геймплей.

#50
(Правка: 13:50) 13:41, 22 янв. 2021

xDimka

Никак. В этом и суть, trunk или develop это сборная солянка для всего. Все выходит из неё и если что-то будет нужно то и возвращается в неё. Технически делается полный мерж всего бранча в myTrunk. После этого проще всего бранч пересоздать из myTrunk заново. Черри пики из бранчей в myTrunk недопускаются, только полный мерж. Из myTrunk в бранчи - допустимо, но разумней ребейз.
Вообщем мало помалу вот так и строится continuous integration.

ну да, в общем-то обычный trunk-based монолит.

но cкладывается впечатление, что и в C++ мире (не утверждаю что он однороден) распределенная инфраструктура если не преобладает, то по крайней мере очень популярна. кстати, в распределенной инфраструктуре continuous integration тоже отлично работает.

PS: рибейз, при живом мерже...
#51
14:46, 22 янв. 2021

pahaa
> Этот подход исключает вариант, когда некоторый код делится только с НЕКОТОРЫМИ
> проектами. У меня в примере не зря myCore был без цифры. Это код, специфичный
> для кор-механики, а не для игры. И я эту механику хочу затащить в 2 разные
> игры, но не в третью. У всех трёх игр разная мета, но у первых двух одинаковый
> кор-геймплей.
В примере который я привёл, engine1 является общим для всех трёх. Если вам его не нужно использовать, не используйте. А то что он присутствует физически в вашем бренча как раз обеспечивает что все ваши интеграционные и юнит тесты проходят до того как вы вообще что-то будете заливать в ваш бренч для всех проектов.

#52
15:00, 22 янв. 2021

kkolyan
> но cкладывается впечатление, что и в C++ мире (не утверждаю что он однороден)
> распределенная инфраструктура если не преобладает, то по крайней мере очень
> популярна. кстати, в распределенной инфраструктуре continuous integration тоже
> отлично работает.
В мире обычно превалирует product ориентированная модель. У продукта есть циклы жизни, планирование, разработка, поддержка. Игры в одном жанре, например шутеры от первого лица, как раз и будет для этой компании продуктом. То есть этот и все последующие шутеры от этой компании фактически это будут развитием одного первого шутера и всегда будут в одном репозиторий.

#53
23:07, 22 янв. 2021

war_zes

>> смотреть на find_package и add_subdirectory.
>Очень хреновая вещь - потом мучаешься с разворачиванием всех зависимостей, ведь оно только ищет, оно не подгружает. За такое и ругают С++ - качаешь какой-нибудь проект, и затем по несколько часов начинаешь руками собирать все зависимости, чтобы CMake перестал ругаться и наконец-то сделал тебе солюшен или что там надо.

Я думаю, «ругают цпп» по существу в основном за то, что нужно знать довольно много разносторонней фигни, чтобы делать осмысленные вещи, а не ерунду. И, как следствие, довольно много ерунды в паблике, которая еще больше увеличивает порог входа – и так по кругу.
find_package – вещь не хреновая, просто она делает то, для чего предназначена (наверно), а не то, чего кому-то там бы хотелось: если локально разрабатывается несколько компонентов и много проектов, от них зависящих, то копипастить их по всей файловой системе средствами гитовских сабмодулей может оказатсья не лучшей идеей. С другой стороны, как раз  add_subdirectory отлично комбинируется именно с сабмодулями.
И Cmake может сам скачивать зависимости при должном использовании.
Подкину еще ссылок, вдруг пригодятся кому
https://stackoverflow.com/questions/8153519/how-to-automatically-… orm-way-cmake
https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html
https://foonathan.net/2016/03/cmake-install/

#54
3:09, 23 янв. 2021

dirmenbitz
огромное спасибо за ссылки. особенно зашла последняя. прямо отвечает на многие тонкие вопросы, которые неуловимо вертятся в голове и не удовлетворяются поиском.

#55
(Правка: 7:19) 6:28, 25 янв. 2021

Пожалуй, буду использовать эту тему для отчетов о своих находках по теме. Крестонубам вроде меня, пришедшим из хипстерских сфер, будет полезно. Да и местные опытные крестовики, надеюсь поправят, если совсем ересь буду писать.

Итак, я выбрал подход с формирование инфраструктуры, состоящей из разных библиотек, распиханным по отдельным репозиториям. Буду называться их проектами, хотя каждый из этих проектов является только кирпичиком возможного продукта.

Каждый такой проект в общем случае имеет

  • основные сорцы
  • тестовые сорцы
  • сорцы тулов вроде генераторов кода
  • ссылается на другие проекты семейства
  • ссылается на сторонние библиотеки и тулы
  • Правила

    1.1. Корневой CMakeLists.txt ничего не делает кроме инклюда других cmake-скриптов.

    1.2. Каждому артефакту (создаваемым напрямую экзешникам и либам) отвидится своя папка со своим CMakeLists.txt, включаемым в проект с помощью add_subdirectory.

    1.3. Скрипт сборки артефакта  конфигурирует ровно 1 таргет, который может быть использован в других скриптах сборки проекта.

    1.4. В скрипте сборки артефакта задаются исходные файлы для сборки (я включаю только CPP, т.к. хедеры подцепятся за ними сами)

    1.5. В том же скрипте, при помощи target_link_libraries задается список требуемых артефактом библиотек (задаются только имена таргетов - никаких файловых путей здесь)

    1.6. При помощи add_dependencies задается порядок сборки относительно других таргетов (если имеет значение)

    1.7. Если этот артефакт является тулой, то скрипт должен объявить cmake-функцию, которую другие скрипты смогут вызвать не заботясь о месте расположения исполняемого файла.

    1.8. А при помощи target_include_directories с опцией PUBLIC или INTERFACE указываем папки с хедерами,  которые нужны зависимым артефактам. не очень интуитивно, т.к. эта же команда может использоваться чтобы указать, наоборот, нужные этому артефакту хедеры (в этом скрипте мы ни в коем случае такого не делаем - оставим это для скриптов импорта при интеграции с чужеродными либами).


    2.1. Каждая подключаемая напрямую зависимость конфигурируется через отдельный cmake-скрипт - скрипт импорта (такие скрипты кладем в папку cmake и подключаем к проекту с помощью include)

    2.2. Здесь скрипт уже может быть устроен по разному, но смысл в том, что он должен выдать в контекст сборки таргет (здесь уже может быть более одного) с проассоциированными с ним бинарниками и папками с хедерами таким образом, чтобы их автоматом подхватывал target_link_libraries, а также функции для удобного вызова всех предсотавляемых тулов.

    2.3. Если либа какая-нибудь очень увесистая, то она должна быть установлена на локальную машину руками (например через vcpkg), откуда скрипт импорта их и подцепит.

    2.4. Если либа достаточно легкая, то скрипт импорта выкачивает ее с помощью FetchContent.

    2.5. Если либа при этом еще и имеет совместимый стиль CMake скриптов (например это другой проект нашей же инфраструктуры), то FetchContent сам же и включит либу в проект со всеми предоставляемыми таргетами.



    Как-то так. Вроде все по полочкам и минималистично, а работает удобно, масштабируемо и без прописывания путей вручную, если не считать git-адреса и путь к тулчейну vcpkg (впрочем он задается в IDE, а не хардкодится)
    Страницы: 1 2 3 4
    ПрограммированиеФорумОбщее