C++ 怎么把一些代码编译为共享库 以便写一些代码调用呢?
使用 CMake 来编译 C++ 代码为共享库是一个常见的做法,下面是使用 CMake 创建一个共享库的完整过程。
/my_project
CMakeLists.txt
src/
my_library.cpp
main.cpp
include/
my_library.h
#include "my_library.h"
#include <iostream>
void MyLibrary::say_hello() {
std::cout << "Hello from MyLibrary!" << std::endl;
}
#ifndef MY_LIBRARY_H
#define MY_LIBRARY_H
class MyLibrary {
public:
void say_hello();
};
#endif
#include "my_library.h"
int main() {
MyLibrary lib;
lib.say_hello();
return 0;
}
在项目根目录(/my_project
)下创建一个 CMakeLists.txt
文件,内容如下:
# 设置 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)
# 设置项目名称
project(MyProject)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 指定头文件的路径
include_directories(include)
# 定义库的源文件
add_library(mylibrary SHARED src/my_library.cpp)
# 设置可执行文件
add_executable(main src/main.cpp)
# 链接共享库到可执行文件
target_link_libraries(main mylibrary)
在项目根目录下(即 CMakeLists.txt
所在的目录)打开终端,然后执行以下命令来构建项目:
mkdir build
cd build
cmake ..
这将生成用于构建项目的 Makefile 或其他构建工具。
make
编译完成后,你会得到以下文件:
libmylibrary.so
:共享库文件(在build
目录下)。main
:生成的可执行文件。
由于共享库 libmylibrary.so
可能不在默认的库搜索路径中,你需要确保运行时能找到它。你可以使用 LD_LIBRARY_PATH
环境变量来指定共享库的路径。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./main
如果一切顺利,你应该看到如下输出:
Hello from MyLibrary!
通过 CMake 编译共享库的关键步骤是:
- 使用
add_library(mylibrary SHARED ...)
来创建共享库。 - 使用
target_link_libraries(main mylibrary)
来链接共享库到你的可执行文件。 - 通过
LD_LIBRARY_PATH
或将共享库放到标准路径下来运行程序。
CMake 会帮助你自动化这些步骤,使得构建过程更加规范和易于管理。
如果我想在另外的地方使用这个库呢?
如果你想在其他项目中使用你创建的共享库,你需要将库文件和头文件正确地引用到新项目中。以下是如何在 CMake 中链接外部库(例如你创建的 libmylibrary.so
)的步骤。
假设你有一个新的项目需要使用这个库。
/new_project
CMakeLists.txt
src/
app.cpp
并且你的共享库文件 libmylibrary.so
和头文件 my_library.h
存放在 /my_project/build
中(或者你也可以将它们安装到系统的库路径或其他位置)。
你有几个选择:
你可以将 libmylibrary.so
和 my_library.h
文件复制到新的项目中:
/new_project
CMakeLists.txt
src/
app.cpp
lib/
libmylibrary.so
include/
my_library.h
app.cpp:
#include "my_library.h"
int main() {
MyLibrary lib;
lib.say_hello();
return 0;
}
如果你不想复制文件,而是希望新项目直接引用现有项目中的库文件和头文件,你可以设置新的项目的 CMake 配置,指定共享库和头文件的路径。
如果你选择了直接复制的方式(即新项目中有 libmylibrary.so
和 my_library.h
),修改新的项目的 CMakeLists.txt
文件如下:
cmake_minimum_required(VERSION 3.10)
project(NewProject)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 指定库和头文件的路径
include_directories(${CMAKE_SOURCE_DIR}/include) # 指定头文件路径
link_directories(${CMAKE_SOURCE_DIR}/lib) # 指定库文件路径
# 定义可执行文件
add_executable(app src/app.cpp)
# 链接到共享库
target_link_libraries(app mylibrary)
如果你选择不复制文件,而是引用 libmylibrary.so
和 my_library.h
文件在其他地方,你可以这样修改 CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.10)
project(NewProject)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 指定库和头文件的路径
include_directories(/path/to/my_project/include) # 设置头文件路径
link_directories(/path/to/my_project/build) # 设置共享库文件路径
# 定义可执行文件
add_executable(app src/app.cpp)
# 链接到共享库
target_link_libraries(app mylibrary)
/path/to/my_project/include
是你共享库头文件(my_library.h
)的路径。/path/to/my_project/build
是你编译生成的共享库文件(libmylibrary.so
)的路径。
在新的项目根目录下,创建构建目录并编译项目:
mkdir build
cd build
cmake ..
make
如果共享库不在标准的库路径下,你需要设置 LD_LIBRARY_PATH
,让程序在运行时能够找到它:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/my_project/build
./app
-
如果复制了共享库和头文件:
- 在新项目的
CMakeLists.txt
中使用include_directories
和link_directories
指定头文件和共享库的位置。 - 使用
target_link_libraries
将共享库链接到可执行文件。
- 在新项目的
-
如果不复制文件,而是引用已有的共享库和头文件:
- 在新项目的
CMakeLists.txt
中指定外部路径。
- 在新项目的
在这两种情况下,target_link_libraries
会确保新项目链接到你创建的共享库,并且 LD_LIBRARY_PATH
变量在运行时确保程序能找到该共享库。
为了在两个 C++ 项目**享同一个库,并避免它们之间的冲突,你可以采取几种不同的策略,具体取决于你如何管理和使用这个共享库。下面是几种常见的做法和文件结构示例。
/shared_lib_project
CMakeLists.txt
src/
my_library.cpp
include/
my_library.h
/project_1
CMakeLists.txt
src/
main_1.cpp
/project_2
CMakeLists.txt
src/
main_2.cpp
在这个结构中,/shared_lib_project
是包含共享库的项目,/project_1
和 /project_2
是依赖该共享库的两个项目。
你可以将共享库项目作为外部依赖项引入到这两个项目中。这样,project_1
和 project_2
都能独立使用该库,而且不会有冲突。
在 shared_lib_project
中,定义共享库:
# shared_lib_project/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyLibrary)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 添加共享库
add_library(mylibrary SHARED src/my_library.cpp)
# 设置头文件路径
target_include_directories(mylibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)
在 project_1
和 project_2
的 CMakeLists.txt
中,你可以通过 ExternalProject
模块引入 shared_lib_project
,并在构建过程中自动编译和链接共享库。
# project_1/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Project1)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 通过 ExternalProject 引入共享库
include_directories(/path/to/shared_lib_project/include)
link_directories(/path/to/shared_lib_project/build)
# 定义可执行文件
add_executable(main_1 src/main_1.cpp)
# 链接共享库
target_link_libraries(main_1 mylibrary)
# project_2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Project2)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 通过 ExternalProject 引入共享库
include_directories(/path/to/shared_lib_project/include)
link_directories(/path/to/shared_lib_project/build)
# 定义可执行文件
add_executable(main_2 src/main_2.cpp)
# 链接共享库
target_link_libraries(main_2 mylibrary)
在这种方法中,两个项目都依赖于同一个共享库,且它们之间不会发生冲突。
编译时,project_1
和 project_2
会依赖于同一个共享库,并且共享库的源代码和头文件在两个项目中都可以被访问,而没有冲突。
如果你不想在每个项目中重复构建共享库,可以选择将共享库安装到系统的标准路径,或者你自己的一个库路径中,这样所有依赖该库的项目都可以通过该路径来链接共享库。
在 shared_lib_project
的 CMakeLists.txt
中,添加一个安装步骤来将共享库安装到某个路径:
# shared_lib_project/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyLibrary)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 创建共享库
add_library(mylibrary SHARED src/my_library.cpp)
# 设置头文件路径
target_include_directories(mylibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)
# 安装共享库
install(TARGETS mylibrary DESTINATION /path/to/install/lib)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION /path/to/install/include)
在 project_1
和 project_2
的 CMakeLists.txt
中,指明共享库和头文件的安装路径:
# project_1/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Project1)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 设置库和头文件安装路径
include_directories(/path/to/install/include)
link_directories(/path/to/install/lib)
# 定义可执行文件
add_executable(main_1 src/main_1.cpp)
# 链接共享库
target_link_libraries(main_1 mylibrary)
# project_2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Project2)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 设置库和头文件安装路径
include_directories(/path/to/install/include)
link_directories(/path/to/install/lib)
# 定义可执行文件
add_executable(main_2 src/main_2.cpp)
# 链接共享库
target_link_libraries(main_2 mylibrary)
-
在
shared_lib_project
中构建并安装共享库:cd /path/to/shared_lib_project mkdir build cd build cmake .. make sudo make install
-
在
project_1
和project_2
中使用cmake
编译和链接:mkdir build cd build cmake .. make
如果你不希望多个项目依赖于同一个共享库,可以考虑将共享库改为静态库(.a
)。这样,你可以将静态库直接嵌入到每个项目中,避免了共享库的路径问题,但会增加最终可执行文件的大小。
# shared_lib_project/CMakeLists.txt
add_library(mylibrary STATIC src/my_library.cpp)
然后你可以在每个项目中链接这个静态库,类似于链接共享库。
- 方法 1:通过 CMake 引入外部共享库:在多个项目**享构建过程和库,避免路径冲突。
- 方法 2:将库安装到系统路径:将共享库安装到统一的路径,多个项目可以引用该库,避免路径问题。
- 方法 3:静态库:将共享库编译为静态库,每个项目链接自己的副本,避免共享库的依赖冲突。
选择哪种方式取决于你如何管理这些库,以及是否希望在每个项目中独立管理依赖项。