In CMake, how can I declare a dependency on glibc with a specific or a minimum version? - Stack Overflow

admin2025-05-01  1

Suppose I'm building a C library or app, and that my code uses libc (directly); but I'm relying on functionality or a bug fix which only became available in a certain version of glibc, or on a bug fix which only landed in that certain version of glibc. And if it's not glibc then, well, let's assume I don't want to build at all (a bit of a silly assumption, but for simplicity's sake).

Now, I can't say something like:

find_package(glibc 2.39...2.40 REQUIRED)

right?

How do I constrain the libc used for building my C code, then?

Suppose I'm building a C library or app, and that my code uses libc (directly); but I'm relying on functionality or a bug fix which only became available in a certain version of glibc, or on a bug fix which only landed in that certain version of glibc. And if it's not glibc then, well, let's assume I don't want to build at all (a bit of a silly assumption, but for simplicity's sake).

Now, I can't say something like:

find_package(glibc 2.39...2.40 REQUIRED)

right?

How do I constrain the libc used for building my C code, then?

Share Improve this question asked Jan 2 at 18:31 einpoklumeinpoklum 133k80 gold badges422 silver badges867 bronze badges 1
  • I posted this on the Kitware blog. – einpoklum Commented Feb 6 at 15:31
Add a comment  | 

1 Answer 1

Reset to default 1

As you say, you can't do the like of:

find_package(glibc 2.39 REQUIRED)

or:

find_package(libc6 2.39 REQUIRED)

because the libc6 package, although it is the one that ships GLIBC, and has a matching development package, does not have a CMake development package. Nor can you do the like of:

find_package(PkgConfig REQUIRED)
pkg_check_modules(libc6 REQUIRED libc6 >= 2.39)

because the development package does not install any pkg-config data.

In that case, perhaps the best resort is to exploit the unusual fact that the libc.so.X is executable, and responds to invocation like this:

$ /usr/lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.39-0ubuntu8.3) stable release version 2.39.
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 13.2.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
Minimum supported kernel: 3.2.0
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

in which output it a good bet that the last word on the first line is invariantly the version number, followed by a full-stop.

If so, then we can filter out the version number in the CMakeLists.txt script and test it to be lexically >= the minimum GLIBC version we require, aborting in configuration if it is not.

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(hw)

if (NOT DEFINED GLIBC_MIN_VERSION OR NOT DEFINED LIBC_SO)
    message(STATUS "You must define \
        `-DGLIBC_MIN_VERSION=<minimum Required version of GLIBC>`")
    message(STATUS "You must define \
        `-DLIBC_SO=libc.so.X`, for the build host's `X`")
    message(FATAL_ERROR "Required commandline definitions not given")
endif()

find_library(libc_so ${LIBC_SO})
set(space " ")
execute_process(
#   i.e. ${libc_so} | head -n1 | rev | cut -d' ' -f1 | tail -c +2 | rev
    COMMAND ${libc_so}
    COMMAND head -n1
    COMMAND rev
    COMMAND cut -d${space} -f1
    COMMAND tail -c +2
    COMMAND rev
    OUTPUT_VARIABLE glibc_version
)
if (glibc_version LESS GLIBC_MIN_VERSION)
    message(STATUS "Want at least GLIBC " ${GLIBC_MIN_VERSION})
    message(STATUS "Found GLIBC " ${glibc_version})
    message(FATAL_ERROR "Your GLIBC is too old")    
endif()

add_executable(hw hello_world.c)

Requiring GLIBC >= 2.40:

$ mkdir build && cd build
$ cmake -DGLIBC_MIN_VERSION=2.40 -DLIBC_SO=libc.so.6 ..
-- The C compiler identification is GNU 13.3.0
-- The CXX compiler identification is GNU 13.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
-- Want at least GLIBC 2.40
-- Found GLIBC 2.39

CMake Error at CMakeLists.txt:27 (message):
  Your GLIBC is too old


-- Configuring incomplete, errors occurred!

So once again requiring GLIBC >= 2.35

$ rm -fr *
$ cmake -DGLIBC_MIN_VERSION=2.35 -DLIBC_SO=libc.so.6 ..
-- The C compiler identification is GNU 13.3.0
-- The CXX compiler identification is GNU 13.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 (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /home/imk/develop/so/cmake_prob/build
$ make
[ 50%] Building C object CMakeFiles/hw.dir/hello_world.c.o
[100%] Linking C executable hw
[100%] Built target hw
$ ./hw
Hello World!
转载请注明原文地址:http://www.anycun.com/QandA/1746102969a91706.html