Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide C++11 ABI style binary of libsnowboy-detect.a #99

Open
kskalski opened this issue Jan 1, 2017 · 27 comments
Open

Provide C++11 ABI style binary of libsnowboy-detect.a #99

kskalski opened this issue Jan 1, 2017 · 27 comments

Comments

@kskalski
Copy link

kskalski commented Jan 1, 2017

When I compile with GCC 5 I get
speech.cc:(.text+0x4ec): undefined reference to snowboy::SnowboyDetect::SnowboyDetect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' speech.cc:(.text+0x500): undefined reference to snowboy::SnowboyDetect::SetSensitivity(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)'

I've seen a recent addition of -D_GLIBCXX_USE_CXX11_ABI=0 into C++ examples, which I think is related to the same problem. However in my case I link to some other libraries, which are only available in CXX11 ABI on my system, so it seems I have to use it for all of my project and in this case it causes failure shown above.

@chenguoguo
Copy link
Collaborator

I'll leave this up for a while. I'm a little bit reluctant to move everything to gcc 5.1 or above.

I haven't tried compiling with another library compiled with GLIBCXX_USE_CXX11_ABI set to 1. What happens if you set -D_GLIBCXX_USE_CXX11_ABI=0 when you compile your binary?

@kskalski
Copy link
Author

kskalski commented Jan 2, 2017

My exact problem is that libprotobuf 3.0.0 on raspbian is compiled with gcc 5 and contains some symbols, which are incompatible when using old ABI. For reference, there is a page detailing compatibility and how to check if given lib is likely to have problems: https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

My fallback is to just recompile it from sources for my project and don't use the OS lib.

As for compiling the lib with GLIBCXX_USE_CXX11_ABI=1 (or using gcc-5) I encourage you to try - it's possible that it will just work if your code doesn't reference C++ objects from other dependencies. Then you can provide CXX11 ABI version of the lib, which will be useful in the future in any case.

The exact error I get when compiling my code with GLIBCXX_USE_CXX11_ABI=0 is:
speech.o: In function google::protobuf::internal::GetEmptyStringAlreadyInited()': speech.cc:(.text._ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedEv[_ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedEv]+0x3c): undefined reference to google::protobuf::internal::empty_string_'
because I'm referencing lib using new ABI.
I guess it's not possible to build binary which is referencing C++ objects from two different libraries using different ABI versions - thus I get error from either one of them.

@chenguoguo
Copy link
Collaborator

GLIBCXX_USE_CXX11_ABI=1 is a way to go, yes. But I'd like to take it slowly, after full checks. Don't want to break people's existing setups.

@kskalski
Copy link
Author

kskalski commented Jan 2, 2017 via email

@BillWSY
Copy link
Contributor

BillWSY commented Jan 9, 2017

Our solution was to build a wrapper class that only expose plain C types in the interface. The first line of the .cc file is #define _GLIBCXX_USE_CXX11_ABI 0, so it can call Snowboy correctly. The rest of the system use char* to pass the parameters.

You don't need GLIBCXX_USE_CXX11_ABI=0 in the global compile options.

@kskalski
Copy link
Author

kskalski commented Jan 9, 2017 via email

@BillWSY
Copy link
Contributor

BillWSY commented Jan 9, 2017

In fact, the <string> library would use the old STL namespace when _GLIBCXX_USE_CXX11_ABI is defined as 0. So make sure it is defined to 0 before including <string>, directly and indirectly.

@kskalski
Copy link
Author

kskalski commented Jan 10, 2017 via email

@fcolecumberri
Copy link

Hi there, I'm having almost the same problem, I'm making an application that uses c++11 libraries and I'm trying to incorporate this project, but the strings are incompatible, and in my case I would need to remake a lot just to make a way around, if you could just compile a libsnowboy-detect++11.a it would not break others implementation and it wold help a lot.

@kskalski
Copy link
Author

You can include following in your project:

snowboy_wrapper.h

#pragma once

#include <cstdint>

class Snowboy {
 public:
  struct Model {
    const char* filename;
    float sensitivity;
  };

  Snowboy(const char* resource_name, Model model, float audio_gain);

