Простой conanfile.py для сборки библиотеки.

Опубликовано SergeyOs - вс, 03/22/2020 - 22:38

Допустим что для сборки какого-нибудь проекта нужно выкачать и собрать библиотеку. Для примера возьмём библиотеку JsonCPP

Это выглядит примерно так: качаем исходники.

# git clone https://github.com/open-source-parsers/jsoncpp.git .
# git checkout tags/1.9.0

Затем собираем (Собираем статические библиотеки и кладём всё в "/opt/jsoncpp"):

# mkdir build
# cd build
# cmake .. -DCMAKE_BUILD_TYPE=release -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_LIBDIR=/opt/jsoncpp/lib -DCMAKE_INSTALL_INCLUDEDIR=/opt/jsoncpp/include/ -DJSONCPP_WITH_TESTS=False -G "Unix Makefiles" 
# make 
# sudo make install

Для примера, проект использующий эту библиотеку состоит из двух файлов: main.cpp и CMakeLists.txt

текст программы main.cpp

#include <iostream>
#include <json/json.h>
 
int main()
{
  Json::Value root;
  root["test"] = "testvalue";
  std::cout << root << std::endl;
  return 0;
}

CmakeLists.txt

cmake_minimum_required(VERSION 3.5)
 
project(jsonshow)
add_definitions("-std=c++14")
 
add_executable(jsonshow main.cpp)
target_include_directories(jsonshow PUBLIC /opt/jsoncpp/include/jsoncpp)
target_link_libraries(jsonshow /opt/jsoncpp/libjsoncpp.a)

Собираем программку.

#mkdir build
#cd build
#cmake .. -DCMAKE_BUILD_TYPE=release
#make

Перейдём к тому как сделать сборку библиотеки jsoncpp с помощью менеджера пакетов Conan. Для начала нам понадобятся python и сам conan

# sudo zypper install python3
# sudo pip3 install conan

В проекте делаем каталог "deps/jsoncpp". Здесь создадим конфигурацию для сборки jsoncpp, для этого напишем питоноскрипт "conanfile.py". Для этого надо определить несколько методов (полный список можно почитать в официальной документации). Но нужны только "source", "build", "package_info".

Метод "source". Он повторяет наши действия по скачиванию исходников.

    def source(self):
        tools.get("https://github.com/open-source-parsers/jsoncpp/archive/%s.tar.gz" % self.version)
        extracted_dir = "jsoncpp-{}".format(self.version)
        os.rename(extracted_dir, "sources")

Далее метод сборки "build". Почти всё также как вызывали cmake, но с некоторыми изменениями. В конфигурации предусмотрим возможность сборки статической и динамической версий. Поэтому в опцию "BUILD_SHARED" будем передавать параметр из настроек "self.options.shared". Описание "options" разберём чуть ниже. Вместо путей для библиотек и заголовков используем "INSTALL_DIR". Если библиотека динамическая и сборка не на windows машине, то нужно включить опцию "CMAKE_POSITION_INDEPENDENT_CODE", это позволяет использовать одну копию библиотеки для нескольких процессов, что, в свою очередь, экономит память

    def build(self):
        cmake = CMake(self)
        cmake.definitions["BUILD_SHARED"] = self.options.shared
        cmake.definitions["BUILD_STATIC_LIBS"] = "ON"
        cmake.definitions["JSONCPP_WITH_TESTS"] = False
        cmake.definitions["INSTALL_DIR"] = os.path.join(self.package_folder)
        if not tools.os_info.is_windows:
            cmake.definitions["CMAKE_POSITION_INDEPENDENT_CODE"] = self.options.shared
 
        cmake.configure(source_folder = "sources")
        cmake.build()
        cmake.install()

Метод "package_info" указывает имя библиотеки, чтобы cmake мог её правильно идентифицировать.

    def package_info(self):
        self.cpp_info.libs = ['jsoncpp']

Указываем опции сборки в главном классе, которые можно будет задать при запуске скрипта из менеджера пакетов conan. Также надо прописать значения по умолчанию.

    options = {"shared": [True, False]}
    default_options = {"shared": False}

Общий код файла "deps/jsoncpp/conanfile.py"

from conans import ConanFile, CMake, tools
import os, shutil
 
class JsoncppConan(ConanFile):
    name = "jsoncpp"
    homepage = "https://github.com/open-source-parsers/jsoncpp"
    topics = ("conan", "json", "parser", "config")
    settings = "os", "compiler", "arch", "build_type"
    options = {"shared": [True, False]}
    default_options = {"shared": False}
    generators = "cmake"
    version = "1.9.0"
 
    def source(self):
        tools.get("https://github.com/open-source-parsers/jsoncpp/archive/%s.tar.gz" % self.version)
        extracted_dir = "jsoncpp-{}".format(self.version)
        os.rename(extracted_dir, "sources")
 
    def build(self):
        cmake = CMake(self)
        cmake.definitions["BUILD_SHARED"] = self.options.shared
        cmake.definitions["BUILD_STATIC_LIBS"] = "ON"
        cmake.definitions["JSONCPP_WITH_TESTS"] = False
        cmake.definitions["INSTALL_DIR"] = os.path.join(self.package_folder)
        if not tools.os_info.is_windows:
            cmake.definitions["CMAKE_POSITION_INDEPENDENT_CODE"] = self.options.shared
 
        cmake.configure(source_folder = "sources")
        cmake.build()
 
    def package_info(self):
        self.cpp_info.libs = ['jsoncpp']

Далее надо изменить файл CmakeLists.txt. Подключить "conanbuildinfo.cmake", вызвать макрос "conan_basic_setup()", вместо конкретной библиотеки прописать переменную "${CONAN_LIBS}", и подключить include директорию, тоже через переменную conan.

cmake_minimum_required(VERSION 3.5)
 
project(jsonshow)
add_definitions("-std=c++14")
 
include(conanbuildinfo.cmake)
conan_basic_setup()
 
add_executable(jsonshow main.cpp)
target_include_directories(jsonshow PUBLIC ${CONAN_INCLUDE_DIRS})
target_link_libraries(jsonshow ${CONAN_LIBS})

Также надо создать файл, который будет конфигурить наш проект - "conanfile.txt". Его нужно положить рядом с файлом "CmakeLists.txt".

содержимое conanfile.txt:

[requires]
jsoncpp/1.9.0@demo/testing
 
[generators]
cmake
 
[options]
jsoncpp:shared=False
 
[imports]

В итоге структура проекта будет такая:

|-deps
  |-jsoncpp
    |--conanfile.py
|-CmakeLists.txt
|-conanfile.txt
|-main.cpp

Теперь проект конфигурить надо так (из директории проекта):

# conan create deps/jsoncpp/ demo/testing
# conan install .

В результате первой команды conan выкачает и соберёт библиотеку jsoncpp, второй - подготовит наш проект для сборки. И, традиционная сборка:

# mkdir build
# cd build
# cmake .. -DCMAKE_BUILD_TYPE=release
# make

Плюсом всей этой пляски, что проект теперь легко собрать под Windows и MacOS. Например, для Windows, в папке сборки указать:

# cmake .. -DCMAKE_BUILD_TYPE=release -G "Visual Studio 15 Win64"

Будет создан проект для Visual Studio.