由Google Protocol Buffer的小例子引起的g++编译问题
問題
學習 Google Protocol Buffer 的使用和原理時,提供了一個小例子,講述了protobuf的使用方法。
假如已經有了如下文件:
其中writer.cpp如下: #include "lm.helloworld.pb.h" #include<iostream> #include<fstream> using namespace std;int main(void) { lm::helloworld msg1; msg1.set_id(101); msg1.set_str("hello"); // Write the new address book back to disk. fstream output("./log", ios::out | ios::trunc | ios::binary); if (!msg1.SerializeToOstream(&output)) { cerr << "Failed to write msg." << endl; return -1; } return 0; }
reader.cpp如下:
#include "lm.helloworld.pb.h" #include<iostream> #include<fstream> using namespace std;void ListMsg(const lm::helloworld & msg) { cout << msg.id() << endl; cout << msg.str() << endl; } int main(int argc, char* argv[]){ lm::helloworld msg1; { fstream input("./log", ios::in | ios::binary); if (!msg1.ParseFromIstream(&input)){ cerr << "Failed to parse address book." << endl; return -1; } } ListMsg(msg1); return 0;}可以看到writer.cpp與reader.cpp都用到了lm.helloworld.pb.h,它的實現文件也在該目錄下。
那么如何編譯writer同樣reader呢?
方法
解析
這里有兩個問題,一個是writer與reader都引用到了lm.helloworld.pb.h,故實際上先需要編譯lm.helloworld.pb.cc才能被前者使用。 第二個是編譯lm.helloworld.pb.cc時需要用到第三方庫protobuf。
下面我們從后往前解決。
g++鏈接用到第三方庫
有兩種方法,
一種就是直接使用-L,-I,-l等參數直接告訴g++需要鏈接到哪些,比如:
可以參考1. linux下g++ 編譯時動態庫和靜態庫的鏈接和頭文件問題
2. gcc/g++使用第三方庫時添加頭文件路徑和庫文件路徑的方法
第二種方法就是使用pkg-config 。
pkg-config 是通過庫提供的一個 .pc 文件獲得庫的各種必要信息的,包括版本信息、編譯和連接需要的參數等。這些信息可以通過 pkg-config 提供的參數單獨提取出來直接供編譯器和連接器使用。
在默認情況下,每個支持 pkg-config 的庫對應的 .pc 文件在安裝后都位于安裝目錄中的 lib/pkgconfig 目錄下。例如,我們安裝一個叫Glib 的庫,且將其安裝在 /opt/gtk 目錄下了,那么這個 Glib 庫對應的 .pc 文件是 /opt/gtk/lib/pkgconfig 目錄下一個叫 glib-2.0.pc 的文件:
使用 pkg-config 的 –cflags 參數可以給出在編譯時所需要的選項,而 –libs 參數可以給出連接時的選項。例如,假設一個 sample.c 的程序用到了 Glib 庫,就可以這樣編譯,得到sample.o:
$ gcc -c `pkg-config --cflags glib-2.0` sample.c然后這樣連接:
$ gcc sample.o -o sample `pkg-config --libs glib-2.0`或者上面兩步也可以合并為以下一步:
$ gcc sample.c -o sample `pkg-config --cflags --libs glib-2.0`從上面的pkgconfig 可以看到cflags, libs 分別指頭文件與庫的路徑。
可以看到:由于使用了 pkg-config 工具來獲得庫的選項,所以不論庫安裝在什么目錄下,都可以使用相同的編譯和連接命令,帶來了編譯和連接界面的統一。
使用 pkg-config 工具提取庫的編譯和連接參數有兩個基本的前提:
后者可以在~/.bashrc中設置:
g++鏈接用到另外一個源文件
可以使用兩種方法,一種就是先編譯lm.helloworld.pb.cc,再編譯writer,reader,即:
$ g++ -c lm.helloworld.pb.cc $ g++ -c writer.cpp $ g++ writer.o lm.helloworld.pb.o -o writer `pkg-config --cflags --libs protobuf` $ ./writer或者
$ g++ -c lm.helloworld.pb.cc `pkg-config --cflags protobuf` $ g++ -c reader.cpp $ g++ reader.o lm.helloworld.pb.o -o reader `pkg-config --libs protobuf` $ ./reader 101 hello第二種方法就是:
$ g++ -o reader reader.cpp lm.helloworld.pb.cc `pkg-config --cflags --libs protobuf` $ ./reader 101 hello可以參考“undefined reference to” 問題解決方法
參考文獻
總結
以上是生活随笔為你收集整理的由Google Protocol Buffer的小例子引起的g++编译问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C语言进阶深度学习记录】三十五 程序
- 下一篇: R-CNN detection 运行问题