  int SampleRate() const;
  int NumChannels() const;
  int BitsPerSample() const;

  int RunDetection(const int16_t* data, int num_samples);

 private:
  void* detector_;
};

snowboy_wrapper.cc

#undef _GLIBCXX_USE_CXX11_ABI
#define _GLIBCXX_USE_CXX11_ABI 0
#include "snowboy_wrapper.h"

#include "snowboy/include/snowboy-detect.h"

static snowboy::SnowboyDetect* c(void* p) { return reinterpret_cast<snowboy::SnowboyDetect*>(p); }
static const snowboy::SnowboyDetect* c(const void* p) {
  return reinterpret_cast<const snowboy::SnowboyDetect*>(p);
}

Snowboy::Snowboy(const char* resource_name, Model model, float audio_gain)
    : detector_(new snowboy::SnowboyDetect(resource_name, model.filename)) {
  // Initializes Snowboy detector.
  // If you have multiple hotword models (e.g., 2), you should set
  // <model_filename> and <sensitivity_str> as follows:
  //   model_filename = "resources/snowboy.umdl,resources/alexa.pmdl";
  //   sensitivity_str = "0.4,0.4";
  c(detector_)->SetSensitivity(std::to_string(model.sensitivity));
  c(detector_)->SetAudioGain(audio_gain);
  c(detector_)->ApplyFrontend(true);
}

int Snowboy::SampleRate() const { return c(detector_)->SampleRate(); }

int Snowboy::NumChannels() const { return c(detector_)->NumChannels(); }

int Snowboy::BitsPerSample() const { return c(detector_)->BitsPerSample(); }

int Snowboy::RunDetection(const int16_t* data, int num_samples) {
  return c(detector_)->RunDetection(data, num_samples);
}

It should work when you use Snowboy object for using the library.

@ghost
Copy link

ghost commented Dec 18, 2017

@BillWSY Hey Bill. Do you know what a savior you are for people like me that read your little comment a few months later? You have no idea what 2 minutes of your time means for people like me that come along months later. You're the man Bill. The man. Wish I could buy you a beer.

@chenguoguo
Copy link
Collaborator

Perhaps, you could submit a PR for that Bill? @BillWSY

@BillWSY
Copy link
Contributor

BillWSY commented Dec 19, 2017

I think @kskalski already provided a well-rounded wrapper. I have something that is very similar, but it will be a duplicate.

@chenguoguo
Copy link
Collaborator

@kskalski would you like to make your wrapper part of the project?

@kskalski
Copy link
Author

As I noted in #99 (comment) I think it would be better if the primary snowboy class just added another constructor and appropriate API with const char* parameters, which would remove the necessity of using a wrapper.

I'm not sure if this would require choosing different names for methods with const char* parameter, the overloads might get hard or impossible to use in this case.

In any case, feel free to include the code in the project, here is a commit with some made-up names / layout 651114d

@NicoHood
Copy link

Can anyone tell me where the source of libsnowboy-detect.a can be found?

@chenguoguo
Copy link
Collaborator

The source code was not released, only libraries were available to the public.

@tatasadi
Copy link

tatasadi commented May 8, 2018

Could someone tell me where should I put this wrapper? How should I use it?

@tatasadi
Copy link

@kskalski Could you please read my last comment and answer it?

@kskalski
Copy link
Author

Not sure if I understand the question - you put it in our client code / compile together with classes using snowboy in your app

@tatasadi
Copy link

@kskalski thank you for your answer. I mean where in client code? (avs-device-sdk/third-party/snowboy/include/ ??) which file should I change to use this wrapper in make? my make command is:

