Home > Blockchain >  how to link to a lib and create a shared .so file at the same time using g or CMake
how to link to a lib and create a shared .so file at the same time using g or CMake

Time:03-24

File structure under folder /home/cyan/proj

fst
 | -- include
 |     |-- fstlib
 |            |-- fst_row_reader.h
 |            |-- fst
 |                 |-- interface
 |                         |-- fststore.h
 |
 | -- lib
       |-- libfst.so

test.cc

CMakeLists.txt

fst folder is a library I added and used in test.cc.

test.cc

#include <iostream>
#include <fstlib/fst_row_reader.h>

class Add{
public:
    double add2num(int a, double b){
        return a   b;
    }
};

extern "C"
{
    Add* test_new(){
        return new Add;
    }
    int my_func(Add* t, int a, double b){
        return t->add2num(a, b);
    }
}

*Note: In my actual test.cc I used some functions in fst library. Here is just a sample for simplicity.

Problem

Previously, I can simply use g test.cc -fPIC -shared -o test.so to get the .so file. However, since I included the fst lib, I got the following error:

In file included from /home/cyan/proj/fst/include/fstlib/fst_row_reader.h:7:0,
                 from read_fst.cc:1:
/home/cyan/proj/fst/include/fstlib/fst_reader.h:6:10: fatal error: fstlib/fst/interface/fststore.h: No such file or directory
 #include <fstlib/fst/interface/fststore.h>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

My attempt:

$ g   -L/home/cyan/proj/fst/lib -l:libfst.so

/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text 0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
---------------------------------------------------------
$ g   read_fst.cc -L /home/cyan/proj/fst/lib/libfst.so -fPIC -shared -o test.so 

In file included from /home/cyan/proj/fst/include/fstlib/fst_row_reader.h:7:0,
                 from read_fst.cc:1:
/home/cyan/proj/fst/include/fstlib/fst_reader.h:6:10: fatal error: fstlib/fst/interface/fststore.h: No such file or directory
 #include <fstlib/fst/interface/fststore.h>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

I also tried CMakeLists.txt to link the fst library as well as create a .so file under the path /home/cyan/proj/build/lib. But I am very new to CMake. Here is my attempt:

cmake_minimum_required(VERSION 3.0.0)
project(MY_PROJ VERSION 0.1.0)
set(mylibSRCS test.cc)
message(STATUS "Build test.so")
include_directories(${CMAKE_SOURCE_DIR}/fst/include)
link_directories(${CMAKE_SOURCE_DIR}/fst/lib)
add_library(MY_PROJ SHARED ${mylibSRCS})
set_target_properties(MY_PROJ PROPERTIES
            LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
target_link_libraries(MY_PROJ ${CMAKE_SOURCE_DIR}/fst/lib/libfst.so)  # link to my fst lib
target_link_libraries(MY_PROJ)

But I can't find any files under the /home/cyan/proj/build/lib. I guess this is my CMake command issue. Could you please help me with this problem?

CodePudding user response:

The most convenient way of using a library located on the file system imho associating the info with a imported library target which allows you to just link it using target_link_libraries:

add_library(fst SHARED IMPORTED)
target_include_directories(fst INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/fst/include)
set_target_properties(fst PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/fst/lib/libfst.so)

...

target_link_libraries(MY_PROJ PRIVATE fst)

this way the info is easy to reuse and it listed in a single place instead of spreading it into different target properties of the linking target.

A bit more advanced, but even better would be to write fst-config.cmake and fst-config-version.cmake files and putting them in the "installation directory" of the library which would allow you to use find_package(fst) to execute the logic creating the imported library which makes the library simple to reuse across multiple cmake projects, but this is beyond the scope of this answer. The find_package documentation provides more info about how to do this.


Btw: Note the use of CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR. If you're specifying absolute paths inside the directory containing the CMakeLists.txt file containing the variable reference, since CMAKE_SOURCE_DIR refers to the toplevel source dir which may be different, if you're including the CMakeLists.txt using add_subdirectory.

  • Related