2

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
2
  • 1
    It seems that FindACL.cmake script you use is a some legacy script (which, however, is used in the modern projects). Could you add some part of that (original!) script to the question post, so changing that script in the repo wouldn't invalidate your question? The part which sets ACL_FOUND variable would be definitely sufficient. Commented Sep 29, 2019 at 11:28
  • 1
    Sure! I have added the relevant part of the FindACL.cmake file. The link also points to a specific revision, so it should stay valid as long as the project is not moved. Commented Sep 29, 2019 at 11:47

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Alright, then I will adjust the script to emit the error itself, as you suggested. Using your explanation I was able to find some hint in an official(?) tutorial which supports your suspicion: How to find libraries. Thank you!
Yes, CMake Wiki could be treated as an "official" guide. Thanks for the link, I have added it to the question post as an confirmation. (Before it, I have checked your code and some its variations on my machine with CMake 3.5).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.