cd /home/ubuntu/Projekte/avs-device-sdk/sdk-build && cmake /home/ubuntu/Projekte/avs-device-sdk/sdk-source/avs-device-sdk -DKITTAI_KEY_WORD_DETECTOR=ON -DKITTAI_KEY_WORD_DETECTOR_LIB_PATH=/home/ubuntu/Projekte/avs-device-sdk/third-party/snowboy/lib/ubuntu64/libsnowboy-detect.a -DKITTAI_KEY_WORD_DETECTOR_INCLUDE_DIR=/home/ubuntu/Projekte/avs-device-sdk/third-party/snowboy/include -DGSTREAMER_MEDIA_PLAYER=ON -DPORTAUDIO=ON -DPORTAUDIO_LIB_PATH=/home/ubuntu/Projekte/avs-device-sdk/third-party/portaudio/lib/.libs/libportaudio.a -DPORTAUDIO_INCLUDE_DIR=/home/ubuntu/Projekte/avs-device-sdk/third-party/portaudio/include && make

Your help would be much appreciated.

@kskalski
Copy link
Author

I don't know your build system, but the wrapper should be part of your app. Do you have any your own source file in your app? Find it in the build system (CMakeLists.txt I guess) and add the wrapper files there too.

@johnnyhuziqin
Copy link

johnnyhuziqin commented May 22, 2018

I am using ubuntu 16.04, with gcc 5.4 installed, i have the same compile error, here is how I fix:
add a line to the CmakeList.txt in the skd-source folder

cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
# Set project information
project(AlexaClientSDK VERSION 1.7.0 LANGUAGES CXX)

run cmake (with all needed args)
run make clean
run make
by this, compile ok. hope this help you.

@avp24
Copy link

avp24 commented Sep 23, 2018

@johnnyhuziqin thank you for your help. With your steps I could able to complete by Build process.
@kskalski @BillWSY @chenguoguo Thanks for your explanations.
Thanks again!

@BlueBlastoise2
Copy link

BlueBlastoise2 commented Oct 5, 2018

Hi, I am currently making modification on Amazon's AVS sample app and make it to work with Kitt.AI. I have put the wrapper in the folder. I am still getting the error. I am not quite sure what I did wrong.
My project is here https://github.com/j42lin/avs-device-sdk/tree/master/SampleApp/src

I put it under avs-device-sdk, and this is the error I got

[100%] Building CXX object SampleApp/src/CMakeFiles/SampleApp.dir/PortAudioMicrophoneWrapper.cpp.o
[100%] Linking CXX executable SampleApp
../../KWD/KittAi/src/libKITTAI.so: undefined reference to `snowboy::SnowboyDetect::SetSensitivity(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
../../KWD/KittAi/src/libKITTAI.so: undefined reference to `snowboy::SnowboyDetect::SnowboyDetect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
SampleApp/src/CMakeFiles/SampleApp.dir/build.make:388: recipe for target 'SampleApp/src/SampleApp' failed
make[3]: *** [SampleApp/src/SampleApp] Error 1
CMakeFiles/Makefile2:8752: recipe for target 'SampleApp/src/CMakeFiles/SampleApp.dir/all' failed
make[2]: *** [SampleApp/src/CMakeFiles/SampleApp.dir/all] Error 2
CMakeFiles/Makefile2:8764: recipe for target 'SampleApp/src/CMakeFiles/SampleApp.dir/rule' failed
make[1]: *** [SampleApp/src/CMakeFiles/SampleApp.dir/rule] Error 2
Makefile:2227: recipe for target 'SampleApp' failed
make: *** [SampleApp] Error 2

@checkomkar
Copy link

I am using ubuntu 16.04, with gcc 5.4 installed, i have the same compile error, here is how I fix:
add a line to the CmakeList.txt in the skd-source folder

cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
# Set project information
project(AlexaClientSDK VERSION 1.7.0 LANGUAGES CXX)

run cmake (with all needed args)
run make clean
run make
by this, compile ok. hope this help you.

Thank you. This helped a lot. Cheers!

@EpicIntegratedSystems
Copy link

I am using ubuntu 16.04, with gcc 5.4 installed, i have the same compile error, here is how I fix:
add a line to the CmakeList.txt in the skd-source folder

cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
# Set project information
project(AlexaClientSDK VERSION 1.7.0 LANGUAGES CXX)

run cmake (with all needed args)
run make clean
run make
by this, compile ok. hope this help you.

Thank you. This helped a lot. Cheers!

This also worked for me. Thanks a ton!

Ubuntu 18.04
gcc 8.2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests