Using Crypto++ with clang

3.9k views Asked by At

I'm attempting to get the following Crypto++ (C++ Class Library of Cryptographic Schemes) example to work on a iMac using clang++.

Example

SHA256 hash;

byte digest[ SHA256::DIGESTSIZE ];

hash.CalculateDigest( digest, (byte*) &value[ 0 ], value.size( ) );

HexEncoder encoder;

string result = String::empty;

encoder.Attach( new StringSink( result ) );

encoder.Put( digest, sizeof( digest ) );

encoder.MessageEnd( );

Build command

Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.4.0
Thread model: posix
 "/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.7.4 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name checksum_impl.cpp -pic-level 2 -mdisable-fp-elim -relaxed-aliasing -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 123.2.1 -v -resource-dir /usr/bin/../lib/clang/2.1 -D framework_EXPORTS -I /Users/Ben/Dropbox/appon/build/../source -nostdinc++ -cxx-isystem /usr/include/c++/v1 -Wall -Wextra -Weffc++ -pedantic -std=c++0x -fdeprecated-macro -ferror-limit 19 -fmessage-length 175 -stack-protector 1 -fblocks -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o CMakeFiles/framework.dir/Users/Ben/Dropbox/source/example.cpp.o -x c++ /Users/Ben/Dropbox/source/example.cpp
clang -cc1 version 2.1 based upon llvm 3.0svn hosted on x86_64-apple-darwin11.4.0
#include "..." search starts here:
#include <...> search starts here:
 /Users/Ben/Dropbox/build/../source
 /usr/include/c++/v1
 /usr/local/include
 /usr/bin/../lib/clang/2.1/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.

Linker output

clang: warning: argument unused during compilation: '-std=c++0x'
Undefined symbols for architecture x86_64:
  "CryptoPP::Filter::TransferTo2(CryptoPP::BufferedTransformation&, unsigned long long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::Filter::CopyRangeTo2(CryptoPP::BufferedTransformation&, unsigned long long&, unsigned long long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool) const", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::ChannelCreatePutSpace(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long&)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::ChannelPut2(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned char const*, unsigned long, int, bool)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::ChannelPutModifiable2(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned char*, unsigned long, int, bool)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::ChannelFlush(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, int, bool)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::ChannelMessageSeriesEnd(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
  "CryptoPP::BufferedTransformation::SetRetrievalChannel(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      vtable for CryptoPP::SimpleProxyFilter in checksum_impl.cpp.o
      vtable for CryptoPP::Bufferless<CryptoPP::Filter> in checksum_impl.cpp.o
      vtable for CryptoPP::Unflushable<CryptoPP::Filter> in checksum_impl.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 2

I'm using the latest development version of Crypto++ 5.6.2 as the previous version 5.6.1 fails to build with clang++. However i'm encountering build issues stating that i have missing symbols for x86_64 architecture.

Any hints would be greatly appreciated.

4

There are 4 answers

2
Ben Crowhurst On BEST ANSWER

This issue was relating to Crypto++ not having been ported over to llvm-clang++. The supported compilers are listed on Platforms; supported compilers for previous releases are listed on Compiling.

My solution was to instead use GCrypt.

Sorry I can't supply anymore details on the cause of the failure.

0
jww On

In addition to Jonathon's answer because this is a fairly prevalent problem when -lcryptopp is specified...

Undefined symbols for architecture x86_64. CryptoPP::Filter::TransferTo2(CryptoPP::BufferedTransformation&, unsigned long long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)"...

The __1 indicates you are using the LLVM C++ runtime (libc++). Somewhere, you are probably mixing and matching with the GNU C++ runtime (libstdc++). The GNU C++ runtime (libstdc++) lacks the __1 decoration on its symbols.

You should go through the project and all pre-built libraries, and ensure they are using one or the other. For each, you should use CXXFLAGS of either (1) -stdlib=libc++ (LLVM), or (2) -stdlib=libstdc++ (GNU).

Be aware that IDEs like Xcode may use a different -stdlib=... setting than Crypto++. In this case, have Xcode match Crypto++, or rebuild the Crypto++ library to match Xcode.

If Xcode is using LLVM's libc++ and you have to rebuild Crypto++, then open the GNUmakefile and rework this section (around line 90):

ifeq ($(UNAME),Darwin)
  AR = libtool
  ARFLAGS = -static -o
  CXX = c++
  IS_GCC2 = $(shell $(CXX) -v 2>&1 | $(EGREP) -c gcc-932)
ifeq ($(IS_GCC2),1)
    CXXFLAGS += -fno-coalesce-templates -fno-coalesce-static-vtables
    LDLIBS += -lstdc++
    LDFLAGS += -flat_namespace -undefined suppress -m
endif
endif

If you want to use LLVM's libc++, then remove:

# GNU C++ Runtime
LDLIBS += -lstdc++

And add:

# LLVM C++ Runtime
CXXFLAGS += -stdlib=libc++

For completeness, if you want to use GNU's runtime, then remove the LDLIBS += -lstdc++ and add CXXFLAGS += -stdlib=libstdc++.

You can also change CXX = c++ to CXX ?= c++ so the makefile will use c++ if its not specified in the environment or command line.


If interested, the __1 is an inline namespace used for versioning. See What are inline namespaces for? and Where does the __1 symbol come from when using LLVM's libc++?.

0
lexa-b On

Crypto++ 5.6.2 successfully build on LLVM version 6.1.0 (clang-602.0.53) with make options:

CXXFLAGS="-std=c++11 -stdlib=libstdc++ -DCRYPTOPP_DISABLE_ASM -Wno-c++11-narrowing"

accordingly this script: https://github.com/mapnik/mapnik-packaging/blob/master/osx/scripts/build_cryptopp.sh

-stdlib=libstdc++ need for MacOSX since Mavericks, see: When is it necessary to use use the flag -stdlib=libstdc++?

1
Jonathan Wakely On

you need to link to the library that provides those symbols, which should be libcryptopp.so, using-lcryptopp in the compiler command

Looking at your "build command" (which is not the command you're running, it's the output of the command you're running, it would be a lot easier to read if you showed the actual command) it seems you are compiling a .cpp file into a .o file, but getting a linker error, which is strange as producing a .o file is usualy the step before linking. What step are you trying to do? Maybe you also need to add -c so it only compiles and doesn't try to link. You will still need -lcryptopp when linking.