Undefined Compiler Errors - help can't figure out why

Status
Not open for further replies.

mjs513

Senior Member+
Hi all
In my latest project I may have bitten off more that I can chew but here it goes. I am working on trying to get UAVcan working on the Teensy, pretty sure it can be done but am having problem with undefined references during compile. An example follows:
Code:
C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_52569\sketch\teensy_example_uavcan.ino.cpp.o: In function `uavcan::GenericSubscriber<uavcan::protocol::GetDataTypeInfo_, uavcan::protocol::GetDataTypeInfo_::Request_<0>, uavcan::TransferListener>::TransferForwarder::~TransferForwarder()':

C:\Users\CyberPalin\Documents\Arduino\libraries\libuavcan_teensy/uavcan/node/generic_subscriber.hpp:133: undefined reference to `uavcan::TransferListener::~TransferListener()'

To me it seems like the compiler doesn't see the .cpp file associated with the header file which have a .hpp extension. If this is the case do the header files need to be changed to .h files? Or is there something wrong with the library structure that I put together? Is there a namespace issue? Don't know. It does seem to be a common error with undefined references so if I get the basic issue solved then the rest will follow.

I am attaching a copy of the library and the sketch. A little to big to post.

Any help will be appreciated.
Thanks
Mike
 

Attachments

  • teensy_example_uavcan.zip
    6.4 KB · Views: 76
  • libuavcan_teensy.zip
    459.9 KB · Views: 102
I just took my open WIP debug.t3.h lib to .hpp in sketch and in the lib .cpp file and it compiled fine.

It is giving error from within the .hpp file so it has it open when it can't find the ~destructor code. Maybe it doesn't have an explicit one and it wants to see it even if empty?
 
Ok. Now sure I mentioned but the library is originally designed to be compiled using cmake and platform.io. Anyway, based on your comments I went back in and took a look at source code again there it seems to use a format that I never came across before:
Code:
class UAVCAN_EXPORT GenericSubscriber : public GenericSubscriberBase
Doing a google it brought me back to the build_config.hpp file as a option:
Code:
/**
 * Declaration visibility
 * http://gcc.gnu.org/wiki/Visibility
 */
 
#ifndef UAVCAN_EXPORT
# define UAVCAN_EXPORT
#endif
Ok, never saw visibility compile option before, so here is what it is:
Put simply, it hides most of the ELF symbols which would have previously (and unnecessarily) been public. This means:
It very substantially improves load times of your DSO (Dynamic Shared Object). For example, a huge C++ template-based library which was tested (the TnFOX Boost.Python bindings library) now loads in eight seconds rather than over six minutes!
It lets the optimiser produce better code. PLT indirections (when a function call or variable access must be looked up via the Global Offset Table such as in PIC code) can be completely avoided, thus substantially avoiding pipeline stalls on modern processors and thus much faster code. Furthermore when most of the symbols are bound locally, they can be safely elided (removed) completely through the entire DSO. This gives greater latitude especially to the inliner which no longer needs to keep an entry point around "just in case".
It reduces the size of your DSO by 5-20%. ELF's exported symbol table format is quite a space hog, giving the complete mangled symbol name which with heavy template usage can average around 1000 bytes. C++ templates spew out a huge amount of symbols and a typical C++ library can easily surpass 30,000 symbols which is around 5-6Mb! Therefore if you cut out the 60-80% of unnecessary symbols, your DSO can be megabytes smaller!
Much lower chance of symbol collision. The old woe of two libraries internally using the same symbol for different things is finally behind us with this patch. Hallelujah!
Although the library quoted above is an extreme case, the new visibility support reduced the exported symbol table from > 200,000 symbols to less than 18,000. Some 21Mb was knocked off the binary size as well!

The usage would then be:
Code:
#define UAVCAN_EXPORT    __attribute__((visibility ("default")))

#ifndef UAVCAN_EXPORT
# define UAVCAN_EXPORT
#endif
but then how would I change the compiler options to take into account this statement:
Code:
In your build system (Makefile etc), you will probably wish to add the -fvisibility=hidden and -fvisibility-inlines-hidden options to the command line arguments of every GCC invocation. Remember to test your library thoroughly afterwards, including that all exceptions correctly traverse shared object boundaries.
And the million dollar question is would this even solve the problem?
 
I gave it a try by adding the additional flags but still the same error messages. Tried a few other things but out of ideas.
 
Hi Kurt.
That looks like it solved the undefined reference issue now to work through compile errors since it now seeing the .cpp files :) Such a simple solution to a issue that's been driving me nuts. Didn't even think about it.

Essentially what I did was move everything in the library folder and created a libraries.property file with the statement includes=uavcan.h. The sketch can now see the library and appears to be working for now.

