Linux下开源库的使用(共享库文件&头文件&配置全局搜索)(WSL)

关键词

g++; vscode; c++; pkg-config; include; lib; linux; .pc; tasks.json; launch.json; WSL

前言

需求及手动解决方法

问题

很多时候需要使用别人开源的东西 for C/C++,我们的目标是使用别人的include和链接库!这俩需求一般都包含在下载下来的文件,这里以下载好的onnxruntime-linux-x64-1.4.0.tgz为例(这是onnx在linux上的发行版)。

解压之后文件结构如下:

onnxruntime-linux-x64-1.4.0$ tree
.
├── C_API.md
├── GIT_COMMIT_ID
├── LICENSE
├── Privacy.md
├── README.md
├── ThirdPartyNotices.txt
├── VERSION_NUMBER
├── include
│   ├── cpu_provider_factory.h
│   ├── cuda_provider_factory.h
│   ├── onnxruntime_c_api.h
│   ├── onnxruntime_cxx_api.h
│   └── onnxruntime_cxx_inline.h
└── lib
    ├── libonnxruntime.so -> libonnxruntime.so.1.4.0
    └── libonnxruntime.so.1.4.0
  • 其中lib问价下存储着我们的lib文件
  • 然后include下存储着所有头文件

TIPS:C++动态库的使用、C++编译及执行过程

下面是原始的使用方法

pwd
mkdir test && cd test
touch test.cpp && vim ./test.cpp

然后输入

#include <iostream>
#include <onnxruntime_cxx_api.h>

int main() {
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");  // 测试
	return 0;
}

用vscode打开会方便一些!

在这里插入图片描述

可以看到,此时搜索不到onnxruntime for CPP

g++编译及vscode配置

设置c_cpp_properties.json中的includePath到onnxruntime的include文件夹。

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**", 
                "/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/include"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

编译的时候需要用到链接库文件,所以需要修改tasks.json来编译!

先用g++在命令行编译!

g++ test.cpp -o test -I ../include/ -L ../lib/ -lonnxruntime
./test 

# 输出
./test: error while loading shared libraries: libonnxruntime.so.1.4.0: cannot open shared object file: No such file or directory
  • 编译成功了,但是运行的时候失败,因为没有找到动态库libonnxruntime.so.1.4.0
ldd ./test
        linux-vdso.so.1 (0x00007ffff7487000)
        libonnxruntime.so.1.4.0 => not found
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9cf06c0000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9cf06a0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9cf04a0000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9cf0351000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9cf08c2000)
  • 直接复制到当前文件夹,即可!
    • 好像没起作用
  • 重新编译,编译的时候指定动态库搜索路径
g++ test.cpp -o test -I ../include/ -L ../lib/ -lonnxruntime -Wl,-rpath=../lib
./test 

# 输出成功
cola

然后设置vscode的tasks.json

原始如下:

  • 当不包含特殊库且单个文件时,这样是可以的!
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: g++ 生成活动文件",
			"command": "/usr/bin/g++",
			"args": [
				"-fdiagnostics-color=always",
				"-g",
				"${file}",
				"-o",
				"${fileDirname}/${fileBasenameNoExtension}"
			],
			"options": {
				"cwd": "${fileDirname}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"detail": "编译器: /usr/bin/g++"
		}
	]
}

修改args如下

  • 可以看到,这和命令行编译时的参数是一一对应的!
"args": [
    "-fdiagnostics-color=always",
    "-g",
    "test.cpp",
    "-I",
    "../include",
    "-L", 
    "../lib", 
    "-lonnxruntime",   
    "-o",
    "${fileDirname}/${fileBasenameNoExtension}", 
    "-Wl,-rpath=../lib", 
],

执行该任务后,可以生成和在命令行一样的输出文件!

至此,我们就明确了要是用别人的一个库,需要怎么做

需求

  • 明确我们要使用的主角仅仅是include下的头文件和lib下的库文件

  • 如果我们需要在其他很多地方使用库和头文件,则每次都需要自己写一大段命令行来用g++编译

  • 这样很不方便呀!

需求

  • 如何才能让onnx这种别人写好的库像标准库那样供我们使用呢!

明确

解决方案1:pkg-config

  • 特点:专门用于用命令行编译的时候使用!
  • 缺点:依然没有设置其能被全局include头文件和全局使用lib
    • 解决方案2可以解决!

类比

编译opencv时,需要加上pkg-config --cflags --libs opencv4,这是做啥呢!

echo `pkg-config --cflags --libs opencv4`

# 输出
-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
  • 可以看见,这其实就是将我们要在g++后面添加的参数,进行了设置!

所以,类比opencv的,我们可以自己写一个config,然后像这样使用!

原理

  • 定义一个xxx.pc文件,那么pkg-config -xxx就可以获得全部信息啦!
  • 注:pkg-config是一个命令

