C++生成、编译动静态库(包含Makefile与CMake例子)

在Linux中,我们难免会用到各种各样的库,如静态库.a文件,动态库.so文件,我们要了解,库有什么用?库里面包含什么,通俗来讲,其实库里面包含了各种函数,调用库相当于调用库里面的函数。写这篇博客的意图源自于这两天使用到了库,但却对其不熟悉,调用总显示未定义。这篇博客将从三方面对库的使用进行讨论:

  1. 首先是使用基本的g++编译器,以及ar工具生成动、静态库,并对cpp源文件进行编译;
  2. 然后是编写Makefile文件来自动生成动静态库并对源文件进行编译;
  3. 最后则是编写CMakeLists.txt文件来自动生成Makefile,再通过Makefile编译好程序。

其实,在现实的工程项目中,我们最常用到的是第三种。下面将以实际的例子来去告诉大家如何使用,一步一步来。

编写demo

这里我们在同一个目录下创建三个文件足以,function.cppfunction.h里写需要用的函数,并生成库,而main.cpp用来调用function生成的库里的函数。
main.cpp:该文件用于调用下面类的函数。

#include <iostream>
#include "function.h"
using namespace std;
int main(void)
{
	//实例化function类
    function test=function();
    //使用实例test调用function类的Sumab函数
	cout <<"  10 + 20 = " <<test.Sumab(10,20) << endl;
    return 0;
}

function.cpp:该文件编写具体的函数功能。

#include "function.h"
function::function(){};
function::~function(){};
int function::Sumab(int a, int b)
{
        int c = a + b;
        return c;
}

function.h:该文件用于定义类与函数。

#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
class function
{
public:
    function();
    int Sumab(int a, int b);
    ~function();
};
#endif //FUNCTION_H

那么,经典的三文件形式就写好了。

只使用g++和ar

直接编译

g++ main.cpp function.cpp function.h -o output_without_lib
./output_without_lib

可以看到生成了一个output_without_lib可执行文件,执行没问题。

好了,接下来咱们把function.cpp做成一个库的形式。

静态库

g++ -c function.cpp 
ar cr libfunction.a function.o 
g++ main.cpp -o output_a -static -lfunction -L.
./output_a

第一条是把function.cpp编译成function.o
第二条是把.o文件生成静态库.a文件
第三条是使用库对main.cpp进行编译,最后生成output_a可执行文件

扫描二维码关注公众号,回复: 9810349 查看本文章

动态库

 g++ -shared -fPIC -o libfunction.so function.o  
sudo cp libfunction.so /usr/lib
g++ main.cpp -L. -lfunction -o output_so
./output_so

第一条是把function.c编译成动态库
第二条是把.so文件移动到路径中,这样编译才能找到
第三条是编译main.cpp

使用Makefile

如果文件多了,我们会发现编译起来很费劲,每次都要写一大堆的命令,为了更加方便,Makefile由此诞生,使用它可以很好地管理编译命令,而且我们只需要输入make,即可编译,下面使用Makefile直接编译看看。

Makefile编译(无库)

Makefile

# Makefile
# source object target
SRC	:= $(wildcard *.cpp)
OBJS	:=	$(SRC: %.cpp=%.o)
TARGET	:= output_without_lib_makefile
# compile and lib parameter
CC		:= g++
LDFLAGS := -L.
INCLUDE := -I.
all:
	$(CC) -o $(TARGET) $(SRC)
# clean
clean:
	rm -fr *.o
	rm -fr $(TARGET)

Makefile解析:
SOURCE表示需要编译的文件,这里用了wildcard,作用就是找到所有的.cpp文件,非常暴力。
OBJS表示的是对应的.o文件,通过变量的替换操作,可得到对应的.o文件列表。
TARGET表示最后生成的可执行文件的名字。
CC,LDFLAGS,INCLUDE表示编译的参数:CC:=g++表示使用g++编译(C++)语言,LDFLAGS表示库路径,INCLUDE表示头文件路径,都是当前路径。
文件解析完了,让我们执行make语句,会生成output_without_lib_makefile文件,愉快地执行吧。
执行完之后,还可以试试make clean,看看编译的文件是否被删除。

