问题
I have the following project structure:
myexec/
|-main.cpp
|-hashing.cpp
|-hashing.h
|-CMakeLists.txt
My little software needs Crypto++ whose latest version I built under this path:
C:\Users\myuser\cryptopp
CMakeLists.txt
is:
cmake_minimum_required (VERSION 3.8)
project ("MyExec")
add_executable(MyExec "main.cpp", "hashing.h", "hashing.cpp")
find_library(CRYPTOPP_LIB cryptopp "C:/Users/myuser/cryptopp/Win32/DLL_Output/Debug")
target_link_libraries(MyExec PUBLIC "${CRYPTOPP_LIB}")
target_include_directories(MyExec PUBLIC "C:/Users/myuser/cryptopp")
hashing.cpp
is:
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 // Needed to use MD5 in Crypto++
#include <cryptlib.h>
#include <md5.h>
#include "Hashing.h"
using namespace CryptoPP;
std::string get_hash(const std::string& str)
{
std::string digest;
Weak::MD5 hash;
hash.Update((const byte*)(str.data()), str.size());
digest.resize(hash.DIGESTSIZE);
hash.Final((byte*)&digest[0]);
return digest;
}
Problem
As I compile this in VS 2019 Community on my Win10 x64 machine, I get this linking error:
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl CryptoPP::Algorithm::Algorithm(bool)" (??0Algorithm@CryptoPP@@QEAA@_N@Z) referenced in function "public: __cdecl CryptoPP::HashTransformation::HashTransformation(void)" (??0HashTransformation@CryptoPP@@QEAA@XZ)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl CryptoPP::HashTransformation::TruncatedVerify(unsigned char const *,unsigned __int64)" (?TruncatedVerify@HashTransformation@CryptoPP@@UEAA_NPEBE_K@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: virtual void __cdecl CryptoPP::IteratedHashBase<unsigned int,class CryptoPP::HashTransformation>::Update(unsigned char const *,unsigned __int64)" (?Update@?$IteratedHashBase@IVHashTransformation@CryptoPP@@@CryptoPP@@UEAAXPEBE_K@Z) referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl get_hash(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?get_hash@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV34@@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2001: unresolved external symbol "public: virtual unsigned char * __cdecl CryptoPP::IteratedHashBase<unsigned int,class CryptoPP::HashTransformation>::CreateUpdateSpace(unsigned __int64 &)" (?CreateUpdateSpace@?$IteratedHashBase@IVHashTransformation@CryptoPP@@@CryptoPP@@UEAAPEAEAEA_K@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl CryptoPP::IteratedHashBase<unsigned int,class CryptoPP::HashTransformation>::Restart(void)" (?Restart@?$IteratedHashBase@IVHashTransformation@CryptoPP@@@CryptoPP@@UEAAXXZ)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl CryptoPP::IteratedHashBase<unsigned int,class CryptoPP::HashTransformation>::TruncatedFinal(unsigned char *,unsigned __int64)" (?TruncatedFinal@?$IteratedHashBase@IVHashTransformation@CryptoPP@@@CryptoPP@@UEAAXPEAE_K@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual unsigned __int64 __cdecl CryptoPP::IteratedHashBase<unsigned int,class CryptoPP::HashTransformation>::HashMultipleBlocks(unsigned int const *,unsigned __int64)" (?HashMultipleBlocks@?$IteratedHashBase@IVHashTransformation@CryptoPP@@@CryptoPP@@MEAA_KPEBI_K@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: static void __cdecl CryptoPP::Weak1::MD5::InitState(unsigned int *)" (?InitState@MD5@Weak1@CryptoPP@@SAXPEAI@Z) referenced in function "protected: virtual void __cdecl CryptoPP::IteratedHashWithStaticTransform<unsigned int,struct CryptoPP::EnumToType<enum CryptoPP::ByteOrder,0>,64,16,class CryptoPP::Weak1::MD5,0,0>::Init(void)" (?Init@?$IteratedHashWithStaticTransform@IU?$EnumToType@W4ByteOrder@CryptoPP@@$0A@@CryptoPP@@$0EA@$0BA@VMD5@Weak1@2@$0A@$0A@@CryptoPP@@MEAAXXZ)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: static void __cdecl CryptoPP::Weak1::MD5::Transform(unsigned int *,unsigned int const *)" (?Transform@MD5@Weak1@CryptoPP@@SAXPEAIPEBI@Z) referenced in function "protected: virtual void __cdecl CryptoPP::IteratedHashWithStaticTransform<unsigned int,struct CryptoPP::EnumToType<enum CryptoPP::ByteOrder,0>,64,16,class CryptoPP::Weak1::MD5,0,0>::HashEndianCorrectedBlock(unsigned int const *)" (?HashEndianCorrectedBlock@?$IteratedHashWithStaticTransform@IU?$EnumToType@W4ByteOrder@CryptoPP@@$0A@@CryptoPP@@$0EA@$0BA@VMD5@Weak1@2@$0A@$0A@@CryptoPP@@MEAAXPEBI@Z)
C:\Users\myuser\cryptopp\Win32\DLL_Output\Debug\cryptopp.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64'
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\myexec.exe : fatal error LNK1120: 9 unresolved externals
ninja: build stopped: subcommand failed.
What am I doing wrong here?
Edit
After good feedback from @botje and @nelsonsule, I fixed the x64 issue:
find_library(CRYPTOPP_LIB cryptopp "C:/Users/myuser/cryptopp/x64/DLL_Output/Release")
This is now causing the arch mismatch warning to go away, but I will get 2 linking errors:
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: static void __cdecl CryptoPP::Weak1::MD5::InitState(unsigned int *)" (?InitState@MD5@Weak1@CryptoPP@@SAXPEAI@Z) referenced in function "protected: virtual void __cdecl CryptoPP::IteratedHashWithStaticTransform<unsigned int,struct CryptoPP::EnumToType<enum CryptoPP::ByteOrder,0>,64,16,class CryptoPP::Weak1::MD5,0,0>::Init(void)" (?Init@?$IteratedHashWithStaticTransform@IU?$EnumToType@W4ByteOrder@CryptoPP@@$0A@@CryptoPP@@$0EA@$0BA@VMD5@Weak1@2@$0A@$0A@@CryptoPP@@MEAAXXZ)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\Hashing.cpp.obj : error LNK2019: unresolved external symbol "public: static void __cdecl CryptoPP::Weak1::MD5::Transform(unsigned int *,unsigned int const *)" (?Transform@MD5@Weak1@CryptoPP@@SAXPEAIPEBI@Z) referenced in function "protected: virtual void __cdecl CryptoPP::IteratedHashWithStaticTransform<unsigned int,struct CryptoPP::EnumToType<enum CryptoPP::ByteOrder,0>,64,16,class CryptoPP::Weak1::MD5,0,0>::HashEndianCorrectedBlock(unsigned int const *)" (?HashEndianCorrectedBlock@?$IteratedHashWithStaticTransform@IU?$EnumToType@W4ByteOrder@CryptoPP@@$0A@@CryptoPP@@$0EA@$0BA@VMD5@Weak1@2@$0A@$0A@@CryptoPP@@MEAAXPEBI@Z)
C:\Users\myuser\Documents\myexec\out\build\x64-Debug (default)\myexec.exe : fatal error LNK1120: 2 unresolved externals
回答1:
C:\Users\myuser\cryptopp\Win32\DLL_Output\Debug\cryptopp.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64'
Your problem seems to be coming from here. you're running on a higher architecture of OS (x64
) while linking to a crypto library designed for a lower OS architecture (x86
) which is a 32 bit. consider linking to a cyrpto library designed for x64
回答2:
OK I have managed to build a minimum reproducible example that works.
Download https://github.com/weidai11/cryptopp and extract to E:\__experiments\cryptopp\cryptopp-master
Open cryptest.sln
in Visual Studio, select x64 configuration and build.
Under directory E:__experiments\cryptopp\testprog:
build\
src\main.cpp
CMakeLists.txt
CMakeLists.txt:
cmake_minimum_required (VERSION 3.15)
# this enables the MSVC_RUNTIME_LIBRARY property for slightly older CMake versions
cmake_policy(SET CMP0091 NEW)
project ("MD5test")
add_executable(MD5test "src/main.cpp")
# this is equivalent to setting C/C++ -> Code Generation -> Runtime Library in the Visual Studio project property pages
set_property(TARGET MD5test
PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
find_library(CRYPTOPP_LIB cryptlib.lib HINTS E:/__experiments/cryptopp/cryptopp-master/x64/Output/*)
target_link_libraries(MD5test PUBLIC "${CRYPTOPP_LIB}")
target_include_directories(MD5test PUBLIC "E:/__experiments/cryptopp/cryptopp-master")
src\main.cpp:
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 // Needed to use MD5 in Crypto++
#include <cryptlib.h>
#include <md5.h>
#include <string>
#include <iostream>
#define byte unsigned char
using std::string;
string get_hash(const string& str)
{
string digest;
CryptoPP::Weak::MD5 hash;
hash.Update((const byte*)(str.data()), str.size());
digest.resize(hash.DIGESTSIZE);
hash.Final((byte*)&digest[0]);
return digest;
}
int main (int argc, char** argv)
{
string hash = get_hash("coconuts");
std::cout << hash << std::endl;
return 0;
Open a "Developer command prompt for VS2019" and navigate to the testprog dir, then enter:
del build
mkdir build
cd build
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ..
cmake --build .
Debug\MD5test.exe
Alternatively write a batch file in the test root, do_build.bat
, so you can use a plain command prompt window:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat"
cd .
del /F /Q build
rd /S /Q build
mkdir build
cd build
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ..
cmake --build .
cd ..
来源:https://stackoverflow.com/questions/64334300/linking-crypto-fails-when-building-a-c-project-using-cmake