Undefined reference to std::to_string while linking

Hello,
I am trying to cross-compile a program for Turris OS and I am always getting an error with undefined reference to std::to_string while linking is performed. I already applied the workaround, which should help to solve this issue:

#include <string>
#include <sstream>

template <typename T>
std::string to_string(T value)
{
    std::ostringstream os ;
    os << value ;
    return os.str() ;
}

int main()
{
     std::string perfect = to_string(5) ;
}

This helped in the phase of building CXX objects, but while linking the problem is back.

Here is the error:

[ 76%] Linking CXX executable gateway
 /home/jakub/build/openwrt/staging_dir/target-arm_cortex-a9+vfpv3_uClibc- 
0.9.33.2_eabi/usr/lib/libPocoFoundation.so: warning: the use of OBSOLESCENT `utime' is discouraged, use 
`utimes'
/home/jakub/build/openwrt/staging_dir/target-arm_cortex-a9+vfpv3_uClibc- 
0.9.33.2_eabi/usr/lib/libcrypto.so.1.0.0: warning: gethostbyname is obsolescent, use getnameinfo() instead.
libGateway.a(NewDeviceCommand.cpp.o): In function `Gateway::NewDeviceCommand::toString() const':
NewDeviceCommand.cpp:(.text+0x218): undefined reference to `std::to_string(int)'
libGateway.a(DeviceManager.cpp.o): In function `Gateway::DeviceManager::lastValue(Gateway::DeviceID 
const&, Gateway::ModuleID const&, Poco::Timespan const&)':
DeviceManager.cpp:(.text+0x554): undefined reference to `std::to_string(int)'
DeviceManager.cpp:(.text+0x57c): undefined reference to `std::to_string(unsigned long)'
libGateway.a(DeviceManager.cpp.o): In function 
`Gateway::DeviceManager::responseDeviceList(Poco::Timespan const&, 
Poco::AutoPtr<Gateway::Answer>)':
DeviceManager.cpp:(.text+0xc04): undefined reference to `std::to_string(unsigned long)'
DeviceManager.cpp:(.text+0xc2c): undefined reference to `std::to_string(unsigned long)'
DeviceManager.cpp:(.text+0xce0): undefined reference to `std::to_string(unsigned long)'
DeviceManager.cpp:(.text+0xd08): undefined reference to `std::to_string(unsigned long)'
....

Thank you for your advice.

If I’m not mistaken, your function template is not const which means the function signature won’t match. Your function also doesn’t exist in the std namespace.

Try making your to_string function const, put it in the std namespace and see what happens.

Also, is the header with your function included before the headers of libGateway? Linker doesn’t seem to be able to see your function regardless of const-ness.

If you could provide more context I might be able to help you more.

I suspect that you are not linking it with stdlibc++. That is probably why you are missing these. Can you please post how you are compiling it? Please post Makefile for package you are trying to compile and some details on project’s build system. From output I suspect cmake. There are multiple other packages using cmake already in OpenWRT package repository so you can peek inside of them to see how they cope with cmake and c++.

Thank you for your answers. Here is the Makefile which I am using. You are right, it is cmake.

include $(TOPDIR)/rules.mk

PKG_NAME:=gateway
PKG_VERSION:=1.2
PKG_RELEASE:=3
INIT_SCRIPT_NAME:=$(PKG_NAME)

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_PROTO:=git
PKG_BUILD_DEPENDS:=+libmosquittopp +poco +zmq +cppzmq +openzwave +cppunit +bluez-libs
PKG_SOURCE_URL:=https://github.com/BeeeOn/gateway.git
PKG_SOURCE_VERSION:=24b5e82ca34f1a21252af7a35abe34f85a1d3683

CMAKE_INSTALL:=1

include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk

CMAKE_OPTIONS += \
         -DCMAKE_INSTALL_PREFIX=/ \
         -DCMAKE_BUILD_TYPE:STRING=Release \
         -DENABLE_UCLIBCXX_FIXES=YES \
         -DENABLE_UDEV=OFF \
          -DENABLE_FITP=OFF 

TARGET_CFLAGS += -DPOCO_NO_FPENVIRONMENT  

    
define Package/$(PKG_NAME)
        TITLE:=Main application for BeeeOn Gateway
        DEPENDS:=+poco +libmosquittopp +libzmq-nc +cppunit +openzwave +bluez-libs
endef

define Package/$(PKG_NAME)/description
Main application for BeeeOn Gateway.
endef

define Package/$(PKG_NAME)/install
        $(INSTALL_DIR) $(1)
        $(CP) -r $(PKG_INSTALL_DIR)/* $(1)

        $(INSTALL_DIR) $(1)/etc/init.d
        $(INSTALL_BIN) ./files/$(INIT_SCRIPT_NAME) $(1)/etc/init.d/$(INIT_SCRIPT_NAME)
 endef

define Package/$(PKG_NAME)/postinst
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
  echo "Enabling and starting $(PKG_NAME) service"
  /etc/init.d/$(INIT_SCRIPT_NAME) enable
  /etc/init.d/$(INIT_SCRIPT_NAME) start
fi
exit 0
endef

define Package/$(PKG_NAME)/prerm
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
  echo "Disabling and stopping $(PKG_NAME) service"
  /etc/init.d/$(INIT_SCRIPT_NAME) disable
  /etc/init.d/$(INIT_SCRIPT_NAME) stop
fi
exit 0
endef

$(eval $(call BuildPackage,$(PKG_NAME)))

I aslo tried to add the std namespace, but it didn’t have any effect. Probably, from some reason, the workaround isn’t applied at the phase of linking.

1 Like

Is your Makefile custom?

Yes, it is custom Makefile.

Try this:

define Package/$(PKG_NAME)
        TITLE:=Main application for BeeeOn Gateway
        DEPENDS:=$(CXX_DEPENDS) +poco +libmosquittopp +libzmq-nc +cppunit +openzwave +bluez-libs
endef

It’s based on @cynerd suggestion and some searching around. The $(CXX_DEPENDS) adds the proper c++ std lib dependency from the main Makefile.

Thank you, I tried to change the Makefile but still the same problem.