DEV Community

Cover image for Conan by example for C
Amin Khozaei
Amin Khozaei

Posted on

Conan by example for C

As a C developer, you know that many tools exist for managing projects. Every C projects use a subset of these tools, so if you want to use a C library in your project, you should understand how these tools work. If you choose CMake as the build generator of your project, and you want to use a library that uses different build tools like Autotools, you should know how to use Autotools in your CMake file. Conan supports multiple build generators and makes suitable configs based on desired build generator. So, you could select each library that exists in Conan repositories.
Conan can do more things like:
It is fully decentralized. Users can host their packages on their servers, privately. Integrates with Artifactory and Bintray.
Portable. Works across all platforms, including Linux, OSX, Windows, Solaris, FreeBSD, embedded and cross-compiling, docker, WSL
Manage binaries. It can create, upload and download binaries for any configuration and platform, even cross-compiling, saving lots of time in development and continuous integration. The binary compatibility can be configured and customized. Manage all your artifacts in the same way on all platforms.
Integrates with any build system, including any proprietary and custom one. Provides tested support for major build systems (CMake, MSBuild, Makefiles, Meson, etc).
Extensible: Its Python-based recipes, together with extension points allow for great power and flexibility.
Stable. Used in production by many companies, since 1.0 there is a commitment not to break package recipes and documented behavior.
Read more on its homepage or GitHub.

How to install Conan

Python 3.6 or newer is required to install Conan tool. The following commands should run to install it.

pip install conan
conan profile detect
Enter fullscreen mode Exit fullscreen mode

‍‍
If you have installed toolchains, the output of recent command is like:

gcc>=5, using the major as version
gcc C++ standard library: libstdc++11
Detected profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux

WARN: This profile is a guess of your environment, please check it.
WARN: The output of this command is not guaranteed to be stable and can change in future Conan versions.
WARN: Use your own profile files for stability.
Saving detected profile to /home/amin/.conan2/profiles/default
Enter fullscreen mode Exit fullscreen mode

Conan supports http and https proxies. If you want to config proxy, the following variables in GNU/Linux should be set.

export HTTP_PROXY="http://ip:port"
export HTTPS_PROXY="http://ip:port"
Enter fullscreen mode Exit fullscreen mode

Using Conan

Libraries in the main repository could be accessed by conan.io or by conan search <libname>. After finding the suitable version of each library, the Conan config file should be configured. Conan supports two different config styles, conanfile.py which uses Python to config Conan tool, and conanfile.txt which has ini style.

An example is a cli software that gets some options and makes a decision on each option.

[requires]
glib/2.73.0

[generators]
CMakeDeps
CMakeToolchain

[options]
glib*:shared=False
Enter fullscreen mode Exit fullscreen mode

The conanfile.txt has multiple sections, requires section used to define imported libraries with specific version, generator section used to define your project's generator like CMake, and options section used to config each imported library, for example, glib*:shared=False used to compile glib statically. Now it's time to create CMakefile.txt. Here is the content of CMakefile.txt.

cmake_minimum_required(VERSION 3.22.6)
project(net_alert C)

find_package(glib REQUIRED)

include_directories(include)

add_executable(${PROJECT_NAME} src/main.c )

target_link_libraries(${PROJECT_NAME} glib::glib-2.0)
target_link_libraries(${PROJECT_NAME} glib::gio-2.0)
Enter fullscreen mode Exit fullscreen mode

Conan makes cmake presets for each library, so find_package can find the library. target_link_libraries should be used to link with our example. Here is the example code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
static struct config_s {
    gint server_port;
    GString server_ip;
    gboolean server_mode;
    GString wav;
    GString command;
}config;

GString *gbuffer;

static GOptionEntry entries[] =
{
  { "port", 'p', 0, G_OPTION_ARG_INT, &config.server_port, "Server_port", NULL },
  { "destination", 'd', 0, G_OPTION_ARG_STRING, &config.server_ip, "Server ip address", NULL },
  { "server", 's', 0, G_OPTION_ARG_NONE, &config.server_mode, "Server mode", NULL },
  { "wav", 'w', 0, G_OPTION_ARG_STRING, &config.wav, "WAV alert file", NULL },
  { "command", 'c', 0, G_OPTION_ARG_STRING, &config.command, "Command to send to the server", NULL },
  { NULL }
};

int
main(int argc, char **argv) {
    GError *error;
    GOptionContext *context;

    error = NULL;
    wav = g_string_new("alert.wav");
    config.server_mode = FALSE;
    config.server_port = 2986;
    gbuffer = g_string_new(NULL);
    context = g_option_context_new ("net_alert: an application to alert on demand");
    g_option_context_add_main_entries (context, entries, NULL);
    g_option_context_add_group (context, NULL);//gtk_get_option_group (TRUE));
    if (!g_option_context_parse (context, &argc, &argv, &error)){
        g_print("option parsing failed: %s\n", error->message);
        exit(EXIT_FAILURE);
    }
    g_string_overwrite(wav, 0, config.wav.str);
    printf("port: %i\nserver address: %s\nserver mode: %i\nWav: %s\ncommand: %s\n\n"
        , config.server_port
        , (char *)config.server_ip.str
        , config.server_mode
        , wav->str
        , (char *)config.command.str);

    if (config.server_mode)
        server_mode();
    else
        client_mode();
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Conan sets include paths for imported libraries, so header files could be included directly. For a complete version of the example follow the GitHub repo.

Build the example

First of all, Canon must build imported libraries. Then created script conanbuild.sh should be sourced by bash shell. After that, CMake can generate build of our example. The following commands needs to build the project.

conan install . --output-folder=build --build=missing
cd build
source conanbuild.sh
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
Enter fullscreen mode Exit fullscreen mode

Conclusion

Conan makes C developers happy but, not all libraries are available in main repository of Conan. So, C developers should make their self repository or use libraries with an understanding of more than one build tools.

Top comments (0)