makefile 设置动态库路径参数

一、makefile 动态库相关

1.1 Libs 变量

在 Makefile 中,Libs 通常是一个变量,用于存储链接器(linker)在生成可执行文件或库文件时需要使用的库文件列表及其相关选项。这些库文件可能包括静态库(.a 文件)和动态库(.so 文件,在 Unix-like 系统上)。
Libs 变量的具体用途和定义方式可能会因项目而异,但一般来说,它包含了以下几个方面的信息:
1、库文件路径:如果库文件不在标准的库搜索路径中(如 /usr/lib 或 /usr/local/lib),则需要使用 -L 选项来指定库文件的路径。这个路径会被添加到链接器的搜索路径列表中。
2、库文件名称:使用 -l 选项来指定链接器需要链接的库文件。链接器会在这个选项指定的名称前加上 lib 前缀和适当的文件扩展名(如 .so 或 .a),然后在库搜索路径中查找这个文件。
3、其他链接选项:有时,链接器需要一些额外的选项来正确地链接库文件,比如指定特定的链接器脚本或处理特定的库依赖关系。
在 Makefile 中定义 Libs 变量的一个示例如下:
库文件名称:使用 -l 选项来指定链接器需要链接的库文件。链接器会在这个选项指定的名称前加上 lib 前缀和适当的文件扩展名(如 .so 或 .a),然后在库搜索路径中查找这个文件。
其他链接选项:有时,链接器需要一些额外的选项来正确地链接库文件,比如指定特定的链接器脚本或处理特定的库依赖关系。

# 定义库文件路径和名称
Libs = -L/path/to/libs -lmylibrary -anotherlibrary

# ... 其他 Makefile 内容 ...

# 链接目标文件和库文件生成可执行文件
myexecutable: myobjectfile.o
    $(CC) $(LDFLAGS) myobjectfile.o $(Libs) -o myexecutable

在这个例子中,Libs 变量包含了 -L/path/to/libs(指定库文件路径)和 -lmylibrary -anotherlibrary(指定库文件名称)。在链接目标文件 myobjectfile.o 生成可执行文件 myexecutable 时,这些选项会被传递给链接器。
需要注意的是,Libs 变量的名称并不是 Makefile 的标准部分,它的命名和使用完全取决于项目或开发者的约定。有些项目可能会使用不同的变量名(如 LDLIBS)来存储链接器选项。因此,在查看或编写 Makefile 时,最好先了解项目的约定和命名习惯。

1.2 LDFLAGS 变量

Makefile 中,也可以使用 LDFLAGS 变量,该变量 包含了 -L/path/to/lib 和 -lmylib,前者指定库路径,后者指定库名。

# Compiler and flags
CC = gcc
CFLAGS = -Wall -g
LDFLAGS = -L/path/to/lib -lmylib

# Source and object files
SRC = main.c
OBJ = $(SRC:.c=.o)

# Executable name
EXEC = myprogram

# Default target
all: $(EXEC)

# Rule to make the executable
$(EXEC): $(OBJ)
	$(CC) $(OBJ) -o $(EXEC) $(LDFLAGS)

# Rule to make the object file
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# Clean up
clean:
	rm -f $(OBJ) $(EXEC)

1.3 二者的作用和区别

在 Makefile 中,Libs 和 LDFLAGS 都是用于控制链接过程的变量,但它们的作用和用法有所不同。
Libs 的作用
Libs 通常用于指定链接器需要链接的库文件列表。这些库文件可能包括静态库(.a 文件)和动态库(.so 文件)。Libs 变量的值通常包含 -l 选项,用于指定库文件的名称(不包括 lib 前缀和文件扩展名)。此外,如果库文件不在标准的库搜索路径中,还需要使用 -L 选项来指定库文件的路径,但这个路径通常不会直接放在 Libs 变量中,而是放在 LDFLAGS 变量中(尽管这不是强制的,具体取决于项目的约定)。

