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
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.