Slugger Slugger - 1 month ago 8
C++ Question

Compiling and linking pimpl style class definition into a library (C++)

I have a class that I use and I tried to rewrite it so it uses the pimpl idiom as an exercise. However, I now have trouble trying to compile and link the program. I have a main folder that contains a folder called

data
in which the pimpl implementation of the class
Data
is declared. This folder again contains a folder
dataimpl
in which the class
DataImpl
is implemented. The tree is

├── data
│   ├── dataimpl
│   ├── lib


The class
Data
is given as

#ifndef INCLUDED_DATA_
#define INCLUDED_DATA_

#include "dataimpl/dataimpl.h"

class Data
{
DataImpl * pimpl; // Only internal variable

public:
Data();
bool read();
void display() const;
};

#endif


I can create an executable like this

g++-6 main.cc data/*.cc data/dataimpl/*.cc -std=c++14


and it works just fine. However, I would like to first create a library file for the
Data
class in the folder
data/lib
. To do this, in the folder
data
I use the commands

g++-6 -c *.cc
ar -rsv lib/libdata.a
ranlib lib/libdata.a


Then I compile the object file for
main.cc
as

g++-6 -c main.cc


Now I want to put the whole thing together by linking as

g++-6 -o exec main.o data/lib/libdata.a data/dataimpl/*.cc


I get the error message

main.o: In function `main':
main.cc:(.text+0x26): undefined reference to `Data::Data()'
main.cc:(.text+0x3a): undefined reference to `Data::read()'
main.cc:(.text+0x7d): undefined reference to `Data::display() const'
collect2: error: ld returned 1 exit status


I can't understand why the
Data
functions give undefined references as I add the library file to the search path while linking. It would make some sense to me if the
DataImpl
functions are not found, but I add those also the search path (the implementations are in
data/dataimpl
and have
.cc
extensions).

Answer

Your ar command

ar -rsv lib/libdata.a

should be

ar -rsv lib/libdata.a *.o

Otherwise you created an empty archive. BTW you should be familiar with the linux command 'nm' which shows symbols.