如何使用CMake正确链接到通过vcpkg安装的cryptopp?

huangapple go评论106阅读模式
英文:

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

  1. cmake_minimum_required(VERSION 3.22)
  2. project(untitled)
  3. set(CMAKE_CXX_STANDARD 17)
  4. add_library(llibcryptopp STATIC IMPORTED)
  5. find_package(cryptopp)
  6. add_executable(untitled main.cpp)
  7. target_link_libraries(untitled cryptopp)

main.cpp

  1. #include <iostream>
  2. #include <cryptopp870/sha.h>
  3. #include <cryptopp870/ripemd.h>
  4. #include <iomanip>
  5. int main() {
  6. std::cout << "Hello, World!" << std::endl;
  7. unsigned char input[] = "test";
  8. // do sha256
  9. CryptoPP::byte abDigest[CryptoPP::SHA256::DIGESTSIZE];
  10. CryptoPP::SHA256().CalculateDigest(abDigest, input, 4);
  11. // do ripemd160
  12. CryptoPP::byte abDigest2[CryptoPP::RIPEMD160::DIGESTSIZE];
  13. CryptoPP::RIPEMD160().CalculateDigest(abDigest2, abDigest, CryptoPP::SHA256::DIGESTSIZE);
  14. // print
  15. for (size_t i = 0; i < CryptoPP::RIPEMD160::DIGESTSIZE; i++) {
  16. std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned)abDigest2[i];
  17. }
  18. std::cout << std::endl;
  19. // should output:
  20. // Hello, World!
  21. // cebaa98c19807134434d107b0d3e5692a516ea66
  22. return 0;
  23. }

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

  1. mkdir build
  2. cd build/
  3. cmake -B . -S .. -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
  4. -- The C compiler identification is GNU 11.3.0
  5. -- The CXX compiler identification is GNU 11.3.0
  6. -- Detecting C compiler ABI info
  7. -- Detecting C compiler ABI info - done
  8. -- Check for working C compiler: /usr/bin/cc - skipped
  9. -- Detecting C compile features
  10. -- Detecting C compile features - done
  11. -- Detecting CXX compiler ABI info
  12. -- Detecting CXX compiler ABI info - done
  13. -- Check for working CXX compiler: /usr/bin/c++ - skipped
  14. -- Detecting CXX compile features
  15. -- Detecting CXX compile features - done
  16. -- Configuring done
  17. -- Generating done
  18. -- Build files have been written to: /home/mctrivia/untitled/build
  19. cmake --build .
  20. [ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.o
  21. [100%] Linking CXX executable untitled
  22. /usr/bin/ld: cannot find -lcryptopp: No such file or directory
  23. collect2: error: ld returned 1 exit status
  24. gmake[2]: *** [CMakeFiles/untitled.dir/build.make:97: untitled] Error 1
  25. gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/untitled.dir/all] Error 2
  26. gmake: *** [Makefile:91: all] Error 2

I installed cryptopp using

  1. sudo vcpkg install cryptopp
  2. sudo cp /opt/vcpkg/packages/cryptopp_x64-linux/lib/libcryptopp.a /usr/bin/
  3. sudo mkdir /usr/local/include/cryptopp870
  4. 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 were located on my development laptop, I thought it was worth trying.

英文:

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

  1. cmake_minimum_required(VERSION 3.22)
  2. project(untitled)
  3. set(CMAKE_CXX_STANDARD 17)
  4. add_library(llibcryptopp STATIC IMPORTED)
  5. find_package(cryptopp)
  6. add_executable(untitled main.cpp)
  7. target_link_libraries(untitled cryptopp)

