0%

compile protobuf-cpp on ubuntu 16.04

Series

Guide

  • protobuf 2.6.1
  • protobuf 3.6.1 latest

old version

install

1
2
3
4
5
6
7
sudo apt-get install libprotobuf-dev

which protoc
/usr/bin/protoc

protoc --version
2.6.1

remove

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#remove exist `protobuf 2.6.1`

sudo apt-get remove libprotobuf-dev
```

### compile

```bash
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz

tar -xvf protobuf-cpp-3.6.1.tar.gz
cd protobuf-3.6.1
./configure --disable-shared CXXFLAGS="-fPIC"
make -j8

tips: we compile static library with --disable-shared CXXFLAGS="-fPIC". 编译动态库dll/so的时候,如果依赖static library(比如profobuf),那么static library编译的时候需要加上-fPIC,否则动态库编译出错。
对于CMake,使用cmake CMAKE_CXX_FLGAS="-fPIC" ..

otherwise, error occurs

Linking CXX shared library ../../../../bin/libcommon.so
/usr/bin/ld: /usr/local/lib/libprotobuf.a(common.o): relocation R_X86_64_32S against `.rodata' can not be used when makinga shared object; recompile with -fPIC
/usr/local/lib/libprotobuf.a: error adding symbols: Bad value

install

1
2
3
4
sudo make install
sudo ldconfig

sudo make uninstall

install path:

  • header: /usr/local/include/google/protobuf
  • lib: /usr/local/lib
  • executable: /usr/local/bin

static libs

1
2
3
ll /usr/local/lib/libproto
libprotobuf.a libprotobuf-lite.a libprotoc.a
libprotobuf.la libprotobuf-lite.la libprotoc.la

By default, make install' will install all the files in /usr/local/bin’, /usr/local/lib' etc. You can specify an installation prefix other than /usr/local’ using --prefix', for instance –prefix=$HOME’.

1
2
3
4
./configure -h

--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]

Static Linking vs DLL

Static linking is now the default for the Protocol Buffer libraries. Due to issues with Win32’s use of a separate heap for each DLL, as well as binary compatibility issues between different versions of MSVC’s STL library, it is recommended that you use static linkage only.
However, it is possible to build libprotobuf and libprotoc as DLLs if you really want. To do this, do the following:

  • Add an additional flag -Dprotobuf_BUILD_SHARED_LIBS=ON when invoking cmake
  • Follow the same steps as described in the above section.
  • When compiling your project, make sure to #define PROTOBUF_USE_DLLS.

test

1
2
3
4
5
which protoc
/usr/local/bin/protoc

protoc --version
libprotoc 3.6.1

tips install openmpi

1
sudo apt-get install -y  libiomp-dev libopenmpi-dev 

multiple protoc

1
2
3
4
whereis protoc 
protoc: /usr/bin/protoc # 2.6.0
/usr/local/bin/protoc # 3.6.1
/usr/share/man/man1/protoc.1.gz

Example

usage

1
2
3
protoc --cpp_out=. ./point_cloud.proto 
protoc --java_out=./java/ ./proto/helloworld.proto
protoc --go_out=./go/ ./proto/helloworld.proto

CMakeLists.txt

1
2
3
4
find_package(Protobuf REQUIRED)
#add_definitions( -DPROTOBUF_USE_DLLS ) # KEY STEPS
MESSAGE( [Main] " PROTOBUF_INCLUDE_DIRS = ${PROTOBUF_INCLUDE_DIRS}")
MESSAGE( [Main] " PROTOBUF_LIBRARIES = ${PROTOBUF_LIBRARIES}")

error

1
2
3
4
5
6
7
./node_perception 

[libprotobuf ERROR google/protobuf/descriptor_database.cc:58] File already exists in database: adapter_config.proto
[libprotobuf FATAL google/protobuf/descriptor.cc:1315] CHECK failed: generated_database_->Add(encoded_file_descriptor, size):
terminate called after throwing an instance of 'google::protobuf::FatalException'
what(): CHECK failed: generated_database_->Add(encoded_file_descriptor, size):
Aborted (core dumped)

reasons

The problem happens when you have multiple compiled copies of the same .pb.cc file sharing a single copy of libprotobuf.so. 

`common`模块编译了`adapter_config.pb.cc`,`node_perception`依赖于`common`,同时也要编译`adapter_config.pb.cc`。运行`node_perception`就会报错。

solutions

同一份`adapter_config.pb.cc`只编译到`node_perception`等executable,不要编译到所依赖的`common`模块。

common和node_perception使用static或者dynamic的protobuf,都会遇到同样的问题。

Reference

History

  • 20181219: created.