.
├── main
│   └── main.c
└── shapes
    ├── include
    │   └── shapes.h
    └── shapes.c

4 directories, 3 files

shapes 文件夹是一个平面图形计算库,可计算矩形,圆形的面积和周长。

// include/shapes.h

#ifndef SHAPES_H
#define SHAPES_H

// 定义矩形结构体
typedef struct {
    double length;
    double width;
} Rectangle;

// 定义圆形结构体
typedef struct {
    double radius;
} Circle;

// 计算矩形的面积
double calculateRectangleArea(Rectangle rectangle);

// 计算矩形的周长
double calculateRectanglePerimeter(Rectangle rectangle);

// 计算圆形的面积
double calculateCircleArea(Circle circle);

// 计算圆形的周长
double calculateCirclePerimeter(Circle circle);

#endif
// shapes.c

#include "shapes.h"
#include <math.h>

// 计算矩形的面积
double calculateRectangleArea(Rectangle rectangle) {
    return rectangle.length * rectangle.width;
}

// 计算矩形的周长
double calculateRectanglePerimeter(Rectangle rectangle) {
    return 2 * (rectangle.length + rectangle.width);
}

// 计算圆形的面积
double calculateCircleArea(Circle circle) {
    
    return M_PI * circle.radius * circle.radius;
}

// 计算圆形的周长
double calculateCirclePerimeter(Circle circle) {
    return 2 * M_PI * circle.radius;
}

main 文件夹是一个二进制可执行库,用于测试平面图形计算库

// main.c

#include <stdio.h>
#include "shapes.h"

int main() {
    Rectangle rectangle = {5.0, 3.0};
    Circle circle = {4.0};

    printf("Rectangle Area: %lf\n", calculateRectangleArea(rectangle));
    printf("Rectangle Perimeter: %lf\n", calculateRectanglePerimeter(rectangle));

    printf("Circle Area: %lf\n", calculateCircleArea(circle));
    printf("Circle Perimeter: %lf\n", calculateCirclePerimeter(circle));

    return 0;
}

创建平面图形计算库的静态链接库 Link to heading

进入平面图形计算库根路径

cd shapes/
.
├── include
│   └── shapes.h
└── shapes.c

2 directories, 2 files

生成目标文件(shapes.o):

gcc -c -o shapes.o shapes.c -I include/
 .
 ├── include
 │   └── shapes.h
 ├── shapes.c
+└── shapes.o

 2 directories, 3 files

生成静态链接库(libshapes.a):

ar rcs libshapes.a shapes.o
 .
 ├── include
 │   └── shapes.h
+├── libshapes.a
 ├── shapes.c
 └── shapes.o

 2 directories, 4 files

创建平面图形计算库的动态链接库 Link to heading

进入平面图形计算库根路径

cd shapes/
.
├── include
│   └── shapes.h
└── shapes.c

2 directories, 2 files

生成动态链接库(libshapes.so):

gcc -shared -o libshapes.so -fPIC shapes.c -I include/
 .
 ├── include
 │   └── shapes.h
+├── libshapes.so
 └── shapes.c

 2 directories, 3 files

使用静态链接库 Link to heading

进入二进制可执行库根路径

cd main/
.
└── main.c

1 directory, 1 file

编译可执行文件并链接静态库

gcc -o main main.c -L ../shapes/ -l shapes -I ../shapes/include/
 .
+├── main
 └── main.c

 1 directory, 2 files

运行可执行文件

$ ./main 
Rectangle Area: 15.000000
Rectangle Perimeter: 16.000000
Circle Area: 50.265482
Circle Perimeter: 25.132741

查看可执行文件的动态链接库依赖关系以及它们的搜索路径

$ ldd ./main
    linux-vdso.so.1 (0x00007ffe598e8000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f3cb171b000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3cb1914000)

使用动态链接库 Link to heading

进入二进制可执行库根路径

cd main/
.
└── main.c

1 directory, 1 file

编译可执行文件并链接动态库

gcc -o main main.c -L ../shapes/ -l shapes -I ../shapes/include/
 .
+├── main
 └── main.c

 1 directory, 2 files

添加动态链接库的搜索路径

export LD_LIBRARY_PATH=../shapes/
Info

也可以在编译可执行文件的时候通过 -Wl,-rpath 参数直接指定运行库路径,这样就不需要额外添加动态链接库的搜索路径

