如何使用 g++ 或 CMake link 到一个 lib 并同时创建一个共享的 .so 文件

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

文件夹/home/cyan/proj

下的文件结构
fst
 | -- include
 |     |-- fstlib
 |            |-- fst_row_reader.h
 |            |-- fst
 |                 |-- interface
 |                         |-- fststore.h
 |
 | -- lib
       |-- libfst.so

test.cc

CMakeLists.txt

fst文件夹是我在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);
    }
}

*注意:在我实际的test.cc中,我使用了fst库中的一些函数。为了简单起见,这里只是一个示例。

问题

以前,我可以简单地使用 g++ test.cc -fPIC -shared -o test.so 来获取 .so 文件。但是,由于我包含了 fst 库,所以出现以下错误:

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.

我的尝试:

$ 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.

我还尝试 CMakeLists.txt 到 link fst 库以及在路径 /home/cyan/proj/build/lib 下创建一个 .so 文件。但我对 CMake 很陌生。这是我的尝试:

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)

但是我在/home/cyan/proj/build/lib下找不到任何文件。我想这是我的 CMake 命令问题。 你能帮我解决这个问题吗?

最方便的使用位于文件系统上的库的方法恕我直言,将信息与导入的库目标相关联,这样您就可以 link 使用 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)

这样信息就很容易重用,而且它列在一个地方而不是分散到 linking 目标的不同目标属性中。

更高级一点,但更好的方法是编写 fst-config.cmakefst-config-version.cmake 文件并将它们放在库的“安装目录”中,这样​​您就可以使用 find_package(fst) 执行创建导入库的逻辑,这使得库可以简单地跨多个 cmake 项目重用,但这超出了本答案的范围。 find_package documentation 提供了有关如何执行此操作的更多信息。


顺便说一句:注意使用 CMAKE_CURRENT_SOURCE_DIR 而不是 CMAKE_SOURCE_DIR。如果您在包含包含变量引用的 CMakeLists.txt 文件的目录中指定绝对路径,因为 CMAKE_SOURCE_DIR 指的是可能不同的顶层源目录,如果您包含 CMakeLists.txt 使用 add_subdirectory.