实用指南:Linux动静态库

news/2025/10/12 14:55:36/文章来源:https://www.cnblogs.com/wzzkaifa/p/19136644

文章目录

  • 一、静态库
    • 1.1ar命令
    • 1.2形成发布库
    • 1.3使用库 ##
      • 1.3.1指定目录搜索头文件
      • 1.3.2指定目录搜索库
      • 1.3.3ldd命令
    • 1.4库的安装
    • 1.5建立软链接
  • 二、动态库
    • 2.1形成库
    • 2.2发布库
    • 2.3使用库
    • 2.4解决加载找不到动态库的方法
      • 2.4.1拷贝到系统的默认的库路径
    • 2.4.2建立软链接
      • 2.4.3库路径添加到环境变量LD_LIBRARY_PATH
      • 2.4.4/etc/d.so.conf.d建立动态库路径的配置文件
      • 2.4.5小结
    • 2.5共享库
  • 三、动态库加载
    • 3.1程序没有加载前的地址
    • 3.2程序被加载后的地址
    • 3.3动态库的地址--fPIC

一、静态库

我们设计了一套方法,给别人用
1.给源文件
2.把我们的源代码打包成库=库+.h(头文件是方法的说明书)
在这里插入图片描述
比如说main.c里面的都是库的源代码,我们想使用的话就是把这五个直接变成.o一编译就好了
静态库就是把上面的a-d.o打包起来形成一个libxxx.o,然后和main.o一链接就形成了对应的可执行程序了

1.1ar命令

ar命令就是将我们的.o打包成.a的一个命令

ar -rc 静态库 xxx.o xxxx.o

ar是gnu归档工具,rc表示(replace and create),如果存在就替换,如果不存在就创建

1.2形成发布库

lib=libmymath.a
$(lib):mymath.oar -rc $@ $^
mymath.o:mymath.cgcc -c $^
.PHONY:clean
clean:rm -rf *.o *.a lib
.PHONY:output
output:mkdir -p lib/includemkdir -p lib/mymathlibcp *.h lib/includecp *.a lib/mymathlib

我们写了一段加减乘除的代码,声明放在了mymath.h,定义放在了mymath.c
前半部分是将.o打包形成库
后半部分是将头文件和库分离

1.3使用库 ##

[wyx@hcss-ecs-000a test]$ cat main.c
#include "mymath.h"
int main()
{printf("2+3=%d\n",Add(2,3));return 0;
}
main.c:1:20: fatal error: mymath.h: No such file or directory#include "mymath.h"
^
compilation terminated.

当我们像日常的逻辑一样使用库的时候,却发现报错报的是找不到这个库
1.gcc会在默认的路径(/usr/include/)下去找
2.gcc会在当前路径下区查找

drwxrwxr-x 4 wyx wyx 4096 Sep 26 10:00 lib
-rw-rw-r-- 1 wyx wyx   79 Sep 26 10:01 main.c

但是mymath.h不在当前目录,在lib的下级目录里面,必须是得和源代码在同一级路径下

1.3.1指定目录搜索头文件

gcc main.c -I ./lib/include/

-I去指定目录下搜索头文件

/tmp/ccUimNNH.o: In function `main':
main.c:(.text+0xf): undefined reference to `Add'
collect2: error: ld returned 1 exit status

虽然还是会报错,但已经报的不是头文件找不到的错了
报的是找不到这个add方法,就是链接的时候报错,其实就是找不到方法的实现,那就是找不到静态库

1.3.2指定目录搜索库

系统只会去默认的路径下去寻找库

gcc main.c -I ./lib/include/ -L ./lib/mymathlib/ -lmymath

1.-L告诉系统我们要链接库,库在哪个地方
2.链接库我们要显性的指定库名称,为什么,因为一个目录下有很多的库,gcc不知道你要链接哪一个库
为什么头文件不需要呢,因为你已经在程序里面指明是哪个头文件,所以gcc可以去根据头文件名去目录下去寻找
3.-l指明我们要链接哪一个库
4.-l后面必须跟库真实名,库真实名要去掉前缀lib,去掉后缀.a
5.第三方库,往后使用的时候,必定是要使用gcc -l

