[英]How do I correctly check for crypt() with CMake?
First of all, please don't lecture me about using crypt()
– I know what it does and what it does not.首先,请不要教我如何使用
crypt()
——我知道它做什么和不做什么。 I have a little C program that is supposed to use the very crypt()
that the OS is using to check user passwords (assuming it does, I know OpenBSD does not).我有一个小 C 程序,它应该使用操作系统用来检查用户密码的
crypt()
(假设它确实如此,我知道 OpenBSD 没有)。
However, crypt()
is a little different in every libc: some require unistd.h
, some require crypt.h
, some require no extra libraries, some require -lcrypt
.但是,每个 libc 中的
crypt()
都略有不同:有些需要unistd.h
,有些需要crypt.h
,有些不需要额外的库,有些需要-lcrypt
。 And there's libxcrypt as well, which is starting to replace glibc's long deprecated crypt()
.还有 libxcrypt ,它开始取代 glibc 长期不推荐使用的
crypt()
。
Long story short: I'm new to CMake, and while checking for something with FindSomething.cmake
or pkg-config is easy, checking for which demons to invoke for libc crypt()
is not, and I feel like I'm doing it wrong.长话短说:我是 CMake 的新手,虽然使用
FindSomething.cmake
或 pkg-config 检查某些东西很容易,但检查要为 libc crypt()
调用的恶魔却不是,我觉得我正在这样做错误的。 It works, but looks way too complicated.它有效,但看起来太复杂了。
Also, I'd like to try using libxcrypt if crypt()
wasn't found with other methods.另外,如果其他方法找不到
crypt()
,我想尝试使用 libxcrypt。 How can I do that without repeating half the checks?我怎样才能做到这一点而不重复一半的检查?
cmake_minimum_required(VERSION 3.10)
project(pwhash)
set(USE_LIBXCRYPT OFF CACHE BOOL "Use libxcrypt for crypt()")
find_package(PkgConfig REQUIRED)
add_executable(pwhash pwhash.c)
if(USE_LIBXCRYPT)
pkg_check_modules(LIBXCRYPT IMPORTED_TARGET REQUIRED libxcrypt)
target_link_libraries(pwhash PUBLIC PkgConfig::LIBXCRYPT)
target_compile_definitions(pwhash PUBLIC HAVE_CRYPT_H)
else()
include(CheckIncludeFile)
check_include_file(crypt.h HAVE_CRYPT_H)
if(HAVE_CRYPT_H)
list(APPEND CMAKE_REQUIRED_INCLUDES "crypt.h")
target_compile_definitions(pwhash PUBLIC HAVE_CRYPT_H)
endif()
include(CheckSymbolExists)
unset(HAVE_CRYPT CACHE)
check_symbol_exists(crypt "unistd.h" HAVE_CRYPT)
if(NOT HAVE_CRYPT)
unset(HAVE_CRYPT CACHE)
list(APPEND CMAKE_REQUIRED_LIBRARIES "crypt")
check_symbol_exists(crypt "unistd.h" HAVE_CRYPT)
if(HAVE_CRYPT)
target_link_libraries(pwhash PUBLIC crypt)
else()
error("No crypt() found")
endif()
endif()
endif()
However,
crypt()
is a little different in every libc: some requireunistd.h
, some requirecrypt.h
, some require no extra libraries, some require-lcrypt
.但是,每个 libc 中的
crypt()
都略有不同:有些需要unistd.h
,有些需要crypt.h
,有些不需要额外的库,有些需要-lcrypt
。 And there's libxcrypt as well, which is starting to replace glibc's long deprecatedcrypt()
.还有 libxcrypt ,它开始取代 glibc 长期不推荐使用的
crypt()
。
As far as I know, the crypt
function is declared in unistd.h
on all major implementations.据我所知,
crypt
函数在所有主要实现的unistd.h
声明。 That includes macOS, FreeBSD, OpenBSD, and Linux.这包括 macOS、FreeBSD、OpenBSD 和 Linux。 The extended set of crypt functions, like
crypt_r
, crypt_rn
, and crypt_ra
are in <crypt.h>
. crypt 函数的扩展集,如
crypt_r
、 crypt_rn
和crypt_ra
位于<crypt.h>
。 I'm curious to know which libcs do not have crypt
in unistd.h
.我很想知道哪些 libcs 在
unistd.h
没有crypt
。
Also, I'd like to try using libxcrypt if crypt() wasn't found with other methods.
另外,如果其他方法找不到 crypt(),我想尝试使用 libxcrypt。 How can I do that without repeating half the checks?
我怎样才能做到这一点而不重复一半的检查?
For this, we'll write a function to encapsulate each method.为此,我们将编写一个函数来封装每个方法。 Each function will try to define an interface library
pwhash_crypt
that encapsulates the usage requirements for the crypt()
function.每个函数都会尝试定义一个接口库
pwhash_crypt
,它封装了crypt()
函数的使用要求。
We'll start with the boilerplate:我们将从样板开始:
cmake_minimum_required(VERSION 3.20)
project(pwhash LANGUAGES C)
First, we'll look at find_libxcrypt
首先,我们来看看
find_libxcrypt
function(find_libxcrypt)
if (TARGET pwhash_crypt)
return()
endif ()
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBXCRYPT IMPORTED_TARGET libxcrypt)
if (TARGET PkgConfig::LIBXCRYPT)
add_library(pwhash_crypt INTERFACE)
target_link_libraries(pwhash_crypt INTERFACE PkgConfig::LIBXCRYPT)
target_compile_definitions(pwhash_crypt INTERFACE HAVE_CRYPT_H)
endif ()
endfunction()
This should be fairly straightforward.这应该相当简单。 If the
pwhash_crypt
target does not exist, then it will try to use pkg-config to find libxcrypt
and create pwhash_crypt
if so.如果
pwhash_crypt
目标不存在,那么它将尝试使用 pkg-config 来查找libxcrypt
并在存在时创建pwhash_crypt
。 Libraries propagate their interface properties to the targets linking to them, so later when we link pwhash
to pwhash_crypt
, it will have HAVE_CRYPT_H
defined.库将它们的接口属性传播到链接到它们的目标,因此稍后当我们将
pwhash
链接到pwhash_crypt
,它将定义HAVE_CRYPT_H
。
The function for the system crypt implementation find_sys_crypt
is similarly straightforward:系统 crypt 实现
find_sys_crypt
函数同样简单:
function(find_sys_crypt)
if (TARGET pwhash_crypt)
return()
endif ()
include(CheckIncludeFile)
include(CheckSymbolExists)
set(defs "")
set(CMAKE_REQUIRED_INCLUDES "")
set(CMAKE_REQUIRED_LIBRARIES "")
check_include_file("crypt.h" HAVE_CRYPT_H)
if (HAVE_CRYPT_H)
list(APPEND defs HAVE_CRYPT_H)
list(APPEND CMAKE_REQUIRED_INCLUDES "crypt.h")
endif ()
check_symbol_exists(crypt "unistd.h" HAVE_CRYPT)
if (NOT HAVE_CRYPT)
list(APPEND CMAKE_REQUIRED_LIBRARIES crypt)
check_symbol_exists(crypt "unistd.h" HAVE_CRYPT_WITH_LIB)
endif ()
if (HAVE_CRYPT OR HAVE_CRYPT_WITH_LIB)
add_library(pwhash_crypt INTERFACE)
target_link_libraries(pwhash_crypt INTERFACE ${CMAKE_REQUIRED_LIBRARIES})
target_compile_definitions(pwhash_crypt INTERFACE ${defs})
endif ()
endfunction()
This follows the same structure as the previous function and the checks in your question.这遵循与上一个函数和问题中的检查相同的结构。
Then you can give users an option whether to look for libxcrypt
first or second and then link the result to your pwhash
executable:然后你可以让用户选择是先还是第二次查找
libxcrypt
,然后将结果链接到你的pwhash
可执行文件:
option(PREFER_LIBXCRYPT "Prefer libxcrypt for crypt()" OFF)
if (PREFER_LIBXCRYPT)
find_libxcrypt()
find_sys_crypt()
else ()
find_sys_crypt()
find_libxcrypt()
endif ()
if (NOT TARGET pwhash_crypt)
message(FATAL_ERROR "Could not find a suitable crypt() implementation")
endif ()
add_executable(pwhash pwhash.c)
target_link_libraries(pwhash PRIVATE pwhash_crypt)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.