0

When the Makefile for a project I'm working on hits this line:

g++ -g build_complex.o simplex.o simplex_src.o split.o permutation_src.o permutation_parity.o tropmod.o main.o -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -L/usr/lib/sagemath/local/lib/ -ligraph -lm -o cpptest

I get the following error:

main.o: In function `main':
/home/xander/Desktop/tropicalmoduli/main.cpp:5: undefined reference to `(anonymous namespace)::ConfigSpace::ConfigSpace(int, int)'
/home/xander/Desktop/tropicalmoduli/main.cpp:9: undefined reference to `(anonymous namespace)::PermWrapper::PermWrapper(permutation*)'
/home/xander/Desktop/tropicalmoduli/main.cpp:11: undefined reference to `(anonymous namespace)::ConfigSpace::getTraceOfPerm((anonymous namespace)::PermWrapper)'
collect2: error: ld returned 1 exit status

Those are functions that are defined in the file tropmod.cpp, which was compiled to tropmod.o. When I run nm tropmod.o spits out:

                 U __cxa_atexit
                 U __dso_handle
                 U free
                 U _GLOBAL_OFFSET_TABLE_
000000000000037c t _GLOBAL__sub_I_tropmod.cpp
                 U igraph_destroy
                 U malloc
                 U _Z10split_freeP5split
                 U _Z12simplex_freeP7simplex
                 U _Z13simplex_traceP7simplexP11permutation
                 U _Z14get_1_skeletoniiPPP5split
                 U _Z16get_mid_skeletoniiiPiPP5splitP8igraph_s
0000000000000333 t _Z41__static_initialization_and_destruction_0ii
00000000000001f0 t _ZN12_GLOBAL__N_111ConfigSpace14getTraceOfPermENS_11PermWrapperE
000000000000010c t _ZN12_GLOBAL__N_111ConfigSpace7destroyEv
0000000000000000 t _ZN12_GLOBAL__N_111ConfigSpaceC2Eii
0000000000000322 t _ZN12_GLOBAL__N_111PermWrapper14getPermutationEv
0000000000000304 t _ZN12_GLOBAL__N_111PermWrapperC2EP11permutation
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
0000000000000000 b _ZStL8__ioinit

All the "undefined references" are listed here, with a "t", which should mean that they're defined in this object file. Both tropmod.o and main.o were compiled from .cpp files which include the header file tropmod.hpp, where the declarations can be found:

#include <iostream>
#include <string>
#include "build_complex.h"

#ifdef tmboost
#include <boost/python/list.hpp>
#include <boost/python/extract.hpp>
typedef boost::python::list bplist;
#endif

namespace {

    // allows a permutation to be converted from python::boost::list
    // to permutation* just once, and then reused
    class PermWrapper {
        permutation *perm;

        public:
        #ifdef tmboost 
        PermWrapper(bplist);
        #endif
        PermWrapper(permutation*);

        permutation *getPermutation();
    };

    class ConfigSpace {
        int n,d;
        int *num_cells;
        int num_facets;
        split **all_splits;
        simplex ***skels;

        public:
        ConfigSpace(int n, int d);

        void destroy();

        int getTraceOfPerm(PermWrapper perm);
    };
}

For completeness, here is main.cpp:

#include "tropmod.hpp"

int main() {

    ConfigSpace cs = ConfigSpace(2, 2);

    int p_d[4] = {1, 0, 3, 2};
    permutation *p = perm_alloc_data(4, p_d);
    PermWrapper pw = PermWrapper(p);

    printf("trace: %i\n", cs.getTraceOfPerm(pw));
}

Both cpp files were compiled with g++ -g -fPIC -c (and without the tmboost flag).

I looked at several other questions on here concerning this kind of linking error, but none of the answers I read are obviously applicable here. It seems like all the pieces are there, does anyone have an idea why the linker can't put it together?

xanderflood
  • 826
  • 2
  • 12
  • 22

1 Answers1

2

In C++, anonymous namespaces are local to their translation unit, and they cannot be referenced from other translation units.

If you read nm's documentation, it clearly states that lowercase letters specify local symbol types.

If these were global symbols, they would be marked as "T", and not "t".

Community
  • 1
  • 1
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • That was exactly it - thanks very much. I did know that 't' meant local, but I thought that local in that context referred to a shared library, rather than the individual object file. – xanderflood Oct 22 '16 at 17:39