blog.michalt.pl

Conan nie barbarzyńca i C++

09.12.2021 23:45 Tech

Czym jest Conan? To kolejny menadżer zależności lub jak kto woli, menadżer pakietów. Ten dedykowany jest dla języka C++. Od dawna istnieją już podobne rozwiązania, takie jak np. Maven dla Javy, NPM dla NodeJS, czy Cagro dla języka Rust. W tym wpisie chciałbym nieco przyjrzeć się temu narzędziu i podzielić się z Wami moimi spostrzeżeniami na jego temat. Jak na mnie przystało, przykłady tu zamieszczone będą pochodzić z konsoli systemu Debian Linux. Między Linuksem i Windowsem nie powinno być różnic.

Omawiane dziś narzędzie można pobrać z jego oficjalnej strony conan.io. Dostępne są instalatory dla systemów linuksowych, Windows i MacOS. Jako że jest ono otwartoźródłowe, możemy podjąć się próby jego kompilacji i instalacji na innych systemach, na przykład FreeBSD.



Nowy projekt – czyli jak się tego używa?

Przy zaciąganiu zależności, możemy korzystać z różnych źródeł, ja spróbuję z conancenter. Najlepiej zacząć od stworzenia pliku conanfile.txt w katalogu projektu. Do niego będziemy dodawać wszystkie zależności.

Spróbujmy z wysokopoziomową biblioteką SFML z której pomocą możemy tworzyć różnego rodzaju aplikacje multimedialne w tym na przykład gry.


Najpierw wyszukajmy dostępne wersje:

$ conan search sfml --remote=conancenter
Existing package recipes:
sfml/2.5.1

Jak widać, mamy dostępną tylko jedną, jest to 2.5.1 i z niej skorzystamy.

Nim tak się stanie, warto zaczerpnąć o niej kilka informacji, np. poznać narzędzie do budowania z którego korzysta – będzie ono znajdowało się w sekcji generator:
$ conan inspect sfml/2.5.1  
name: sfml
version: 2.5.1
url: https://github.com/conan-io/conan-center-index
homepage: https://www.sfml-dev.org
license: Zlib
author: None
description: Simple and Fast Multimedia Library.
topics: ('sfml', 'multimedia', 'games', 'graphics', 'audio')
generators: ('cmake', 'cmake_find_package', 'cmake_find_package_multi')
exports: None
exports_sources: ['CMakeLists.txt', 'patches/**']
short_paths: False
apply_env: True
build_policy: None
revision_mode: hash
settings: ('os', 'arch', 'compiler', 'build_type')
options:
   audio: [True, False]
   fPIC: [True, False]
   graphics: [True, False]
   network: [True, False]
   shared: [True, False]
   window: [True, False]
default_options:
   audio: True
   fPIC: True
   graphics: True
   network: True
   shared: False
   window: True
deprecated: None

Jak widać, po wywołaniu conana z parametrem inspect otrzymaliśmy sporo przydatnych informacji, jak np. zastosowanie biblioteki – sekcja topics, opis – sekcja description, licencja i interesujące nas generatory – sekcja generators.


Jeśli nie interesuje Was cała zawartość opisu, polecam skorzystać z grepa:

$ conan inspect sfml/2.5.1 | grep generators
generators: ('cmake', 'cmake_find_package', 'cmake_find_package_multi')

Jak widać, mamy tu do czynienia z cmake. Jeśli w generatorach będzie cmake, pamiętaj o jego zainstalowaniu w systemie.

Przejdźmy do pliku conanfile.txt. Aby móc skorzystać z wyżej wymienionej wersji, należy wpisać do niego następujące informacje, które uzyskaliśmy wcześniej:

[requires]
sfml/2.5.1
[generators]
cmake

Różne narzędzia mają swoje różne wymagania, w przypadku cmake powinniśmy utworzyć w naszym projekcie katalog build, a następnie przejść do niego i wywołać polecenie:

$ conan install ..

Okazało się, że brakuje kilku zależności:

ERROR: Missing prebuilt package for 'brotli/1.0.9', 'bzip2/1.0.8', 'flac/1.3.3', 'freetype/2.11.0', 'libalsa/1.2.4',
'libpng/1.6.37', 'ogg/1.3.4', 'openal/1.21.1', 'sfml/2.5.1', 'vorbis/1.3.7', 'zlib/1.2.11'
Try to build from sources with '--build=missing'
Use 'conan search --table table.html'
Or read 'http://docs.conan.io/en/latest/faq/troubleshooting.html#error-missing-prebuilt-package'

Jak zapewne zauważyliście, conan podpowiedział jak rozwiązać ten problem:

$ conan install .. --build=missing

Może się okazać, że nasze zależności nie występują w żadnych dostępnych repozytoriach, wówczas konieczne będzie ich zaciągnięcie i zainstalowanie poza Conanem.

Gdy rozejrzymy się po katalogu build, okaże się, że nie znajdziemy w nim zaciągniętej biblioteki. Można natomiast zauważyć 4 pliki: conan.lock, conanbuildinfo.txt, conaninfo.txt i graph_info.json. Plik conan.lock jest odpowiednikiem na przykład pliku package-lock.json znanego z nodeJS – mamy tu listę zależności z ich wersjami. W pozostałych znajdziemy informację o położeniach bibliotek (w Linuksie znajdują się one w katalogu ~/.conan/data/), pełnych zależnościach i opcjach budowania.



Co poza tym?

Możemy również tworzyć własne pakiety bibliotek, a nawet je eksportować.

Przygotowanie pakietu wymaga m.in. utworzenia pliku conanfile.py i przygotowanie odpowiedniej konfiguracji w języku Python. Co ciekawe, możemy posłużyć się gotowymi templatami i wygenerować taki plik.

Wystarczy wydać polecenie:

conan new michalt/1.0 --template=cmake_lib

Gdzie michalt to nazwa projektu, 1.0 to jego wersja, a cmake to generator.


Po wydaniu tego polecenia utworzone zostaną następujące pliki:

CMakeLists.txt
conanfile.py
src/michalt.cpp
src/michalt.h
test_package/CMakeLists.txt
test_package/conanfile.py
test_package/src/example.cpp

Nasze pakiety możemy również wgrywać do repozytoriów pakietów, na przykład na conancenter lub utworzyć własne.

Więcej na ten temat znajdziecie w oficjalnej dokumentacji tego narzędzia, na stronie docs.conan.io



Nie barbarzyńca? A może jednak?

Pierwszy raz z Conanem zetknąłem się w korpo w którym pracowałem. Tam to była nowość, którą uznano za rewolucyjną. Co ja o nim myślę? Uważam, że ułatwia on pracę z zależnościami, ale nie jest panaceum na wszystkie problemy – baza pakietów ma trochę braków, które trzeba będzie zaciągnąć z innych miejsc. Różne generatory również mogą przyprawić nas o pewne problemy. Sprawdziłem przy okazji, czy obsługuje znane z Qt, qmake i okazało się, że niestety nie. Na szczęście Qt Framework od wersji 6.0 posiada wsparcie również dla Cmake. Czy wdrożę go w swoje hobbystyczne projekty? Poważnie się nad tym zastanawiam, ale jeszcze nie jestem tego pewien. Czas pokaże...

To na tyle w tym wpisie,
do przeczytania! :)