Использование Crypto++ с Clang
Я пытаюсь получить следующий пример Crypto++ (библиотека классов криптографических схем C++) для работы на iMac с использованием clang ++.
пример
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( );
Команда построения
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.
Линкерный выход
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
Я использую последнюю версию разработки Crypto++ 5.6.2, так как предыдущая версия 5.6.1 не может быть собрана с помощью clang ++. Однако я сталкиваюсь с проблемами сборки, утверждая, что у меня отсутствуют символы для архитектуры x86_64.
Любые советы будут с благодарностью.
4 ответа
Crypto++ 5.6.2 успешно собрана на LLVM версии 6.1.0 (clang-602.0.53) с опциями make:
CXXFLAGS="-std=c++11 -stdlib=libstdc++ -DCRYPTOPP_DISABLE_ASM -Wno-c++11-narrowing"
соответственно этот скрипт: https://github.com/mapnik/mapnik-packaging/blob/master/osx/scripts/build_cryptopp.sh
-stdlib=libstdC++ требуется для MacOSX начиная с Mavericks, см.: Когда необходимо использовать, используйте флаг -stdlib=libstdC++?
Вам нужно сделать ссылку на библиотеку, которая предоставляет эти символы, которая должна быть libcryptopp.so, используя-lcryptopp
в команде компилятора
Глядя на вашу "команду сборки" (которая не является командой, которую вы запускаете, это вывод команды, которую вы выполняете, было бы намного легче читать, если бы вы показали фактическую команду), кажется, что вы компилируете .cpp
файл в .o
файл, но получаю ошибку компоновщика, что странно, как создание .o
Файл обычно является шагом до ссылки. Какой шаг вы пытаетесь сделать? Может быть, вам также нужно добавить -c
поэтому он только компилируется и не пытается связать. Вам все еще нужно -lcryptopp
при связывании.
В дополнение к ответу Джонатона, потому что это довольно распространенная проблема, когда -lcryptopp
указан...
Неопределенные символы для архитектуры 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)"
...
__1
означает, что вы используете среду выполнения LLVM C++ (libc++
). Где-то вы, вероятно, смешиваете и сопоставляете со средой выполнения GNU C++ (libstdc++
). Среда выполнения GNU C++ (libstdc++
) не хватает __1
украшение на его символы.
Вы должны просмотреть проект и все предварительно собранные библиотеки и убедиться, что они используют одну или другую. Для каждого вы должны использовать CXXFLAGS
любого из (1) -stdlib=libc++
(LLVM) или (2) -stdlib=libstdc++
(ГНУ).
Имейте в виду, что IDE, такие как Xcode, могут использовать разные -stdlib=...
установка чем Crypto++. В этом случае Xcode должен соответствовать Crypto ++ или пересобрать библиотеку Crypto ++ для соответствия Xcode.
Если XCode использует LLVM libc++
и вам нужно пересобрать Crypto++, затем открыть GNUmakefile
и переделать этот раздел (около строки 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
Если вы хотите использовать LLVM libc++
затем удалите:
# GNU C++ Runtime
LDLIBS += -lstdc++
И добавить:
# LLVM C++ Runtime
CXXFLAGS += -stdlib=libc++
Для полноты, если вы хотите использовать среду выполнения GNU, удалите LDLIBS += -lstdc++
и добавить CXXFLAGS += -stdlib=libstdc++
,
Вы также можете изменить CXX = c++
в CXX ?= c++
поэтому make-файл будет использовать c++
если это не указано в среде или командной строке.
Если интересно, то __1
это встроенное пространство имен, используемое для управления версиями. См. Для чего нужны встроенные пространства имен? и откуда берется символ __1 при использовании libC++ от LLVM?,