I was under the assumption that I could still use the 1.0x since that same page said it was backward compatible. Guess in this case I couldn't use that structure.

Thanks
Mike
 
Looks like to the last error and its with std function:
Code:
C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_778033\sketch\teensy_example_uavcan.ino.cpp.o: In function `std::function<void (uavcan::ReceivedDataStructure<uavcan::protocol::debug::KeyValue_<0> > const&)>::operator()(uavcan::ReceivedDataStructure<uavcan::protocol::debug::KeyValue_<0> > const&) const':

c:\local programs\arduino-1.8.5-142b4\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1/functional:2266: undefined reference to `std::__throw_bad_function_call()'
 
Well you can stop wondering I added the following:
Code:
namespace std {
  void __throw_bad_alloc()
  {
    Serial.println("Unable to allocate memory");
  }

  void __throw_length_error( char const*e )
  {
    Serial.print("Length Error :");
    Serial.println(e);
  }

  void __throw_bad_function_call()
  {
    Serial.println("Bad function call!");
  }
}
and it compiles and runs. I figured I might as well leave the 2 other throws in just in case. Now for a test with a sensor in the loop :)

Thanks for all your help Kurt. Been beating my head against the wall for two or three days now working this out. Will post if it all works out :)


Thanks
Mike
 
Another strange undefined error I am getting that I think is namespace related. I am in the process of updating the clock methodology that is used in the current UAVcan library for the Teensy. It is basically going from using elapsedMillis to using PIT timers. The new Clock implementation is based on a driver for UAVcan using kinetis processors.

Here are some of the error messages (pretty much repeated a bunch of times:
Code:
C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_116602\sketch\teensy_uavcan_gnsFix_publish.ino.cpp.o: In function `uavcan_teensy::SystemClock::adjustUtc(uavcan::UtcDuration)':

C:\Users\CyberPalin\Documents\Arduino\libraries\libuavcan_teensy\src/uavcan/uavcan_teensy/clock.hpp:112: undefined reference to `uavcan_teensy::clock::adjustUtc(uavcan::UtcDuration)'

C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_116602\sketch\teensy_uavcan_gnsFix_publish.ino.cpp.o: In function `uavcan_teensy::SystemClock::getMonotonic() const':

C:\Users\CyberPalin\Documents\Arduino\libraries\libuavcan_teensy\src/uavcan/uavcan_teensy/clock.hpp:117: undefined reference to `uavcan_teensy::clock::getMonotonic()
I've a bunch of times to make sure I had all the includes correct and paths identified. The only thing I could thing of is how he does is systemclock linkage in clock.hpp:
Code:
/**
 * Adapter for uavcan::ISystemClock.
 */
class SystemClock : public uavcan::ISystemClock
                    , uavcan::Noncopyable
{
    SystemClock() {
    }

    virtual void adjustUtc(uavcan::UtcDuration adjustment) {
        clock::adjustUtc(adjustment);
    }

public:
    virtual uavcan::MonotonicTime getMonotonic() const {
        return clock::getMonotonic();
    }
    virtual uavcan::UtcTime getUtc()             const {
        return clock::getUtc();
    }

/**
 * Calls clock::init() as needed.
 * This function is thread safe.
 */
    static SystemClock& instance();
};
}

versus the way it is now:
private:
  /*
   * Instance of SystemClock
   */
  static SystemClock self;

  SystemClock() { }

  uavcan::MonotonicTime getMonotonic() const override
  {
    return clock::getMonotonic();
  }

  uavcan::UtcTime getUtc() const override
  {
    return clock::getUtc();
  }

  void adjustUtc(uavcan::UtcDuration adjustment) override
  {
    clock::adjustUtc(adjustment);
  }
};
I think I isolated the issue but just don't know how to fix it. The functions are defined in the associated clock.cpp file. However, unless I remove the namespace clock:: from adjustUTC, getMonotonic and getUTC it will always throw those errors. Just can't figure out a way around it.
If I do that I then get an error message:
Code:
C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_493326\sketch\teensy_uavcan_gnsFix_publish.ino.cpp.o: In function `initSystemClock()':

C:\Users\CYBERP~1\AppData\Local\Temp\arduino_build_493326\sketch/phoenix_can_shield.h:45: undefined reference to `uavcan_teensy::SystemClock::instance()
and the function initSystemClock() is:
// init system clock interface
ISystemClock& initSystemClock()
{   return uavcan_teensy::SystemClock::instance();  }

I am attaching two zip files, 1 with the old way and 1 with the new clock functions to be complete. Any help would be appreciated, because I am stumped on this one.
 

Attachments

  • uavcan_clock_orig.zip
    1.6 KB · Views: 67
  • uavcan_clock_new.zip
    4.4 KB · Views: 75
Status
Not open for further replies.
Back
Top