我們在寫代碼的時候不一定都是有自己來完成,一個工程中會大量使用一些比較優秀的動態庫、靜態庫等,我們在使用這些庫完成所有的代碼后,需要在編譯的時候將這些庫使用的頭文件添加到我們的工程上,將他的庫文件也添加到我們的工程中,接下來我們就來看一下怎么來添加。
我們在項目中很少將第三方庫與我們自己的代碼放到同一個目錄中,而是有一些約定俗成的存放方法:
如上圖,我們會將第三方庫的頭文件放到include文件夾,將第三方的靜態庫放到lib文件夾,將動態庫放到bin文件夾,(注:如果是使用開源庫盡可能使用靜態庫,因為這樣會給部署帶來極大的方便,我沒在工程中使用動態庫,因此沒有bin文件夾,在這里需要提一下的就是,因為動態庫so文件是在程序運行時加載的,因此需要聯通程序一同發布)
廢話不多說上代碼(代碼下載地址 選擇makefile-3)
- //div.h 靜態庫所用頭文件
- #ifndef __DIV_H__
- #define __DIV_H__
- #ifdef __cplusplus
- extern "C" {
- #endif
- double div(double x, double y);
- #ifdef __cplusplus
- }
- #endif
- #endif //__DIV_H__
03lib
|----lib
|----libdiv.a
|----include
|----div.h
|----main.cpp main.h
|----add.cpp add.h
|----sub.cpp sub.h
|----mul.cpp mul.h
|----Makefile
上面這是我的文件結構圖,其中libdiv.a是我引用的外部庫,div.h是該庫的頭文件,這兩個文件分別放在了lib和include文件夾,下面請看我的Makefile文件夾
- Makefile
- CROSS =
- CC = $(CROSS)gcc
- CXX = $(CROSS)g++
- DEBUG = -g -O2
- CFLAGS = $(DEBUG) -Wall -c
- RM = rm -rf
- SRCS = $(wildcard ./*.cpp)
- OBJS = $(patsubst %.cpp, %.o, $(SRCS))
- HEADER_PATH = -I./include/
- LIB_PATH = -L./lib/
- LIBS = -ldiv
- # LIBS = libdiv.a
- VERSION = 1.0.0.1
- TARGET = test.$(VERSION)
- $(TARGET) : $(OBJS)
- $(CXX) $^ -o $@ $(LIB_PATH) $(LIBS)
- $(OBJS):%.o : %.cpp
- $(CXX) $(CFLAGS) $< -o $@ $(HEADER_PATH)
- clean:
- $(RM) $(TARGET) *.o
如上圖,我添加了13、14、16、17行,其中13和14行是為了告訴源代碼第三方庫和頭文件的路徑,16行和17行意義是完全相同的,16行只是顯示的表明我用靜態庫,但是在使用的時候需要注意,LIBS = -ldiv的方式一般用於動態庫,LIBS = libdiv.a適用於靜態庫加載,而且只有當libdiv.a與Makefile在同一目錄下才可以,一般靜態庫使用將目錄寫死的方式,但是這樣的話又不方便代碼的傳播,在一點一點學寫Makefile5我們將告訴大家如何靈活的將目錄寫死。
在23行我寫的是$(CXX) $^ -o $@ $(LIB_PATH) $(LIBS),這是在最后鏈接是需要告訴編譯器我的庫放在了那個目錄,以及該庫的名字
在26行,我在后面添加了一個$(HEADER_PATH)即指定頭文件的所在目錄
- //main.cpp
- #include "add.h"
- #include "mul.h"
- #include "sub.h"
- #include <div.h>
- #include <iostream>
- using namespace std;
- int main()
- {
- cout << "add(1, 2) = " << add(1, 2) << endl;
- cout << "sub(1, 2) = " << sub(1, 2) << endl;
- cout << "mul(1, 2) = " << mul(1, 2) << endl;
- cout << "div(1, 2) = " << div(1, 3) << endl;
- return 0;
- }
看上圖,注意我在包含div.h時候選擇的<>符號