Makefile、多Makefile编译静态库、动态库、SRC实例总结
静态库生成及使用
calc.h
#ifndef __MY_LIB_H__
#define __MY_LIB_H__
int add(int a, int b);
#endif
calc.c
#include "calc.h"
#include <stdio.h>
int sum(int i, int j)
{
return (i+j);
}
编译:
gcc -c calc.c -o calc.o
ar -cr libcalc.a calc.o
gcc -o main main.c ./libcalc.a
动态库生成及使用
show.h
#ifndef __SHOW_H__
#define __SHOW_H__void show(int i, char* name);
#endif
show.c
#include "show.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>void show(int i, char* name)
{
printf("%s=%d\n", name, i);}
编译:
gcc -fPIC -Wall -c show.c -o show.o
gcc -shared -o libshow.so show.o
gcc -o main main.c ./libshow.so
主函数:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../inc/calc.h"
#include "../inc/show.h" //可替换makefile的 -I参数添加路径incint main(void)
{
int s;
int i = 1;
int j = 2;
s = sum(i,j);
printf ("%d\n", s);
show(s,"sum");
return 0;
}
注意:
因为gcc 或者g++时编译会在前者加lib、后者添加.a或者.so,所以有了另一种主函数写法
cd /etc
编辑 ld.so.conf
sudo vim ld.so.conf
加入 libshow.so 的路径 /lib
保存之后 再执行如下命令 ldconfig
gcc -o main main.c -L. ./lshow -I../inc
或者指定lib路径
gcc -o main.o -c main.c -Wall -I../inc
gcc -o ../bin/main main.o -L../lib -lshow -lcalc
Makefile模板
#-------------------------配置区域-----------------------
#DIR指的是.o文件和.c文件所在的目录
DIR=#BIN指的是最终生成的目标对象名(包括路径),它可以是可执行程序、动态链接库或静态链接库
BIN=$(DIR)/#SHARE特指链接生成动态链接库对象时的编译选项
SHARE=--share#CFLAG即compile flag,表示在编译时所加入的选项参数
#参数包括
#-Wall : 编译后显示所有警告信息
#-g : 编译时加入调试信息,以便之后可以用gdb调试
#-fPIC : 编译动态链接库时加入的选项
#-I./inc: -I选项指定从哪个目录寻找头文件,在这指定之后,在源文件中包含头文件就可以使用<>,这里./inc即为指定的目录
CFLAG=#LFLAG即library flag,表示链接生成可执行程序时所要链接的所有库的选项参数
#-L./lib : -L指示动态/静态链接库所在的目录,这里./lib即所在的目录
#-l : -l指示动态/静态链接库的名字,注意: 这里的库名字并不包括前缀(lib)和后缀(.a或.so)
#$(SHARE) : 取SHARE变量对应的动态链接库链接选项--share
LFLAG=#CC即编译链接命令gcc -o 用于编译或者链接动态库以及可执行程序
CC=gcc -o#AR即ar -cr ,ar -cr是专门链接生成静态库的命令
#-c : 即create,创建静态库
#-r : 即replace,当静态库改变时,替代原有静态库
AR=ar -cr#最终用的是哪个链接命令
#链接生成动态库和可执行程序用CC
#链接生成静态库用AR
CO=$(CC)
#-------------------------以下为通用不变区域-----------------------#SRC指的是指定目录下的所有.c文件名,OBJ指的是指定目录下的所有.o文件名
SRC=$(wildcard $(DIR)/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))#链接命令
all:$(BIN)
$(BIN):$(OBJ)
$(CO) $@ $^ $(LFLAG)#编译命令
$(DIR)/%.o:$(DIR)/%.c
$(CC) $@ -c $< $(CFLAG)
#清除无用文件
.PHONY:clean
clean:
rm $(OBJ) $(BIN)
$@ --目标文件,$^ --所有的依赖文件,$< --第一个依赖文件
.PHONY :是一个伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,另一种是提交执行makefile时的效率。
wildcard : 扩展通配符
notdir : 去除路径
patsubst :替换通配符
-I../inc :通用头文件
整个项目工程都包括什么?
一个工程目录下一般有7个目录,一个联合编译Makefile文件:
<1>、bin目录:一般存放可执行程序
<2>、etc目录:存放配置文件
<3>、lib目录 :存放所有的库文件,包括动态库和静态库
<4>、inc目录:存放所有的公共头文件,一般是动态库和静态库对应的头文件
<5>、src目录:存放项目源码文件和编译它的Makefile文件
<6>、static目录:存放静态库源文件和编译它的Makefile文件
<7>、dynamic目录:存放动态库源文件和编译它的Makefile文件
为src、static、dynamic目录下的源文件编写不同的Makefile文件
为static目录,即静态链接库源代码目录。在此目录下要生成静态链接库文件libstatic_test.a
#------------------------------配置区域----------------------------
DIR=.
#静态库名以lib为前缀,.a为后缀
BIN=../lib/libcalc.aSHARE=--share
CFLAG=
LFLAG=
CC=gcc -o
AR=ar -cr
#编译静态库用ar -cr命令
CO=$(AR)
#-------------------------以下为通用不变区域-----------------------SRC=$(wildcard $(DIR)/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))
#$(info $(OBJ))all:$(BIN)
$(BIN):$(OBJ)
$(CO) $@ $^ $(LFLAG)$(DIR)/%.o:$(DIR)/%.c
$(CC) $@ -c $< $(CFLAG).PHONY:clean
clean:
rm $(OBJ) $(BIN)
为dynamic目录,即动态链接库源代码目录,在此目录下生成动态链接库 libshow.so
#------------------------------配置区域----------------------------
DIR=.
#动态库名以lib为前缀,以.so为后缀
BIN=../lib/libshow.soSHARE=--share
#动态链接库编译时需要-fPIC选项
CFLAG=-fPIC#链接动态库需要--share选项
LFLAG=$(SHARE)CC=gcc -o
AR=ar -cr
#编译动态链接库用gcc -o命令
CO=$(CC)
#-------------------------以下为通用不变区域-----------------------SRC=$(wildcard $(DIR)/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))all:$(BIN)
$(BIN):$(OBJ)
$(CO) $@ $^ $(LFLAG)$(DIR)/%.o:$(DIR)/%.c
$(CC) $@ -c $< $(CFLAG).PHONY:clean
clean:
rm $(OBJ) $(BIN)
为src目录,即工程源代码目录。在此目录下要通过链接动态链接库libshow.so和静态库libcalc.a 来生成可执行文件main
#-------------------------配置区域-----------------------
#源码所在的目录
DIR=.#在源码所在目录下生成可执行文件main
BIN=../bin/mainSHARE=--share
#显示所有编译警告,并指示公共头文件(静态库和动态库的头文件)所在目录
CFLAG= -Wall -I../inc#在../lib目录中链接两个外部库文件
LFLAG=-L../lib -lshow -lcalcCC=gcc -o
AR=ar -cr
#使用gcc -o 链接命令
CO=$(CC)
#-------------------------以下为通用不变区域-----------------------#SRC指的是指定目录下的所有.c文件名,OBJ指的是指定目录下的所有.o文件名
SRC=$(wildcard $(DIR)/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))#链接命令
all:$(BIN)
$(BIN):$(OBJ)
$(CO) $@ $^ $(LFLAG)#编译命令
$(DIR)/%.o:$(DIR)/%.c
$(CC) $@ -c $< $(CFLAG)
#清除无用文件
.PHONY:clean
clean:
rm $(OBJ) $(BIN)
本程序tree
编写联合编译Makefile文件
.PHONY:test
test:
make -C ./dynamic
#make -C:进入指定的目录下执行make命令
make -C ./static
#将静态、动态库文件拷贝到lib目录下
#cp ./static/libstatic_test.a ./lib
#cp ./dynamic/libdynamic_test.so ./lib
make -C ./src.PHONY:install
install:
#为lib目录下的动态链接库文件在/usr/lib目录下创建软连接,这里使用的必须是绝对路径
sudo ln -s /mnt/test/lib/libshow.so /usr/lib/libshow.so
#将最后生成的可执行文件main拷贝到./bin目录下
#mv ./src/main ./bin.PHONY:clean
clean:
make clean -C ./dynamic
#make clean -C: 进入指定目录下执行make clean命令
make clean -C ./static
make clean -C ./src
最后得出: