From 8b38ff21e35708cc989de8cd54777a3255ede1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduard=20=C4=8Cuba?= Date: Mon, 30 Oct 2017 11:11:48 +0100 Subject: [PATCH] Add gobject and wrap it into C++ object --- CMakeLists.txt | 5 ++ cmake/modules/FindGLIB.cmake | 122 +++++++++++++++++++++++++++++++++++ libdnf/CMakeLists.txt | 12 +++- libdnf/package.cpp | 25 +++++++ libdnf/package.hpp | 46 +++++++------ libdnf/swdb.hpp | 6 ++ libdnf/swdb/CMakeLists.txt | 80 +++++++++++++++++++++++ libdnf/swdb/package.cpp | 53 +++++++++++++++ libdnf/swdb/package.hpp | 29 +++++++++ run.sh | 3 + tests/python/run_tests.py.in | 2 +- tests/python/test_swdb.py | 26 ++++++++ 12 files changed, 388 insertions(+), 21 deletions(-) create mode 100644 cmake/modules/FindGLIB.cmake create mode 100644 libdnf/package.cpp create mode 100644 libdnf/swdb.hpp create mode 100644 libdnf/swdb/CMakeLists.txt create mode 100644 libdnf/swdb/package.cpp create mode 100644 libdnf/swdb/package.hpp create mode 100644 tests/python/test_swdb.py diff --git a/CMakeLists.txt b/CMakeLists.txt index a0e1010..e6e0eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,11 @@ ADD_COMPILE_OPTIONS (-std=c++11 -Wall -Wextra -Wno-unused-parameter -fPIC) PROJECT (libdnf) +# include GLib +find_package(PkgConfig) +SET (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) +PKG_CHECK_MODULES(GLIB gio-unix-2.0>=2.46.0 REQUIRED) +INCLUDE_DIRECTORIES(${GLIB_INCLUDE_DIRS}) if (${PYTHON_DESIRED} STREQUAL "2") message("Building for python2") diff --git a/cmake/modules/FindGLIB.cmake b/cmake/modules/FindGLIB.cmake new file mode 100644 index 0000000..30124bf --- /dev/null +++ b/cmake/modules/FindGLIB.cmake @@ -0,0 +1,122 @@ +# - Try to find Glib and its components (gio, gobject etc) +# Once done, this will define +# +# GLIB_FOUND - system has Glib +# GLIB_INCLUDE_DIRS - the Glib include directories +# GLIB_LIBRARIES - link these to use Glib +# +# Optionally, the COMPONENTS keyword can be passed to find_package() +# and Glib components can be looked for. Currently, the following +# components can be used, and they define the following variables if +# found: +# +# gio: GLIB_GIO_LIBRARIES +# gobject: GLIB_GOBJECT_LIBRARIES +# gmodule: GLIB_GMODULE_LIBRARIES +# gthread: GLIB_GTHREAD_LIBRARIES +# +# Note that the respective _INCLUDE_DIR variables are not set, since +# all headers are in the same directory as GLIB_INCLUDE_DIRS. +# +# Copyright (C) 2012 Raphael Kubo da Costa +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +find_package(PkgConfig) +pkg_check_modules(PC_GLIB QUIET glib-2.0) + +find_library(GLIB_LIBRARIES + NAMES glib-2.0 + HINTS ${PC_GLIB_LIBDIR} + ${PC_GLIB_LIBRARY_DIRS} +) + +# Files in glib's main include path may include glibconfig.h, which, +# for some odd reason, is normally in $LIBDIR/glib-2.0/include. +get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH) +find_path(GLIBCONFIG_INCLUDE_DIR + NAMES glibconfig.h + HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR} + ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0/include +) + +find_path(GLIB_INCLUDE_DIR + NAMES glib.h + HINTS ${PC_GLIB_INCLUDEDIR} + ${PC_GLIB_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0 +) + +set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) + +# Version detection +file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) +string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") +set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") +set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") +set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") +set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") + +# Additional Glib components. We only look for libraries, as not all of them +# have corresponding headers and all headers are installed alongside the main +# glib ones. +SET(GLIB_FIND_COMPONENTS gobject; gio; gio-unix;) +foreach (_component ${GLIB_FIND_COMPONENTS}) + if (${_component} STREQUAL "gio") + find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES) + elseif (${_component} STREQUAL "gobject") + find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES) + elseif (${_component} STREQUAL "gmodule") + find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES) + elseif (${_component} STREQUAL "gthread") + find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR}) + set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES) + elseif (${_component} STREQUAL "gio-unix") + # gio-unix is compiled as part of the gio library, but the include paths + # are separate from the shared glib ones. Since this is currently only used + # by WebKitGTK+ we don't go to extraordinary measures beyond pkg-config. + pkg_check_modules(GIO_UNIX QUIET gio-unix-2.0) + include_directories(${GIO_UNIX_INCLUDE_DIRS}) + endif () +endforeach () + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS} + VERSION_VAR GLIB_VERSION) + +mark_as_advanced( + GLIBCONFIG_INCLUDE_DIR + GLIB_GIO_LIBRARIES + GLIB_GIO_UNIX_LIBRARIES + GLIB_GMODULE_LIBRARIES + GLIB_GOBJECT_LIBRARIES + GLIB_GTHREAD_LIBRARIES + GLIB_INCLUDE_DIR + GLIB_INCLUDE_DIRS + GLIB_LIBRARIES +) diff --git a/libdnf/CMakeLists.txt b/libdnf/CMakeLists.txt index d807121..a428b2d 100644 --- a/libdnf/CMakeLists.txt +++ b/libdnf/CMakeLists.txt @@ -5,22 +5,32 @@ INCLUDE (UseSWIG) INCLUDE_DIRECTORIES (${PYTHON_INCLUDE_PATH}) INCLUDE_DIRECTORIES ("${PROJECT_BINARY_DIR}") +INCLUDE_DIRECTORIES ("swdb") +ADD_SUBDIRECTORY ("swdb") SET (LIBDNF_SOURCES repo.cpp + package.cpp + swdb/package.cpp ) SET (LIBDNF_HEADERS package.hpp repo.hpp + swdb.hpp ) - ADD_LIBRARY (libdnf SHARED ${LIBDNF_SOURCES}) SET (DNF_SO_VERSION 1) SET_TARGET_PROPERTIES (libdnf PROPERTIES OUTPUT_NAME "dnf") SET_TARGET_PROPERTIES (libdnf PROPERTIES SOVERSION ${DNF_SO_VERSION}) +TARGET_LINK_LIBRARIES(libdnf + ${GLIB_LIBRARIES} + ${GLIB_GOBJECT_LIBRARIES} + ${GLIB_GIO_LIBRARIES} + ${GLIB_GIO_UNIX_LIBRARIES}) + # SWIG_ADD_LIBRARY doesn't work on RHEL 7 (cmake 2.8.12.2), use SWIG_ADD_MODULE instead # Example: SWIG_ADD_LIBRARY (pylibdnf LANGUAGE python SOURCES pylibdnf.i) diff --git a/libdnf/package.cpp b/libdnf/package.cpp new file mode 100644 index 0000000..3a80725 --- /dev/null +++ b/libdnf/package.cpp @@ -0,0 +1,25 @@ +#include "package.hpp" + +SwdbPackage::SwdbPackage(const char *n, int e, const char *v, const char *r, const char *a) +{ + pkg = dnf_swdb_pkg_new(n, e, v, r, a); +} + +SwdbPackage::~SwdbPackage() +{ + if (pkg) { + g_object_unref(pkg); + } +} + +char * +SwdbPackage::nevra() +{ + + if (pkg) { + return dnf_swdb_pkg_nevra(pkg); + } + else { + return NULL; + } +} diff --git a/libdnf/package.hpp b/libdnf/package.hpp index fb53e7c..f43d759 100644 --- a/libdnf/package.hpp +++ b/libdnf/package.hpp @@ -1,32 +1,40 @@ #ifndef DNF_PACKAGE_HPP #define DNF_PACKAGE_HPP - +#include "swdb.hpp" #include - -class Package { - public: - Package() {}; - virtual ~Package() = default; - std::string name; +class Package +{ +public: + Package(){}; + virtual ~Package() = default; + std::string name; }; - -class RPMPackage : public Package { - public: - RPMPackage() {}; - std::string version; - std::string release; +class RPMPackage : public Package +{ +public: + RPMPackage(){}; + std::string version; + std::string release; }; - -class ModulePackage : public Package { - public: - ModulePackage() {}; - std::string stream; - long long version; +class ModulePackage : public Package +{ +public: + ModulePackage(){}; + std::string stream; + long long version; }; +class SwdbPackage : public Package +{ +public: + SwdbPackage(const char *n, int e, const char *v, const char *r, const char *a); + ~SwdbPackage(); + char *nevra(); + DnfSwdbPkg *pkg = NULL; +}; #endif diff --git a/libdnf/swdb.hpp b/libdnf/swdb.hpp new file mode 100644 index 0000000..8299388 --- /dev/null +++ b/libdnf/swdb.hpp @@ -0,0 +1,6 @@ +#ifndef SWDB_H +#define SWDB_H + +#include "swdb/package.hpp" + +#endif diff --git a/libdnf/swdb/CMakeLists.txt b/libdnf/swdb/CMakeLists.txt new file mode 100644 index 0000000..3839dfb --- /dev/null +++ b/libdnf/swdb/CMakeLists.txt @@ -0,0 +1,80 @@ +SET (DNF_GI_VERSION 42.0) + +# source files used for gir generation +SET (SWDB_SOURCES + package.cpp +) + +SET (SWDB_HEADERS + package.hpp +) + +# gir generation - GObject introspection +# taken from https://github.com/ufo-kit/libuca/blob/master/src/CMakeLists.txt +find_program(INTROSPECTION_SCANNER "g-ir-scanner") +find_program(INTROSPECTION_COMPILER "g-ir-compiler") +pkg_check_modules(GOBJECT_INTROSPECTION gobject-introspection-1.0) + +find_package(PkgConfig REQUIRED) +function(pkg_check_variable _pkg _name) + string(TOUPPER ${_pkg} _pkg_upper) + string(TOUPPER ${_name} _name_upper) + string(REPLACE "-" "_" _pkg_upper ${_pkg_upper}) + string(REPLACE "-" "_" _name_upper ${_name_upper}) + set(_output_name "${_pkg_upper}_${_name_upper}") + + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_name} ${_pkg} + OUTPUT_VARIABLE _pkg_result + OUTPUT_STRIP_TRAILING_WHITESPACE) + + set("${_output_name}" "${_pkg_result}" CACHE STRING "pkg-config variable + ${_name} of ${_pkg}") +endfunction() + +if (GOBJECT_INTROSPECTION_FOUND) + option(WITH_GIR "Build introspection files" ON) + + if (WITH_GIR) + pkg_check_variable(gobject-introspection-1.0 g_ir_scanner) + pkg_check_variable(gobject-introspection-1.0 g_ir_compiler) + + set(GIR_PREFIX "Dnf-${DNF_GI_VERSION}") + set(GIR_XML "${GIR_PREFIX}.gir") + set(GIR_TYPELIB "${GIR_PREFIX}.typelib") + + add_custom_command(OUTPUT ${GIR_XML} + COMMAND env CFLAGS=${CMAKE_C_FLAGS} ${GOBJECT_INTROSPECTION_1.0_G_IR_SCANNER} + --namespace=Dnf + --nsversion=${DNF_GI_VERSION} + --library-path=${CMAKE_CURRENT_BINARY_DIR} + --library=dnf + --no-libtool + --include=GObject-2.0 + --include=Gio-2.0 + -Idirectory ${CMAKE_CURRENT_SOURCE_DIR} + --output ${CMAKE_CURRENT_BINARY_DIR}/${GIR_XML} + --pkg=librepo + --warn-all + --quiet + ${SWDB_SOURCES} + ${SWDB_HEADERS} + DEPENDS libdnf + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + add_custom_command(OUTPUT ${GIR_TYPELIB} + COMMAND ${GOBJECT_INTROSPECTION_1.0_G_IR_COMPILER} + -o ${GIR_TYPELIB} + ${GIR_XML} + DEPENDS ${GIR_XML} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target(gir ALL + DEPENDS ${GIR_XML} ${GIR_TYPELIB}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_XML} + DESTINATION share/gir-1.0 + COMPONENT libraries) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_TYPELIB} + DESTINATION ${LIB_INSTALL_DIR}/girepository-1.0 + COMPONENT libraries) + endif() +endif() diff --git a/libdnf/swdb/package.cpp b/libdnf/swdb/package.cpp new file mode 100644 index 0000000..e677978 --- /dev/null +++ b/libdnf/swdb/package.cpp @@ -0,0 +1,53 @@ +#include "package.hpp" + +G_DEFINE_TYPE(DnfSwdbPkg, dnf_swdb_pkg, G_TYPE_OBJECT) + +static void +dnf_swdb_pkg_finalize(GObject *object) +{ + DnfSwdbPkg *pkg = (DnfSwdbPkg *)object; + g_free(pkg->name); + g_free(pkg->version); + g_free(pkg->release); + g_free(pkg->arch); + G_OBJECT_CLASS(dnf_swdb_pkg_parent_class)->finalize(object); +} + +// SWDB Package Class initialiser +static void +dnf_swdb_pkg_class_init(DnfSwdbPkgClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = dnf_swdb_pkg_finalize; +} + +// SWDB Package object initialiser +static void +dnf_swdb_pkg_init(DnfSwdbPkg *self) +{ +} + +gchar * +dnf_swdb_pkg_nevra(DnfSwdbPkg *self) +{ + return g_strdup_printf("%s-%d:%s-%s.%s", self->name, self->epoch, self->version, self->release, self->arch); +} + +/** + * dnf_swdb_pkg_new: + * + * Creates a new #DnfSwdbPkg. + * + * Returns: a #DnfSwdbPkg + **/ +DnfSwdbPkg * +dnf_swdb_pkg_new(const gchar *name, gint epoch, const gchar *version, const gchar *release, const gchar *arch) +{ + DnfSwdbPkg *swdbpkg = (DnfSwdbPkg *)g_object_new(DNF_TYPE_SWDB_PKG, NULL); + swdbpkg->name = g_strdup(name); + swdbpkg->epoch = epoch; + swdbpkg->version = g_strdup(version); + swdbpkg->release = g_strdup(release); + swdbpkg->arch = g_strdup(arch); + return swdbpkg; +} diff --git a/libdnf/swdb/package.hpp b/libdnf/swdb/package.hpp new file mode 100644 index 0000000..6e6fae6 --- /dev/null +++ b/libdnf/swdb/package.hpp @@ -0,0 +1,29 @@ +#ifndef SWDB_PKG_H +#define SWDB_PKG_H + +#include + +G_BEGIN_DECLS + +#define DNF_TYPE_SWDB_PKG dnf_swdb_pkg_get_type() +G_DECLARE_FINAL_TYPE(DnfSwdbPkg, dnf_swdb_pkg, DNF, SWDB_PKG, GObject) + +struct _DnfSwdbPkg +{ + GObject parent_instance; + gchar *name; + gint epoch; + gchar *version; + gchar *release; + gchar *arch; +}; + +DnfSwdbPkg * +dnf_swdb_pkg_new(const gchar *name, gint epoch, const gchar *version, const gchar *release, const gchar *arch); + +gchar * +dnf_swdb_pkg_nevra(DnfSwdbPkg *self); + +G_END_DECLS + +#endif diff --git a/run.sh b/run.sh index f8ddb38..af45f5a 100755 --- a/run.sh +++ b/run.sh @@ -14,6 +14,9 @@ cmake -DPYTHON_DESIRED=3 .. # compile make +# requred for typelibs +make install + # run tests export CTEST_OUTPUT_ON_FAILURE=1 make test diff --git a/tests/python/run_tests.py.in b/tests/python/run_tests.py.in index 5715860..6d50348 100755 --- a/tests/python/run_tests.py.in +++ b/tests/python/run_tests.py.in @@ -8,7 +8,7 @@ import unittest # insert built module(s) into python path sys.path.insert(0, "${CMAKE_BINARY_DIR}/libdnf") - +os.environ["GI_TYPELIB_PATH"] = "${LIB_INSTALL_DIR}/girepository-1.0" # load all tests from current dir and run them loader = unittest.TestLoader() diff --git a/tests/python/test_swdb.py b/tests/python/test_swdb.py new file mode 100644 index 0000000..45956f8 --- /dev/null +++ b/tests/python/test_swdb.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +import unittest + +import package + +import gi +gi.require_version('Dnf', '42.0') +from gi.repository import Dnf + + +class TestSwdb(unittest.TestCase): + + def test_load(self): + pkg = Dnf.SwdbPkg.new("n", 0, "v", "r", "a") + self.assertEqual(pkg.nevra(), "n-0:v-r.a") + + +class TestSwdbWrapper(unittest.TestCase): + + def test_wrapper(self): + p1 = package.SwdbPackage("n", 0, "v", "r", "a") + self.assertEqual(p1.nevra(), "n-0:v-r.a") + +if __name__ == "__main__": + unittest.main()