LDFLAGS 的作用
LDFLAGS 用于指定链接器选项,这些选项会影响链接过程的行为。LDFLAGS 可以包含多种类型的选项,包括但不限于:

  • -L 选项:指定库文件的搜索路径。
  • -l 选项:虽然通常放在 Libs 变量中,但有时也可以放在 LDFLAGS 中(这取决于项目的约定)。
  • -Wl, 选项:将后续的选项传递给链接器。例如,-Wl,-rpath,/path/to/lib 会将 /path/to/lib 添加到可执行文件的运行时库搜索路径中。
  • 其他链接器特定的选项:这些选项可能因链接器的不同而有所不同,用于控制链接过程的各个方面。
    区别
    1、用途不同:Libs 主要用于指定需要链接的库文件,而 LDFLAGS 用于指定链接器的选项,这些选项可能包括库文件的搜索路径、运行时库搜索路径、以及其他链接器特定的行为。
    2、内容不同:Libs 通常只包含 -l 选项(和可能的 -L 选项,但这不是标准做法),而 LDFLAGS 可以包含多种类型的链接器选项。
    3、灵活性不同:由于 LDFLAGS 可以包含多种类型的选项,因此它比 Libs 更加灵活和强大。通过 LDFLAGS,可以控制链接过程的许多方面,而 Libs 则主要关注于库文件的链接。

在编写 Makefile 时,通常会将库文件的名称放在 Libs 变量中,而将库文件的搜索路径和其他链接器选项放在 LDFLAGS 变量中。然而,这并不是绝对的,具体取决于项目的约定和链接器的要求。在某些情况下,可能会看到 -L 选项被放在 Libs 变量中,或者 -l 选项被放在 LDFLAGS 中,这取决于项目的具体实现和链接器的行为。因此,在查看或编写 Makefile 时,最好先了解项目的约定和链接器的要求。

二、设置方式

2.1 编译时指定库路径

在编译时,需要使用 -L 选项来指定库的搜索路径,使用 -l 选项来指定库名(不包括前缀 lib 和文件扩展名 .so 或 .a)。

# Compiler and flags
CC = gcc
CFLAGS = -Wall -g
LDFLAGS = -L/path/to/lib -lmylib

# Source and object files
SRC = main.c
OBJ = $(SRC:.c=.o)

# Executable name
EXEC = myprogram

# Default target
all: $(EXEC)

# Rule to make the executable
$(EXEC): $(OBJ)
	$(CC) $(OBJ) -o $(EXEC) $(LDFLAGS)

# Rule to make the object file
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# Clean up
clean:
	rm -f $(OBJ) $(EXEC)

在这个 Makefile 中,LDFLAGS 变量包含了 -L/path/to/lib 和 -lmylib,前者指定库路径,后者指定库名。

2.2 运行时指定库路径

在运行时,系统需要知道在哪里找到这些动态库。这可以通过设置 LD_LIBRARY_PATH 环境变量来实现。
命令行手动设置

export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH
./myprogram

也可以在 Makefile 中添加一个目标来设置这个环境变量并运行的程序:

# Run the executable with LD_LIBRARY_PATH set
run: $(EXEC)
	LD_LIBRARY_PATH=/path/to/lib:$$LD_LIBRARY_PATH ./$(EXEC)

可以通过运行 make run 来编译并运行程序,同时确保 LD_LIBRARY_PATH 已正确设置。

三、测试

以snap7 动态库为例,将 动态库 放置在 /home/user/Desktop/snap7 文件下。
工程结构如下:
在这里插入图片描述
makefile 文件如下:

##
## LINUX barebone makefile for c examples : good for all platforms
##
## Simply run make or make clean
##
## Intend this makefile only as a "batch examples updater" after library modification.
##
LDFLAGS  := -L/home/user/Desktop/snap7
Libs     := -lsnap7 

CXX      := arm-linux-g++
CC       := arm-linux-gcc
#CXXFLAGS :=-O3
CFLAGS   :=

.PHONY: all clean

all: 
	$(CC) $(CFLAGS) -o client ./client.c $(LDFLAGS) $(Libs) 

clean:
	$(RM) client

指令 make
在这里插入图片描述
可看到动态库被正确链接编译。生成可执行文件 clinet。
在这里插入图片描述
刚开始编译时遇到问题,提示:

/usr/bin/ld: skipping incompatible......

在这里插入图片描述
这个问题实质是链接库文件时,库文件版本与平台版本不对应的问题。
解决方法:

objdump -p libsnap7.so  

看一下该库的版本是32为还是64位的,或是ARM版还是…等等。
在这里插入图片描述
在这里插入图片描述
使用 arm-linux工具链编译即可。

参考
Linux关于 PATH / LD_LIBRARY_PATH / LIBRARY_PATH环境变量的设置和区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值