[CMake] Linking problem

Michael Hertling mhertling at online.de
Fri Jul 29 23:09:28 EDT 2011


On 07/27/2011 01:14 PM, Sanatan Rai wrote:
> Hi,
>    This is a newbie question. So apologies in advance if this is covered
> somewhere in the docs (I haven't been able to find a satisfactory explanation).
> 
> The issue is this:
> 
> * I have a library called (lib)atmath as per:
> 
> include_directories(${at_SOURCE_DIR})
> add_library(atfwmath RngStream.cpp RngStream.h coin.cpp coin.hpp)
> target_link_libraries(atfwmath)
> 
> Where coin.hpp:
> 
> #ifndef COIN_HPP_INCLUDED
> #define COIN_HPP_INCLUDED
> ////////////////////////////////////////////////////////////////////////////////
> #include <sstream>
> #include <fw/math/RngStream.h>
> using namespace std;
> ////////////////////////////////////////////////////////////////////////////////
> class coin
> {
> private:
>   static string name()
>   {
>     static unsigned long id(0);
>     stringstream str;
>     str << "Coin_" << (++id) << "_stream";
>     return str.str();
>   }
>   double p;
>   RngStream *rng;
>   void init();
> public:
>   coin();
>   coin(double _p);
>   ~coin();
>   bool toss();
>   void reset(double _p);
> };
> #endif
> 
> and coin.cpp:
> 
> #include <fw/math/coin.hpp>
> ////////////////////////////////////////////////////////////////////////////////
> coin::coin() : p(0.5), rng(0) { init();}
> coin::coin(double _p) : p(_p), rng(0)
> {
>   if ((p < 0) || (p > 1))
>     throw;
>   init();
> }
> coin::~coin()
> {
>   delete rng, rng = 0;
> }
> void coin::init()
> {
>   rng = new RngStream(name().c_str());
> }
> bool coin::toss()
> {
>   double u(rng->RandU01());
>   return (u >= p);
> }
> void coin::reset(double _p)
> {
>   if ((_p < 0) || (_p > 1)) throw;
>   p = _p;
> }
> 
> 
> I use these classes in another library:
> 
> add_library(atidt STATIC idt.cpp)
> target_link_libraries(atidt atmath boost_date_time boost_signals)
> 
> 
> which is then linked to the final executable:
> add_executable(bt bt.cpp)
> target_link_libraries(bt atidt atmath boost_date_time boost_program_options)
> target_link_libraries(bt "-Wl,-whole-archive -L../idt/ -latidt
> -Wl,-no-whole-archive")
> 
> When I run make:
> 
>    * libatmath compiles fine.
>    * libatidt complies fine.
>    * when compiling bt, it complains about coin::coin, coin::reset etc
> being undefined.
>      Ie it would see it is not finding them in the linked libraries.
> Even though:
> 
>      $ ar t libatmath.a
>       RngStream.cpp.o
>       coin.cpp.o
> 
> What am I missing here? It is also quite bizarre as it doesn't
> complain about the declarations in
> RngStream.h which are defined in RngStream.c.
> 
> Thanks in advance!
> 
> --Sanatan

AFAICS, the problem arises from bt's TARGET_LINK_LIBRARIES() commands:

target_link_libraries(bt atidt atmath ...)
target_link_libraries(bt "-Wl,-whole-archive -L../idt/ -latidt
-Wl,-no-whole-archive")

In this way, -latidt appears at last in the linker command line without
a chance for CMake to mention atmath afterwards, but the former depends
on the latter as can be concluded from atidt's TARGET_LINK_LIBRARIES()
command. Finally, the whole-archive switch forces the linker to include
every object file - regardless if it is referred to or not - so atidt's
references to atmath can not be resolved. What do you intend with this
second TARGET_LINK_LIBRARIES() command? To me, it does not make much
sense at the first glance. Moreover:

(1) Since you force all object files from atidt to be included in the
final executable, you might also get errors from multiple definitions
as the executable is linked against atidt once before.

(2) Don't use "using namespace std;" at the global scope in a header.

'hope that helps.

Regards,

Michael


More information about the CMake mailing list