Search code examples
c++makefileg++gnustatic-linking

Build a static library for c++ which is internally dependent on third-party libraries


I want to make a library say libmyfoo.a at a location /home/my/library/libmyfoo.a

And I want to use this static library in the simplest form as below:

Lets say this is myProgram.cpp

#include "AAA.h"

int main(void) {
    int x = 2;

    myFooFunction(x);

    return(0);
}

I want to run this as g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo

Now: The AAA.h (and AAA.cc) are dependent on a third party framework/libraries, namely gstreamer, protobuf and grpc

The hierarchy at /path/to/AAA.h is

Makefile
AAA.h
AAA.cc
AAA.o
BBB(Folder)
    BBB.cc
    BBB.h
    BBB.o

The Makefile has the rule:

GOOGLEAPIS_GENS_PATH ?= $(HOME)/GOOGLE/googleapis/gens
GOOGLEAPIS_API_CCS = $(shell find $(GOOGLEAPIS_GENS_PATH)/google/api \
    -name '*.pb.cc')
GOOGLEAPIS_RPC_CCS = $(shell find $(GOOGLEAPIS_GENS_PATH)/google/rpc \
    -name '*.pb.cc')
GOOGLEAPIS_SPEECH_CCS = $(shell find \
    $(GOOGLEAPIS_GENS_PATH)/google/cloud/speech -name '*.pb.cc')
GOOGLEAPIS_LONGRUNNING_CCS = $(shell find \
    $(GOOGLEAPIS_GENS_PATH)/google/longrunning -name '*.pb.cc')
GOOGLEAPIS_CCS = $(GOOGLEAPIS_API_CCS) $(GOOGLEAPIS_RPC_CCS) \
    $(GOOGLEAPIS_LONGRUNNING_CCS) $(GOOGLEAPIS_SPEECH_CCS)


OBJS = ./BBB/BBB.o AAA.o

.PHONY: all
all: libmyfoo.a
libmyfoo.a: $(OBJS) $(GOOGLEAPIS_CCS:.cc=.o)
    ar rcs $@ $(OBJS) $(GOOGLEAPIS_CCS:.cc=.o)
    ranlib $@
    echo "build final executable......"

This builds the libmyfoo.a with alot of *.o files in it.

Problem: When I am trying to run the myProgram.cpp as shown above it throws undefined reference to alot of things. That mean it is not getting linking correctly.

Now the AAA.cc and BBB.cc are dependent on grpc, protobuf and gstreamer as I said. So I linked those in myProgram.cpp as

g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo -L/usr/lib -L/usr/lib64 -L/usr/local/lib64 -L/usr/local/lib -lgrpc++ -lgrpc -lgrpc++_reflection -lprotobuf -lpthread -lglib-2.0 -lgobject-2.0 -lgstreamer-1.0 -ldl -lboost_system -lboost_thread

And this works absolutely fine.

Can someone explain this why? And also is it possible to run myProgram.cpp the way it is mentioned earlier i.e. g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo

Regards,


Solution

  • When a static library you use depends on shared libraries, you need to explicitly link your final binary against those shared libraries. The reason for that is that a static library is just a collection of object files, packed into an "ar" archive (that's what .a files are.) No information is stored about shared library dependencies.