zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Makefile、多Makefile编译静态库、动态库、SRC实例总结

实例静态 总结 动态 编译 Makefile src
2023-09-11 14:14:44 时间

静态库生成及使用

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参数添加路径inc

int 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.a

SHARE=--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.so

SHARE=--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/main

SHARE=--share

#显示所有编译警告,并指示公共头文件(静态库和动态库的头文件)所在目录
CFLAG= -Wall -I../inc

#在../lib目录中链接两个外部库文件
LFLAG=-L../lib -lshow -lcalc

CC=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

 

最后得出: