janw
janw

Reputation: 9646

find_package(ACL REQUIRED) does not stop processing

I am currently trying to set up a CMake-based build system for a small C library of mine. Since this library depends on libacl, CMake should verify that it is present on the system, or fail otherwise.

Since there is no predefined FindACL module, I used the one from the KDE project:

[...] check_include_files [...] find_library [...]

if (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
   set(ACL_FOUND TRUE)
   set(ACL_LIBS ${ACL_LIBS} ${ATTR_LIBS})
   message(STATUS "Found ACL support: ${ACL_LIBS}")
endif (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)

I call it using the following (minimal) CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)

project(
    cmaketest
    VERSION 1.0
    DESCRIPTION "cmake test"
    LANGUAGES C
)

set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(ACL REQUIRED) # ACL_LIBS

It correctly detects that my system is lacking the libacl includes, but does not stop processing, even though the manual states that

The REQUIRED option stops processing with an error message if the package cannot be found.

Do I have to explicitly check whether ACL_FOUND is set, through an if statement?

I am using CMake 3.13.4. Terminal output:

-- The C compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for include file attr/libattr.h
-- Looking for include file attr/libattr.h - not found
-- Looking for include file sys/xattr.h
-- Looking for include file sys/xattr.h - found
-- Looking for include file sys/acl.h
-- Looking for include file sys/acl.h - not found
-- Looking for include file acl/libacl.h
-- Looking for include file acl/libacl.h - not found
-- Configuring done
-- Generating done
-- Build files have been written to: [redacted]/build

Upvotes: 2

Views: 1243

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 66089

It seems that since some time CMake expects a FindXXX.cmake script (used in MODULE mode of find_package) to check REQUIRED option and emit an error if needed. Such change in CMake behavior makes old legacy "Find" scripts, like FindACL.cmake, to be broken.

Indirect confirmation of that can be found in this "Common bug in find module", described in CMake wiki:

The module does not check _FIND_REQUIRED or _FIND_QUIETLY - and thus the find_package arguments QUIET and REQUIRED will have no effect

So, FindACL.cmake script could be rewritten as follows:

# FindACL.cmake

# ...

if (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
  set(ACL_FOUND TRUE)
  set(ACL_LIBS ${ACL_LIBS} ${ATTR_LIBS})
  message(STATUS "Found ACL support: ${ACL_LIBS}")
elif (ACL_FIND_REQUIRED)
  # ACL hasn't been found but REQUIRED. Emit an error.
  message(FATAL_ERROR "Cannot find ACL")
endif (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)

Actually, most "Find" scripts use the special helper which sets result of find_package and cares about its options. FindACL.cmake could also use this helper:

# FindACL.cmake

# ...

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ACL
  # Use default message on fail.
  DEFAULT_MSG
  # Variables which should be true-evaluated for assume the package to be found
  ACL_HEADERS_FOUND ACL_LIBS ATTR_LIBS
)

The things are different for XXXConfig.cmake scripts, which are processed in CONFIG mode of find_package. These scripts should only set XXX_FOUND variable to false, and CMake will handle REQUIRED option by itself.

Upvotes: 1

Related Questions