SO文件通常以“.so”为后缀,广泛应用于C/C++等编程语言中
本文将深入探讨如何在Linux环境下打包SO文件,包括从编写代码到生成可执行文件并打包SO文件的完整流程,同时介绍一些高级技巧,如使用Cython将Python文件打包成SO文件
一、编写C/C++代码并生成SO文件 首先,我们从编写C/C++代码开始
假设我们有一个简单的C++项目,其中包含一个名为`mysocket`的库,以及使用该库的主程序`main`
1. 编写库代码 创建一个名为`socketLib`的目录,并在其中编写我们的库代码
例如,我们有两个文件:`XTcp.cpp`和`XTcp.h`
// XTcp.h
ifndef XTCP_H
define XTCP_H
class XTcp {
public:
voidconnect();
};
endif
// XTcp.cpp
include XTcp.h
include
Makefile for socketLib
CC = g++
CFLAGS = -fPIC -shared -std=c++11
TARGET = libmysocket.so
SRCS = XTcp.cpp
OBJS =$(SRCS:.cpp=.o)
all:$(TARGET)
$(TARGET): $(OBJS)
$(CC)$(CFLAGS) -o $@ $^
clean:
rm -f$(OBJS) $(TARGET)
执行`make`命令后,会在当前目录下生成`libmysocket.so`文件
3. 编写主程序并使用SO文件
现在,我们编写一个主程序`main`来使用这个SO文件 创建一个名为`mainApp`的目录,并在其中编写代码
// main.cpp
include
Makefile for mainApp
CC = g++
CFLAGS = -I/path/to/socketLib -L/path/to/socketLib -lmysocket
TARGET = main
SRCS = main.cpp
OBJS =$(SRCS:.cpp=.o)
all:$(TARGET)
$(TARGET): $(OBJS)
$(CC)$(CFLAGS) -o $@ $^
clean:
rm -f$(OBJS) $(TARGET)
注意,`-I`选项用于指定头文件搜索路径,`-L`选项用于指定库文件搜索路径,`-l`选项用于指定链接的库名(不需要加前缀`lib`和后缀`.so`)
执行`make`命令后,会在当前目录下生成`main`可执行文件 但是,在运行`./main`时,可能会遇到以下错误:
./main: error while loading shared libraries: libmysocket.so: cannot open shared object file: No such file or directory
这是因为系统找不到`libmysocket.so`文件 可以通过以下几种方法解决:
- 临时修改环境变量:`export LD_LIBRARY_PATH=/path/to/socketLib`
- 修改用户环境变量:将`export LD_LIBRARY_PATH=/path/to/socketLib`添加到`~/.bashrc`的末尾,然后执行`source ~/.bashrc`
- 将SO文件复制到系统默认的库路径中,如`/usr/lib`或`/usr/local/lib`,并运行`ldconfig`命令更新库缓存
二、使用Cython将Python文件打包成SO文件
除了C/C++,Cython也提供了一种将Python代码打包成SO文件的方法,从而可以在C/C++代码中调用Python函数,或者提高Python代码的执行效率
1. 安装Cython
首先,确保已安装Cython和编译工具链
pip install cython
sudo yum install python-devel gcc CentOS
sudo apt-get install python-dev gcc Ubuntu
2. 编写Python代码和setup.py
创建一个名为`hello`的目录,并在其中编写`hello.py`和`setup.py`
hello.py
def greet(name):
return hello + name
setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize(【hello.py】)
)
3. 打包成SO文件
执行以下命令来打包`hello.py`文件:
python setup.pybuild_ext --inplace
执行完该命令后,会在同级目录下生成一个`hello.cpython- 可以重命名为`hello.so`以便使用
4. 测试SO文件
编写一个测试文件`demo.py`来测试生成的SO文件
demo.py
from hello import greet
print(greet(tom))
运行`python demo.py`,输出应为`hellotom` 此时,即使删除`hello.py`文件,程序仍然可以正常运行,因为`hello`模块已经来源于SO文件
三、将可执行文件依赖的SO文件打包
在部署Linux应用程序时,有时需要将可执行文件及其依赖的所有SO文件一起打包,以便在其他机器上运行 这可以通过以下步骤实现:
1.使用`ldd`命令查看可执行文件依赖的所有SO文件
2.使用`awk`命令提取SO文件的路径
3.使用`xargs`命令将SO文件拷贝到一个目录中
4.使用`tar`命令将SO文件打包成一个压缩文件
例如:
ldd /path/to/executable | awk{print $3} | xargs -I{} cp -v {} /path/to/copy/so/files/dir/ && tar -czvf /path/to/so/files.tar.gz /path/to/copy