main.cpp

  1. #include &lt;iostream&gt;
  2. #include &lt;cryptopp870/sha.h&gt;
  3. #include &lt;cryptopp870/ripemd.h&gt;
  4. #include &lt;iomanip&gt;
  5. int main() {
  6. std::cout &lt;&lt; &quot;Hello, World!&quot; &lt;&lt; std::endl;
  7. unsigned char input[]=&quot;test&quot;;
  8. //do sha256
  9. CryptoPP::byte abDigest[CryptoPP::SHA256::DIGESTSIZE];
  10. CryptoPP::SHA256().CalculateDigest(abDigest, input, 4);
  11. //do ripemd160
  12. CryptoPP::byte abDigest2[CryptoPP::RIPEMD160::DIGESTSIZE];
  13. CryptoPP::RIPEMD160().CalculateDigest(abDigest2,abDigest,CryptoPP::SHA256::DIGESTSIZE);
  14. //print
  15. for (size_t i=0;i&lt;CryptoPP::RIPEMD160::DIGESTSIZE;i++) {
  16. std::cout &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill(&#39;0&#39;) &lt;&lt; (unsigned)abDigest2[i];
  17. }
  18. std::cout &lt;&lt; std::endl;
  19. //should output:
  20. //Hello, World!
  21. //cebaa98c19807134434d107b0d3e5692a516ea66
  22. return 0;
  23. }

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

  1. mkdir build
  2. cd build/
  3. cmake -B . -S .. -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
  4. -- The C compiler identification is GNU 11.3.0
  5. -- The CXX compiler identification is GNU 11.3.0
  6. -- Detecting C compiler ABI info
  7. -- Detecting C compiler ABI info - done
  8. -- Check for working C compiler: /usr/bin/cc - skipped
  9. -- Detecting C compile features
  10. -- Detecting C compile features - done
  11. -- Detecting CXX compiler ABI info
  12. -- Detecting CXX compiler ABI info - done
  13. -- Check for working CXX compiler: /usr/bin/c++ - skipped
  14. -- Detecting CXX compile features
  15. -- Detecting CXX compile features - done
  16. -- Configuring done
  17. -- Generating done
  18. -- Build files have been written to: /home/mctrivia/untitled/build
  19. cmake --build .
  20. [ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.o
  21. [100%] Linking CXX executable untitled
  22. /usr/bin/ld: cannot find -lcryptopp: No such file or directory
  23. collect2: error: ld returned 1 exit status
  24. gmake[2]: *** [CMakeFiles/untitled.dir/build.make:97: untitled] Error 1
  25. gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/untitled.dir/all] Error 2
  26. gmake: *** [Makefile:91: all] Error 2

I installed cryptopp using

  1. sudo vcpkg install cryptopp
  2. sudo cp /opt/vcpkg/packages/cryptopp_x64-linux/lib/libcryptopp.a /usr/bin/
  3. sudo mkdir /usr/local/include/cryptopp870
  4. 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.

答案1

得分: 2

不需要同时定义已导入的库和使用 find_package 来查找它。

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

> 当使用具有特定CMake支持的库进行安装时,vcpkg将显示有关如何使用该库的信息

对于 cryptopp,vcpkg建议执行以下操作:

  1. find_package(cryptopp CONFIG REQUIRED)
  2. target_link_libraries(main PRIVATE cryptopp::cryptopp)

与vcpkg无关的信息(如果此问题与vcpkg无关,我会说什么):

忽略你所写的 find_package 部分,

你的目标被称为 llibcryptopp。我假设你想在 target_link_libraries 中传递目标名称吧?即 target_link_libraries(untitled llibcryptopp)。我猜 "llib" 是一个拼写错误,你实际上是想说 "lib"。

在CMake中,不需要在库目标名称前加上 "lib" 前缀。事实上,这是不利的,因为CMake会自动在传统平台上将 "lib" 前缀添加到目标的输出文件名中(请参阅 CMAKE_SHARED_LIBRARY_PREFIXCMAKE_STATIC_LIBRARY_PREFIX)。如果你提前加上 "lib" 前缀,你将得到一个以 "liblib" 为前缀的输出文件。

我建议你将目标命名为 cryptopp,然后执行 target_link_libraries(untitled cryptopp)

你可以在参考文档中了解有关 target_link_libraries 的工作方式的信息。每个项参数可以是库目标名称、库文件的完整路径、普通库名称、链接标志或生成器表达式。当库是同一CMake配置中的目标时,应使用库目标名称形式。

英文:

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:

  1. find_package(cryptopp CONFIG REQUIRED)
  2. 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.

huangapple
  • 本文由 发表于 2023年6月26日 09:32:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定