pkg-config的信息来自于两个地方:

  • 第一种:取系统的/usr/lib下的所有*.pc文件。
  • 第二种:PKG_CONFIG_PATH环境变量所指向的路径下的所有*.pc文件。

添加自己的.pc文件,两种方式:

  • 把你的pc文件,直接放到/usr/lib/…默认路径下。

  • 把你的pc文件的路径写到PKG_CONFIG_PATH环境变量里。

    写自己的.pc文件


参考opencv

# Package Information for pkg-config

prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4

Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.5.5
Libs: -L${exec_prefix}/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir}

写onnx的!

# Package Information for pkg-config

prefix=/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/lib
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: onnxruntime
Description: onnxruntime library made by cola in 2022年2月13日
Version: 1.4.0
Libs: -L${libdir} -lonnxruntime
Cflags: -I${includedir}

添以下到~/.bashrc,然后再执行source ~/.bashrc

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/home/cola/cola/ColaMain/ColaStore/cache/Cola_pkgconfig
export PKG_CONFIG_PATH

测试

pkg-config onnxruntime --cflags --libs

# 输出
-I/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/lib/include -L/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/lib/lib -lonnxruntime

编译运行

g++ test.cpp -o test `pkg-config onnxruntime --libs --cflags`
./test 

# 输出
./test: error while loading shared libraries: libonnxruntime.so.1.4.0: cannot open shared object file: No such file or directory
  • 编译成功,但是运行时找不到

.so文件复制到当前目录下,然后:

g++ test.cpp -o test `pkg-config onnxruntime --libs --cflags` -Wl,-rpath=./
./test 

# 输出 前提是 当前路径下有需要的.so文件
cola

附录:pkg-config的参数

pkg-config onnxruntime --cflags --libs  # 头文件信息和库信息
pkg-config --list-all  # 所有pkg-config文件

解决方案2: 像标准库一样

想法

对,标准库不就是随地使用么!同时,我也希望onnx能这样!

提前明确

todo

  • 明确附录中:链接库的搜索路径!
  • 完成方案2中对include和lib库搜索的设置!
  • vscode中tasks.json到底如何使用pkg-config

实作

参考:[库搜索路径的全局设置](#includelib的全局搜索路径 by 环境变量)

includelib的全局搜索路径 by 环境变量

注意

  1. 以下方法都是先明确对应命令所需文件的搜索文件夹路径
    • 他们都会对应一个环境变量
    • 然后我们修改环境变量
  2. 所有都是修改的./bashrc

include路径设置

  • https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html

路径搜索优先级

CPATH  # C/C++的
C_INCLUDE_PATH  # C的
CPLUS_INCLUDE_PATH  # C++的
OBJC_INCLUDE_PATH  # OBJC_INCLUDE_PATH

修改方法

将以下内容加入到~/.bashrc

TMP_PATH="/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/include"
export CPATH=$CPATH:$TMP_PATH
vim ~/.bashrc
source ~/.bashrc

lib路径配置

  • https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html

原理:设置LIBRARY_PATHLD_LIBRARY_PATH

  • 之前一直以为是LD_LIBRARY_PATH!结果一直出错!凸(艹皿艹 )
    • 区别在于前者是编译前,后者是编译后!我们需要的是编译前的搜索路径!

添加以下到~/.bashrc

TMP_PATH="/home/cola/cola/ColaMain/ColaStore/cache/onnxruntime-linux-x64-1.4.0/lib"
export LIBRARY_PATH=$LIBRARY_PATH:$TMP_PATH  # for compile
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TMP_PATH  # for run time

测试

g++命令行

g++ test.cpp -lonnxruntime -o test && ./test

# 输出
cola

编写vscode::tasks.json

附录

Linux环境下的include路径

查看当前C/C++中include的文件夹

  • https://stackoverflow.com/questions/4980819/what-are-the-gcc-default-include-directories
$ cc  -xc   /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p'
/usr/lib/gcc/x86_64-linux-gnu/9/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include

$ c++ -xc++ /dev/null -E -Wp
,-v 2>&1 | sed -n 's,^ ,,p'
/usr/include/c++/9
/usr/include/x86_64-linux-gnu/c++/9
/usr/include/c++/9/backward
/usr/lib/gcc/x86_64-linux-gnu/9/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include

Linux环境下链接库路径

  • https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html

程序运行时共享库的搜索路径:

  • 环境变量LD_LIBRARY_PATH

  • 可执行程序的-rpath

    • -WL,-rpath=PathToMyLib
  • 系统搜索路径: /lib/usr/lib

程序编译时的搜索路径: LD_LIBRARY_PATH

  • https://stackoverflow.com/questions/4250624/ld-library-path-vs-library-path#:~:text=LIBRARY_PATH%20is%20used%20by%20gcc,been%20successfully%20compiled%20and%20linked.
  • 可以在编译的时候用g++ -v参数查看!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值