1.3.3ldd命令

ldd命令是显示一个可执行程序或共享库(动态库)所依赖的共享库列表

wyx@hcss-ecs-000a test]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffcb9967000)libc.so.6 => /lib64/libc.so.6 (0x00007f5c588cb000)/lib64/ld-linux-x86-64.so.2 (0x00007f5c58c99000)

可是这里我们却没有看到我们上面所写的静态库
gcc对默认的库链接时是动态链接
如果系统中只提供静态链接,gcc则只能对该库进行静态链接
动静态库都提供的时候默认肯定是动态链接的,你想静态链接就带-static
如果系统中需要链接多个库,则gcc可以链接多个库

1.4库的安装

[wyx@hcss-ecs-000a test]$ sudo cp lib/include/mymath.h /usr/include/
[wyx@hcss-ecs-000a test]$ ls /usr/include/mymath.h
/usr/include/mymath.h
[wyx@hcss-ecs-000a test]$ sudo cp lib/mymathlib/libmymath.a /lib64
[wyx@hcss-ecs-000a test]$ ls /lib64/libmymath.a
/lib64/libmymath.a

我们将自己写的库或者第三方库拷贝到系统默认的搜索路径下的这种操作叫作库的安装

1.5建立软链接

   `sudo ln -s /home/wyx/lesson9_library/test/lib/include/ /usr/include/myhead`ll /usr/include/myhead`
lrwxrwxrwx 1 root root 43 Sep 26 19:11 /usr/include/myhead -> /home/wyx/lesson9_library/test/lib/include/

头文件建立软连接

   sudo ln -s /home/wyx/lesson9_library/test/lib/mymathlib/ /lib64/libmymath.a
ll /lib64/libmymath.a
lrwxrwxrwx 1 root root 45 Sep 26 19:13 /lib64/libmymath.a -> /home/wyx/lesson9_library/test/lib/mymathlib/gcc main.c -lmymath

库文件建立软链接
虽然在系统路径下建立了软链接,但是在编译的时候我们还是需要指明库的名称以便寻找到具体的库

二、动态库

动态库和静态库的前置都一样,都是要把源文件先形成.o才能执行后续的操作
fPIC:产生与位置无关码
这个我们后面会说到

2.1形成库

[wyx@hcss-ecs-000a lesson9_library]$ gcc -fPIC -c mylog.c
[wyx@hcss-ecs-000a lesson9_library]$ gcc -fPIC -c myprint.c

先把源文件变成.o文件
ar命令是专门形成静态库的,使用gcc命令形成动态库
gcc默认内置可以形成动态库
-shared形成共享库

 gcc -shared -o libmymethod.so *.o
-rwxrwxr-x 1 wyx wyx 8144 Sep 26 19:36 libmymethod.so
-rw-rw-r-- 1 wyx wyx 1880 Sep 26 09:54 libmymath.a

不带-shared是形成可执行程序,但是我们要形成库就要带-shared
动态库是带可执行权限的,静态库不带
因为静态库的链接是直接把静态库的文件拷贝到程序里面,其他东西静态库是不管的,静态库是不会加载到内存的
动态库是要和你的可执行程序产生关联,当你的可执行程序要执行的时候势必要跳转到动态库,所以你的动态库必须要被加载,只有可执行程序这样的文件才能快速被加载
可执行权限就是你的文件是否会以可执行程序的形式加载到内存
动态库不是不能执行,只是不能单独执行

2.2发布库

dt-lib=libmymethod.so
static-lib=libmymath.a
.PHONY:all
all: $(static-lib) $(dt-lib)
$(static-lib):mymath.oar -rc $@ $^
mymath.o:mymath.cgcc -c $^
$(dt-lib):myprint.o mylog.ogcc -shared -o  $@ $^
myprint.o:myprint.cgcc -fPIC -c $^
mylog.o:mylog.cgcc -fPIC -c $^
.PHONY:clean
clean:rm -rf *.o *.a mylib
.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp *.h mylib/includecp *.a mylib/libcp *.so mylib/lib

通过这样的形式我们就能完成对动静态库的一起发布了

[wyx@hcss-ecs-000a test]$ tree mylib
mylib
├── include
│   ├── mylog.h
│   ├── mymath.h
│   └── myprint.h
└── lib
├── libmymath.a
└── libmymethod.so

2.3使用库

#include "mymath.h" //静态库
//动态库
#include "myprint.h"
#include "mylog.h"
int main()
{//静态库printf("2+3=%d\n",Add(2,3));//动态库Print();Log("hello Log");return 0;
}
gcc main.c -I ./mylib/include -L ./mylib/lib -lmymethod -lmymath

动态库在编译的时候我们也要指明对应的路径要不然系统默认去系统的路径下去搜索

[wyx@hcss-ecs-000a test]$ ./a.out
./a.out: error while loading shared libraries: libmymethod.so: cannot open shared object file: No such file or directory

但是我们在运行的时候就会直接报错

[wyx@hcss-ecs-000a test]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffeea7fd000)libmymethod.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00007f996fabb000)/lib64/ld-linux-x86-64.so.2 (0x00007f996fe89000)

我们查看这个可执行程序的共享库信息时就会发现这个动态库并没有找到
但是我们不是编译的时候告诉gcc这个库在哪里了吗
但是我们只告诉了编译器,gcc确实形成了可执行
一旦形成可执行就和编译器就没关系了
动态库在哪里,你也得告诉系统–加载器
加载的时候C语言为什么能够找到你呢

libc.so.6 => /lib64/libc.so.6 (0x00007f996fabb000)

动态库加载的时候也要告诉路径,系统会在默认的路径下去搜索C语言的动态库

2.4解决加载找不到动态库的方法

2.4.1拷贝到系统的默认的库路径

sudo cp /home/wyx/lesson9_library/test/mylib/lib/libmymethod.so /lib64
[wyx@hcss-ecs-000a test]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffd5e5a6000)libmymethod.so => /lib64/libmymethod.so (0x00007fda57a89000)libc.so.6 => /lib64/libc.so.6 (0x00007fda576bb000)/lib64/ld-linux-x86-64.so.2 (0x00007fda57c8b000)

2.4.2建立软链接

 sudo ln -s /home/wyx/lesson9_library/test/mylib/lib/libmymethod.so /lib64/libmymethod.so
[wyx@hcss-ecs-000a test]$ ll /lib64/libmymethod.so
lrwxrwxrwx 1 root root 55 Sep 26 20:33 /lib64/libmymethod.so -> /home/wyx/lesson9_library/test/mylib/lib/libmymethod.so

这样我们就能够直接找到了

[wyx@hcss-ecs-000a test]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffe83ff9000)libmymethod.so => /lib64/libmymethod.so (0x00007fa5803c5000)libc.so.6 => /lib64/libc.so.6 (0x00007fa57fff7000)/lib64/ld-linux-x86-64.so.2 (0x00007fa5805c7000)

2.4.3库路径添加到环境变量LD_LIBRARY_PATH

LD_LIBRARY_PATH
这个环境变量是专门用来给用户提供搜索用户自定义库的路径的
所以将我们的动态库路径添加到这个环境变量系统就能找到了

 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wyx/lesson9_library/test/mylib/lib
[wyx@hcss-ecs-000a test]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffeadbd9000)libmymethod.so => /home/wyx/lesson9_library/test/mylib/lib/libmymethod.so (0x00007f938c936000)libc.so.6 => /lib64/libc.so.6 (0x00007f938c568000)/lib64/ld-linux-x86-64.so.2 (0x00007f938cb38000)

这也是一种办法

2.4.4/etc/d.so.conf.d建立动态库路径的配置文件

在/etc/d.so.conf.d建立动态库路径的配置文件,然后重新ldconfig即可

ls /etc/ld.so.conf.d/
bind-export-x86_64.conf  kernel-3.10.0-1160.119.1.el7.x86_64.conf  kernel-3.10.0-957.el7.x86_64.conf  mariadb-x86_64.conf

这些文件是系统维护自己的动态库时的搜索路径文件
在这个路径下建立一个这样的.conf文件保存你的路径系统自然而然就能找到了

sudo vim  lesson9_library.conf
sudo ldconfig

把你的路径放到这样的文件,还需要将配置文件重新加载一下,系统就能找到了
不需要库名字,因为你的可执行程序在编译的时候就知道你要链接哪一个库了

2.4.5小结

实际情况,我们用的库都是别人的成熟的库,都采用直接安装到系统的方式

2.5共享库

[wyx@hcss-ecs-000a test]$ rm -f ./mylib/lib/libmymath.a
[wyx@hcss-ecs-000a test]$ ./a.out

当我们把静态库删除了之后我们会发现程序还可以跑因为静态库已经拷贝到我们的程序里了

[wyx@hcss-ecs-000a test]$ gcc -o main main.c -I ./mylib/include/ -L ./mylib/lib -lmymethod
[wyx@hcss-ecs-000a test]$ gcc -o test main.c -I ./mylib/include/ -L ./mylib/lib -lmymethod

当我们建立完两个可执行文件的时候删掉对应的动态库,这两个程序都跑不了了

[wyx@hcss-ecs-000a test]$ rm ./mylib/lib/libmymethod.so
[wyx@hcss-ecs-000a test]$ ./test
./test: error while loading shared libraries: libmymethod.so: cannot open shared object file: No such file or directory
[wyx@hcss-ecs-000a test]$ ./main
./main: error while loading shared libraries: libmymethod.so: cannot open shared object file: No such file or directory

说明这一个共享库一定是会被两个不相关的程序都会使用到的
1.常见的动态库被所有的可执行程序(动态链接的),都要使用,动态库–共享库
2.动态库在进程运行的时候,是要被加载的(静态库没有)
所以,动态库在系统加载之后,会被所有进程共享

动态库把代码共享出来所有的进程共享这一个库,可以让代码只有一份,大大节省内存,这就叫作共享库

三、动态库加载

在这里插入图片描述
1.当我们的程序想要调用共享库时,共享库就需要被加载到内存,填进页表的物理地址处,映射进地址空间的共享区
2.当我们的正文代码需要调用库里面的函数时,只需要跳转到共享区,然后去执行,再返回给正文代码,此时你就能满足在你的地址空间上完成对库的访问了
3.结论:建立映射,从此以后,我们执行的任何代码,都是在我们的进程地址空间中进行执行
系统运行中,一定会存在多个动态库-os管理起来–先描述再组织–系统中,所有库的加载情况,os非常清楚

3.1程序没有加载前的地址

在这里插入图片描述
1.程序编译后之后,程序内部有地址的概念
2.代码在编译的时候,天然的就对代码和数据有编址了,不会使用函数名了,转而使用call这个地址
3.可执行程序在没有被加载到内存的时候,就已经被分为了很多段(堆栈未初始化数据等)
4.这些都是老的,实际上可执行程序在进行编译链接时形成可执行程序时,内部的编址已经变成现如今的平坦模式-我们在磁盘上看到的可执行程序它的顺序的排布问题和我们加载到内存里和地址空间里对应的规则基本上是一致的
编译器也要考虑操作系统
5.为了方便编译代码,先看main函数,还要看到其他的函数,不能边编译边给你解析,所以函数都是要先声明的
6.这上面的地址已经是虚拟地址,所以我们的可执行程序还没有加载到内存的时候,也就是在磁盘的时候,已经按虚拟地址的方式给我们加载好的,这也叫逻辑地址
7.小结:可执行程序没有加载之前,在磁盘的时候可执行程序内部采用逻辑地址的方式进行编址

3.2程序被加载后的地址

1.当我们可执行程序加载到内存的时候,每一条指令就占据了物理地址,所以每条代码就占据了两套地址,一是可执行程序内部的逻辑地址,二是物理地址
如何理解呢?
我们站在一个大的学校操场,全校师生站在一起(内存),由于内存里排列的地址是不固定的,也就是你们都站在操场随便站,此时唯一能区分你的就是学号(物理地址),回到班级以后(可执行程序),在班级里你有对应的座位号,老师上课的时候就不会喊你某某班的多少学号,而是喊你多少号,这就是在内部使用的逻辑地址。
在这里插入图片描述
2.程序加载到内存后,如何执行第一条指令呢?可执行程序在形成的时候里面包含着entry(入口地址),由于是在可执行程序内部在编译期间就已经形成的,所以入口地址也是逻辑地址,内存中是虚拟地址
3.一个进程内部包含了自己的cwd工作目录和exe(能找到自己的可执行程序),所以当我们加载这个可执行程序时就把入口地址放到CPU寄存器EIP当中
4.因为已经时虚拟地址了,所以直接就去正文段执行了,就可以通过页表映射去寻找物理地址了,可执行程序不是有必要一次性加载到内存,可以先将入口地址加载,当我们在页表要填物理地址的时候就会触发缺页中断,程序就被加载进来了,就可以填上右侧的物理地址了,因为加载之后是以页位单位的,所以就加载了一大批的指令
5.然后读取一条指令,这条指令的长度我们就知道了,我们只需要让入口地址+长度就可以取执行下一条指令了
比如我们读取call 4也就是跳转到函数,CPU内读取到的指令,内部可能有数据,可能也有地址,着也是虚拟地址
6.读取程序当中的地址,CPU内部处理的地址,到二次访问读到的全部都是虚拟地址,CPU读到的是虚拟地址,但是要真正的找到你,再怎么虚拟也是指令间进行定位,但是我们必须要读取你指令,通过页表将虚拟地址转化成物理地址,找到你的这条指令又是虚拟地址,然后重复就循环起来了
7.CPU读取到的只有虚拟地址比如0x112233,通过页表转化你才能找到物理地址,而物理地址里面存着指令,就是虚拟地址只存地址不存指令,我们找到物理地址后,读取指令的长度,虚拟地址加指令的长度就能找到下一条虚拟地址

3.3动态库的地址–fPIC

在这里插入图片描述
1.当我们可执行程序内部调用库方法比如printf,因为采用的是逻辑地址,cpu读到虚拟地址以后,就在正文代码去找到共享区去找,共享库加载进来开辟物理内存,共享库映射到共享区里面
2.关键是共享区大了,具体映射到哪里呢,这个printf是提前被编译好的,如果是固定的绝对地址,我有十个八个共享库加载进来,保不齐就能把你这个绝对地址占了,所以动态库被加载到固定地址空间中的位置是不可能的
3.库在形成的时候,让自己的内部函数不要采用绝对地址,只表示每个函数在库中的偏移量即可,所以在编译的时候,printf所采用的不是绝对地址而是偏移量
4.当我们把库加载进来,在地址空间里就可以随便放,操作系统只需要记住库的起始地址,找到这个函数只需要加函数的偏移量就可以了
5.fPIC与位置无关码–直接用偏移量对库中函数进行编址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/935448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年10月工作服厂家最新推荐排行榜,春夏秋冬季工作服,工人工作服,车间工作服,防静电工作服公司推荐!

在当前工作服市场中,企业采购时常常面临诸多难题。一方面,市场上工作服产品质量参差不齐,部分产品面料不符合行业标准,色牢度差、易磨损,难以满足不同行业的工作场景需求,比如化工行业需要的防酸碱工作服,若面料…

2023-网鼎杯web-thinkshop

这题应该在出题的时候就有提供docker环境,也就是说比赛的时候就有考ctfer搭建docker环境的能力,我看了网上大佬的wp,也侧面验证了,所以从搭建环境开始 docker load < thinkshop.tar docker导入环境 docker run -tid…

2025活性氧化镁厂家最新权威推荐榜:高纯度与稳定性能深度解

2025活性氧化镁厂家最新权威推荐榜:高纯度与稳定性能深度解在现代化工材料领域,活性氧化镁作为一种重要的无机化工原料,其应用范围已从传统的橡胶、塑料行业扩展到医药、环保等新兴领域。随着产业升级对材料性能要求…

Java的一些细节

1、Java的源文件以java格式命名,之后转为class格式(字节码文件)才可以运行; 2、Java程序开始执行的入口,是在main()方法,固定格式为 public static void main(String[] args){} 3、Java严格区分大小写; 4、Ja…

通用寄存器, 与RAM寄存器的内存关系

通用寄存器, 与RAM寄存器的内存关系通用寄存器和堆栈、data、bss段完全不在一个层级上。它们是两种截然不同的存储结构。​​ 您的理解中可能混淆了“内存地址空间”和“CPU硬件寄存器”这两个概念。让我们来详细分解…

C++20中线程类std::jthread的使用 - 详解

C++20中线程类std::jthread的使用 - 详解2025-10-12 14:39 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block…

2025年CNC高压清洗机厂家权威推荐:高效清洁与耐用性能深

2025年CNC高压清洗机厂家权威推荐:高效清洁与耐用性能深在制造业智能化转型的浪潮中,CNC高压清洗机作为工业清洁领域的关键设备,正发挥着日益重要的作用。这类设备不仅能有效清除CNC加工中心、数控机床等精密设备在…

ABC427

ABC427C. Bipartize 枚举每个点的颜色,然后统计有多少条边的端点颜色相同,这就是要删除的点,取最小值即可代码实现 #include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i)using name…

C# NUnit

Install-Package NUnit; Install-Package NUnit3TestAdapter; Install-Package Microsoft.Net.Test.Sdk; Install-Package Moq;using Moq; using NUnit.Framework; using NUnit.Framework.Legacy;namespace ConsoleApp…

从 EFI 到 GPT:深入理解现代计算机启动与磁盘分区技能

从 EFI 到 GPT:深入理解现代计算机启动与磁盘分区技能pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…

2025年扁钢厂家最新权威推荐榜:强度与精度双重保障的工业脊

2025年扁钢厂家最新权威推荐榜:强度与精度双重保障的工业脊梁在制造业转型升级的关键时期,扁钢作为工业领域的"骨架材料",其质量直接影响着装备制造、建筑工程、轨道交通等行业的健康发展。随着新材料技术…

GJB 438C学习

系列标准宣贯︱GJB 438C中规定软件文档的用途与编写时机长风破浪会有时,直挂云帆济沧海! 可通过下方链接找到博主 https://www.cnblogs.com/judes/p/10875138.html

typora markdown

markdown学习 标题: +空格+标题名字 二级标题 +名称 以此类推每级加一个# 字体 hello,world! 左右 ** hello,world! * hello,workd! *** hello,workd! …

2025防爆数粒机厂家权威推荐榜:高效精准与安全防爆口碑之选

2025防爆数粒机厂家权威推荐榜:高效精准与安全防爆口碑之选在制药、化工、食品等工业领域,颗粒物料的精准计数与分装是生产流程中的关键环节。防爆数粒机作为特种设备,不仅需要满足高效精准的计数要求,更要具备严格…

想在浏览器里跑 AI?TensorFlow.js 硬件帮助完全指南

想在浏览器里跑 AI?TensorFlow.js 硬件帮助完全指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&quo…

Linux系统设置与理解主机名(hostname)的重要性

在Linux系统中,主机名(hostname)是区分网络中一台主机或者是服务设备的一个唯一标识。操作系统在网络通讯时会使用到主机名,它允许用户和程序方便地识别和交互。除了作为识别符,主机名在系统安全性、维护管理方面也…

CSharp: image (JPG,PNG,etc) covert webp using Aspose.Imaging

protected void Page_Load(object sender, EventArgs e){if (!IsPostBack){// 激活Aspose//ActiveAspose(); ///无效HookManager.ShowHookDetails(true);HookManager.StartHook();// The path to the documents direct…

基于GPT2搭建医疗问诊机器人

基于GPT2搭建医疗问诊机器人2025-10-12 14:23 dribs 阅读(0) 评论(0) 收藏 举报1

2025耐磨轮胎厂家最新权威推荐榜:超强抓地力与持久耐用深度

2025耐磨轮胎厂家最新权威推荐榜:超强抓地力与持久耐用深度在商用车运输领域,轮胎作为车辆与路面唯一接触的部件,其耐磨性能直接关系到运营成本与行车安全。据统计,轮胎磨损占运输企业运营成本的比重不容忽视,优质…

在Vue 3项目中集成Element Plus组件库的步骤

安装Element Plus 首先,确保你的开发环境已经安装了Node.js和npm(或yarn)。然后,在你的Vue 3项目根目录下打开终端,并执行以下命令来安装Element Plus: npm install element-plus --save # 或者使用yarn yarn ad…