Search code examples
c++cmakecrypto++cmakelists-options

How do I properly link using CMake to cryptopp installed using vcpkg?


I thought I had figured this out but I recently spun up a new server to let my code run on and I can't get it to build on the new server. Everything works perfectly on my IDE on my development laptop(Ubuntu 22). Here is a simplified example to show what I am trying to do.

CMakeLists.txt

cmake_minimum_required(VERSION 3.22)
project(untitled)

set(CMAKE_CXX_STANDARD 17)

add_library(llibcryptopp STATIC IMPORTED)

find_package(cryptopp)

add_executable(untitled main.cpp)

target_link_libraries(untitled cryptopp)

main.cpp

#include <iostream>

#include <cryptopp870/sha.h>
#include <cryptopp870/ripemd.h>
#include <iomanip>

int main() {
    std::cout << "Hello, World!" << std::endl;

    unsigned char input[]="test";

    //do sha256
    CryptoPP::byte abDigest[CryptoPP::SHA256::DIGESTSIZE];
    CryptoPP::SHA256().CalculateDigest(abDigest, input, 4);

    //do ripemd160
    CryptoPP::byte abDigest2[CryptoPP::RIPEMD160::DIGESTSIZE];
    CryptoPP::RIPEMD160().CalculateDigest(abDigest2,abDigest,CryptoPP::SHA256::DIGESTSIZE);

    //print
    for (size_t i=0;i<CryptoPP::RIPEMD160::DIGESTSIZE;i++) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned)abDigest2[i];
    }

    std::cout << std::endl;

    //should output:
    //Hello, World!
    //cebaa98c19807134434d107b0d3e5692a516ea66


    return 0;
}

On my IDE it executes and prints the correct hash. On the new server when I try to build I get:

mkdir build
cd build/
cmake -B . -S .. -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake

-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mctrivia/untitled/build

cmake --build .

[ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.o
[100%] Linking CXX executable untitled
/usr/bin/ld: cannot find -lcryptopp: No such file or directory
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/untitled.dir/build.make:97: untitled] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/untitled.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

I installed cryptopp using

sudo vcpkg install cryptopp
sudo cp /opt/vcpkg/packages/cryptopp_x64-linux/lib/libcryptopp.a /usr/bin/
sudo mkdir /usr/local/include/cryptopp870
sudo cp /opt/vcpkg/packages/cryptopp_x64-linux/include/cryptopp/* /usr/local/include/cryptopp870/

I would not think the copy commands would be necessary but since that was where the files where located on my development laptop I thought it was worth trying.


Solution

  • It doesn't make to define an imported library and find_package for it at the same time.

    https://learn.microsoft.com/en-us/vcpkg/users/buildsystems/cmake-integration#using-libraries says:

    When installing libraries with specific CMake support, vcpkg will display usage information on how to consume the library

    For cryptopp, vcpkg says to do the following:

    find_package(cryptopp CONFIG REQUIRED)
    target_link_libraries(main PRIVATE cryptopp::cryptopp)
    

    Non-vcpkg-related info (what I would say if this question had nothign to do with vcpkg):

    Ignoring the find_package part of what you wrote,

    Your target is called llibcryptopp. I assume you mean to pass the target name in your target_link _libraries? I.e. target_link_libraries(untitled llibcryptopp). I assume "llib" is a typo and you actually mean "lib".

    It's not necessary to prefix library target names in CMake with "lib". In fact, that's counterproductive, since CMake will add the "lib" prefix to the target's output file name automatically on platforms where that's conventional (see CMAKE_SHARED_LIBRARY_PREFIX and CMAKE_STATIC_LIBRARY_PREFIX). If you preemptively prefix it with "lib", you'll get an output file prefixed with "liblib".

    I'd suggest you name your target cryptopp and then do target_link_libraries(untitled cryptopp).

    You can read about how target_link_libraries works in the reference docs. Each item argument can be a library target name, a full path to a library file, a plain library name, a link flag, or a generator expression. When the library is a target in the same CMake config, you should use the library target name form.