由于CryptoPP中未定义的引用,CMake引发异常

时间:2017-10-04 09:47:05

标签: c++ cmake linker crypto++

我收到此错误:

CMakeFiles/Athena.dir/Startup/main.cpp.o: In function `CryptoPP::ClonableImpl<CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>, CryptoPP::Rijndael::Enc>::ClonableImpl()':
/home/dev/workspace/Athena/lib/cryptopp/simple.h:26: undefined reference to `CryptoPP::Rijndael::Enc::Enc()'
collect2: error: ld returned 1 exit status
CMakeFiles/Athena.dir/build.make:434: recipe for target 'Athena'

当我尝试将CryptoPP链接到我的程序时。

这是我的CMakeLists.txt:

cmake_minimum_required(VERSION 3.8)
project(Athena)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fpermissive -Wno-deprecated -Wno-int-to-pointer-cast -Wno-deprecated-declarations")

include_directories(lib/SQLiteCpp/include)
add_subdirectory(lib/SQLiteCpp)

include_directories(lib/cryptopp)
add_subdirectory(lib/cryptopp)

include_directories(lib/json/src)
add_subdirectory(lib/json)

set(SOURCE_FILES
    Startup/main.cpp)

add_executable(Athena ${SOURCE_FILES})
target_link_libraries(Athena SQLiteCpp sqlite3 pthread dl cryptopp)

以下是我的包含:

#include "modes.h" // For CTR_Mode
#include "filters.h" //For StringSource
#include "aes.h" // For AES

我已经尝试通过find_library通过find_package链接cryptopp,我甚至尝试编写脚本来手动下载并制作cryptopp。我真的没有想法,我也很确定这不是我的代码(我在cryptopp wiki的一个例子中粘贴)。

2 个答案:

答案 0 :(得分:1)

您的CMakeLists.txt看起来不正确。你应该做两件事。首先,您应该复制GNUmakefile用于目标的源文件的确切列表。其次,您应该使用GNUmakefile使用的相同标记。您必须运行项目的makefile或msbuild文件才能获得这些文件。

您还应该考虑使用ExternalProject_Add;并停止尝试让Cmake建立库。该库已经提供了一个Makefile和MSBuild文件,用于在它支持的所有平台上构建库,因此Cmake是多余的,不需要。没有理由让Cmake创建具有错误选项和标志的构建文件,因为我们已经为其提供了正确的选项。另请参阅Stack Overflow上的How to use CMake ExternalProject_Add or alternatives in a cross platform way?

在Crypto ++中尝试支持Cmake一年后,我会说很多经验。另请参阅Crypto ++ wiki上的Cmake

CMakeFiles/Athena.dir/Startup/main.cpp.o: In function `CryptoPP::ClonableImpl<CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>, CryptoPP::Rijndael::Enc>::ClonableImpl()':
/home/dev/workspace/Athena/lib/cryptopp/simple.h:26: undefined reference to `CryptoPP::Rijndael::Enc::Enc()'
collect2: error: ld returned 1 exit status
CMakeFiles/Athena.dir/build.make:434: recipe for target 'Athena'

您应该显示用于构建库的命令行。这是Crypto ++取消对Cmake的支持的另一个原因 - 它隐藏了用于故障排除的必要信息,比如用于构建源文件的命令行。这导致了糟糕的错误报告。

Rijndael::Enc::Enc()用于在未对齐的数据访问生效时使代码加强对侧通道攻击。构造函数本身没有使用;但它需要代码路径,因为它中设置了一些值。

如果查看rijndael.h,当平台为IA-32,ARM或PowerPC时,您将看到构造函数已启用。但感兴趣的源文件实际上是rijndael.cpp,在第1070行附近:

#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86

static inline bool AliasedWithTable(const byte *begin, const byte *end)
{
    ptrdiff_t s0 = uintptr_t(begin)%4096, s1 = uintptr_t(end)%4096;
    ptrdiff_t t0 = uintptr_t(Te)%4096, t1 = (uintptr_t(Te)+sizeof(Te))%4096;
    if (t1 > t0)
        return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1);
    else
        return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0);
}

struct Locals
{
    word32 subkeys[4*12], workspace[8];
    const byte *inBlocks, *inXorBlocks, *outXorBlocks;
    byte *outBlocks;
    size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement;
    size_t regSpill, lengthAndCounterFlag, keysBegin;
};

const size_t s_aliasPageSize = 4096;
const size_t s_aliasBlockSize = 256;
const size_t s_sizeToAllocate = s_aliasPageSize + s_aliasBlockSize + sizeof(Locals);

Rijndael::Enc::Enc() : m_aliasBlock(s_sizeToAllocate) { }

#endif  // CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86

#if CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64 || CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
// Do nothing
Rijndael::Enc::Enc() { }
#endif

你需要弄清楚为什么Cmake正在捣乱CRYPTOPP_BOOL_X86CRYPTOPP_BOOL_X64和朋友的定义。为此,您需要查看命令行,但Cmake会将其隐藏起来。

相关的,我们测试C ++ 17,你应该对那个标志没问题。但是,根据经验,这可能会导致问题:set(CMAKE_CXX_STANDARD 17)。 Cmake没有很好的C ++支持。我们无法执行简单的project(cryptopp, CXX)。另请参阅Tell CMake to use C++ compiler for C files coming from CMake?

我将研究删除所有构建的构造函数;并在m_aliasBlock中设置UncheckedSetKey。这可能有助于解决这个问题。但它只是一个更大的工程问题的创可贴。 Cmake创造的更大的工程问题是我们撤回对它的支持的原因。

答案 1 :(得分:0)

尝试

target_link_libraries(Athena SQLiteCpp sqlite3 cryptopp pthread ${CMAKE_DL_LIBS})

我想改变库的排序可能有所帮助。使用${CMAKE_DL_LIBS}代替dl不是强制性的,但使用便携式CMake定义是一种很好的做法。