目录
- 一、makefile 动态库相关
- 1.1 Libs 变量
- 1.2 LDFLAGS 变量
- 1.3 二者的作用和区别
- 二、设置方式
- 2.1 编译时指定库路径
- 2.2 运行时指定库路径
- 三、测试
一、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 cleanall: $(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环境变量的设置和区别