gcc -o main main.c -I ../shapes/include/ -Wl,-rpath, ../shapes/libshapes.so

查看可执行文件的动态链接库依赖关系以及它们的搜索路径

 $ ldd ./main
     linux-vdso.so.1 (0x00007ffd778ab000)
+    ../shapes/libshapes.so (0x00007f1526be8000)
     libc.so.6 => /lib64/libc.so.6 (0x00007f15269f1000)
     /lib64/ld-linux-x86-64.so.2 (0x00007f1526bef000)

运行可执行文件

$ ./main 
Rectangle Area: 15.000000
Rectangle Perimeter: 16.000000
Circle Area: 50.265482
Circle Perimeter: 25.132741

查看可执行文件的动态链接库依赖关系以及它们的搜索路径

 $ ldd ./main
     linux-vdso.so.1 (0x00007ffc98260000)
+    libshapes.so => ../shapes/libshapes.so (0x00007f4f8efeb000)
     libc.so.6 => /lib64/libc.so.6 (0x00007f4f8edf4000)
     /lib64/ld-linux-x86-64.so.2 (0x00007f4f8eff2000)

运行可执行文件的同时打印动态链接库的搜索信息

$ LD_DEBUG=libs ./main 
    151250:     find library=libshapes.so [0]; searching
    151250:      search path=../shapes/glibc-hwcaps/x86-64-v3:../shapes/glibc-hwcaps/x86-64-v2:../shapes                (LD_LIBRARY_PATH)
    151250:       trying file=../shapes/glibc-hwcaps/x86-64-v3/libshapes.so
    151250:       trying file=../shapes/glibc-hwcaps/x86-64-v2/libshapes.so
    151250:       trying file=../shapes/libshapes.so
    151250:
    151250:     find library=libc.so.6 [0]; searching
    151250:      search path=../shapes/glibc-hwcaps/x86-64-v3:../shapes/glibc-hwcaps/x86-64-v2:../shapes                (LD_LIBRARY_PATH)
    151250:       trying file=../shapes/glibc-hwcaps/x86-64-v3/libc.so.6
    151250:       trying file=../shapes/glibc-hwcaps/x86-64-v2/libc.so.6
    151250:       trying file=../shapes/libc.so.6
    151250:      search cache=/etc/ld.so.cache
    151250:       trying file=/lib64/libc.so.6
    151250:
    151250:
    151250:     calling init: /lib64/ld-linux-x86-64.so.2
    151250:
    151250:
    151250:     calling init: /lib64/libc.so.6
    151250:
    151250:
    151250:     calling init: ../shapes/libshapes.so
    151250:
    151250:
    151250:     initialize program: ./main
    151250:
    151250:
    151250:     transferring control: ./main
    151250:
Rectangle Area: 15.000000
Rectangle Perimeter: 16.000000
Circle Area: 50.265482
Circle Perimeter: 25.132741
    151250:
    151250:     calling fini:  [0]
    151250:
    151250:
    151250:     calling fini: ../shapes/libshapes.so [0]
    151250:
    151250:
    151250:     calling fini: /lib64/libc.so.6 [0]
    151250:
    151250:
    151250:     calling fini: /lib64/ld-linux-x86-64.so.2 [0]
    151250:
Question
当同名的动态链接库和静态连接库在同一目录时,会优先链接哪个?

进入平面图形计算库根路径

cd shapes/
 .
 ├── include
 │   └── shapes.h
+├── libshapes.a
+├── libshapes.so
 ├── shapes.c
 └── shapes.o

 2 directories, 5 files

进入二进制可执行库根路径

cd main/
.
└── main.c

1 directory, 1 file

链接平面图形计算库

gcc -o main main.c -L ../shapes/ -l shapes -I ../shapes/include/
 .
+├── main
 └── main.c

 1 directory, 2 files

查看可执行文件的动态链接库依赖关系以及它们的搜索路径

 $ ldd main
     linux-vdso.so.1 (0x00007ffc24b27000)
+    libshapes.so => ../shapes/libshapes.so (0x00007f7350c14000)
     libc.so.6 => /lib64/libc.so.6 (0x00007f7350a1d000)
     /lib64/ld-linux-x86-64.so.2 (0x00007f7350c1b000)
Note
优先链接动态链接库