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?
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!