Search code examples
c++cmakelinkershared-librariesi2c

How to link dynamic library "-li2c" with Cmake? (undefined reference to `i2c_smbus_write_byte_data`)


As I'm rather new to Cmake usage, I don't really know how to solve this problem. In my C++ code, I use functions from the Linux i2c library, as follows:

extern "C" {
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
}
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>

bool cpi2c_writeRegister(uint8_t address, uint8_t subAddress, uint8_t data) {
    return i2c_smbus_write_byte_data(address, subAddress, data) == 0;
}

I usually compile with Cmake using CMakeLists, but now it doesn't work since it states: undefined reference to 'i2c_smbus_write_byte_data'. I tried with G++ to link dynamically:

g++ -std=c++11 -Wall -c main.cpp
g++ -std=c++11 -o Main main.o -li2c

This worked well and there are no problems. The problem is I really need to compile with CMakeLists, so do you know a way how to achieve this? Cmake does not find the package by default (since it has no .config-file) and I don't know where the functions from i2c/smbus.h are defined.

Thanks for your help!


Solution

  • Using pkg-config is generally preferred to link libraries that have a .pc file.

    But as libi2c does not seem to install a .pc file you can use target_link_libraries() directly by providing the library name. For simplicity and portability use the "Plain library name" (see the target_link_libraries documentation).

    target_link_libraries(main i2c)
    

    CMake will take care of expanding the plain library name to -li2c, i2c.lib, or whatever is suited to your build environment and operating system.