Makefile生成静态库并编译

Makefile静态库生成
重新编写Makefile程序

# Makefile
# source object target
SRC	:= $(wildcard *.cpp)
OBJS	:=	$(SRC: %.cpp=%.o)
LIB	:= libfunction_makefile.a 
AR	:= ar
# compile and lib parameter
CC		:= g++
INCLUDE := -I.
#link
$(LIB):function.o
	$(AR) -r $@ -o $^
function.o:function.cpp
	$(CC) -c $^ -o $@
# clean
clean:
	rm -fr *.o

此时生成了一个libfunction_makefile.a文件。

Makefile静态库使用

# Makefile
TARGET := output_makefile_a
# compile and lib parameter
CC		:= g++
INCLUDE := -I.
LDFLAGS := -L.
LIBS := libfunction_makefile.a
# link
$(TARGET):main.o
	$(CC) -o $@ $^ $(LIBS)
#compile
main.o:main.cpp
	$(CC) -c $^ -o $@
# clean
clean:
	rm -fr *.o

执行make,多出了一个output_makefile_a可执行文件。

Makefile生成动态库并编译

Makefile动态库生成

# Makefile
# compile and lib parameter
CC		:= g++
INCLUDE := -I.
LIBS := libfunction_makefile.so
# link
$(LIBS): function.o
	$(CC) -shared -o $@ $^
function.o:function.cpp
	$(CC) -c $^ -o $@
# clean
clean:
	rm -fr *.o

执行make,生成libfunction_makefile.so
然后我们把它移动到/usr/lib

mv libfunction_makefile.so /usr/lib

为什么要移动到/usr/lib呢?因为该路径是链接库的标准路径,可以运行链接动态库,或者也可以指定 LD_LIBRARY_PATH。
Makefile动态库使用

# Makefile
TARGET := output_makefile_so
# compile and lib parameter
CC		:= g++
INCLUDE := -I.
LIBS    := -lfunction_makefile
# link
$(TARGET): main.o
	$(CC)  $^  -o  $(TARGET) -lfunction_makefile
main.o:main.cpp
	$(CC) -c $^ -o $@
# clean
clean:
	rm -fr *.o

再次make,得到output_makefile_so,便可以执行了。

使用Cmake

懒得写了~这里就只说一下Cmake如何使用库吧!因为在实际工程中,一般都是调用别人写好的库,也就是常说的API。
这里举例说明如何使用静态库:

我们把一些不必要的.o文件、可执行文件删除掉,再路径先放好。留如下文件:(build文件夹是用来进行编译的文件,这样编译的文件就不会和主目录混在一起啦,这个称之为外部编译)
这里默认你已经掌握linux常用的rm、mkdir、touch命令
在这里插入图片描述

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(output_cmake)
set(CMAKE_CXX_STANDARD 11)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/lib)
add_executable(output_cmake main.cpp)
TARGET_LINK_LIBRARIES(output_cmake libfunction.a)

其中,
set(CMAKE_CXX_STANDARD 11)指的是c++版本号
INCLUDE_DIRECTORIES为头文件目录,存放.h文件
LINK_DIRECTORIES为库文件目录,存放.a文件
TARGET_LINK_LIBRARIES指的是链接相关库
然后,我们移动到build下,编译运行:

mv build/
cmake ..
make 
./output_cmake 

到这里就结束了。

如果我的文章对你有帮助,欢迎关注,点赞,评论。

参考:
https://blog.csdn.net/u011964923/article/details/73297443
https://www.cnblogs.com/prettyshuang/p/5552328.html
https://www.cnblogs.com/fengliu-/p/10216723.html
https://blog.csdn.net/u013870094/article/details/84899188

发布了39 篇原创文章 · 获赞 50 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Hanghang_/article/details/104787128