英文:
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 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
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.
答案1
得分: 2
不需要同时定义已导入的库和使用 find_package
来查找它。
https://learn.microsoft.com/en-us/vcpkg/users/buildsystems/cmake-integration#using-libraries 中提到:
> 当使用具有特定CMake支持的库进行安装时,vcpkg将显示有关如何使用该库的信息
对于 cryptopp
,vcpkg建议执行以下操作:
find_package(cryptopp CONFIG REQUIRED)
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_PREFIX
和 CMAKE_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:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论