CMake#
This chapter will look at using CMake to build software.
Note
The steps outlined below are performed on the ARC4 HPC system where a recent CMake is available as a loadable module.
CMake was loaded with the command:
module add cmake/3.22.3
Introduction#
CMake is a collection of tools for building, testing and packaging software. It is open source and cross platform and supports a variety of different build tools including Make, Microsoft Visual Studio, Apple’s Xcode and others.
CMake works by generating build files from a series of CMake configuration files which the relevant build tool can be used to build the software from. This in many cases means CMake is used to create a series of Makefiles which allow us to use GNU make to build our software.
Installation#
If you don’t have CMake installed you can download the latest version for your operating system from the CMake website.
Building software with CMake#
In the following section we’ll explore a small example of building the command line tool cURL using CMake. cURL is a tool for transferring data using various network protocols and is commonly used for downloading data from the internet.
Note
cURL is already installed on ARC4, but we’ll look at installing our own personal version for this tutorial.
Cloning the cURL source code#
To get started we need to download the cURL source code. cURL is available via GitHub so we can clone the source code at the most recent tagged release with the following line.
$ git clone --single-branch --branch curl-7_85_0 https://github.com/curl/curl.git
This will download the cURL source code with the history of the associated release. You will likely see a warning message about being in a detached head state
which you can ignore for this tutorial.
Configuring with CMake#
Now we’ve downloaded the cURL source code we need to configure it before building using CMake.
To do this we need to create a build
directory that will contain all of the autogenerated build file.
Once we’ve created a build
directory we run cmake
to perform the configuration steps.
You can do this directly in the command line by running cmake
and specifying additional options or you can use ccmake
to do configuration interactives through a GUI-like interface.
Using cmake directly#
Running CMake directly runs all the configuration steps and provides some output to the screen.
We can modify CMake default behaviour by passing additional arguments to cmake
at this stage.
$ cd curl
$ mkdir build
$ cd build
$ cmake ..
For modern installations of CMake it is preferable to specify the source and build directories directly when running cmake
.
$ cd curl
$ mkdir build
$ cmake -S . -B build
This command at a basic level, will detect that there are GNU Makefiles present and, using the CMakeLists.txt file, configure a series of Makefiles for building the software. Running this line on ARC4 will provide output similar to this:
-- curl version=[7.85.0-DEV]
-- Could NOT find LibPSL (missing: LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR)
-- Could NOT find LibSSH2 (missing: LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
-- Enabled features: SSL IPv6 unixsockets libz AsynchDNS Largefile alt-svc HSTS NTLM HTTPS-proxy
-- Enabled protocols: DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS LDAP MQTT POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP
-- Enabled SSL backends: OpenSSL
-- Configuring done
-- Generating done
-- Build files have been written to: /home/home01/arcuser/curl
As we’re doing this on ARC4 where a version of cURL is already installed we should probably make some tweaks.
We can do this directly by passing specific arguments to cmake
, in this example we want to specify a specific local build directory and set the name of the associated library libcurl
that gets built to avoid conflicts with the system-installed libcurl
.
$ cd curl
$ mkdir build install
$ cmake -S . -B build/ -DCMAKE_INSTALL_PREFIX=$(pwd)/install -DLIBCURL_OUTPUT_NAME=libcurl2
View full output
-- The C compiler identification is Intel 19.0.4.20190416
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /apps/developers/compilers/intel/19.0.4/1/default/compilers_and_libraries_2019.4.243/linux/bin/intel64/icc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- curl version=[7.85.0-DEV]
-- Performing Test _no_bug
-- Performing Test _no_bug - Success
-- Performing Test HAVE_SOCKADDR_IN6_SIN6_ADDR
-- Performing Test HAVE_SOCKADDR_IN6_SIN6_ADDR - Success
-- Performing Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
-- Performing Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID - Success
-- Found Perl: /usr/bin/perl (found version "5.16.3")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Looking for connect in socket;-lpthread
-- Looking for connect in socket;-lpthread - not found
-- Looking for gethostname
-- Looking for gethostname - found
-- Found OpenSSL: /usr/lib64/libcrypto.so (found version "1.0.2k")
-- Looking for RAND_egd
-- Looking for RAND_egd - not found
-- Looking for OPENSSL_IS_BORINGSSL
-- Looking for OPENSSL_IS_BORINGSSL - not found
-- Looking for ldap_init in ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto
-- Looking for ldap_init in ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto - found
-- Looking for ber_init in lber;ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto
-- Looking for ber_init in lber;ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto - found
-- Looking for include file ldap.h
-- Looking for include file ldap.h - found
-- Looking for include files ldap.h, lber.h
-- Looking for include files ldap.h, lber.h - found
-- Performing Test NOT_NEED_LBER_H
-- Performing Test NOT_NEED_LBER_H - Success
-- Looking for 3 include files ldap.h, ..., ldap_ssl.h
-- Looking for 3 include files ldap.h, ..., ldap_ssl.h - not found
-- Looking for idn2_lookup_ul in idn2;lber;ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto
-- Looking for idn2_lookup_ul in idn2;lber;ldap;-lpthread;OpenSSL::SSL;OpenSSL::Crypto - not found
-- Found ZLIB: /usr/lib64/libz.so (found version "1.2.7")
-- Could NOT find LibPSL (missing: LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR)
-- Could NOT find LibSSH2 (missing: LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
-- Performing Test USE_UNIX_SOCKETS
-- Performing Test USE_UNIX_SOCKETS - Success
-- Found CA bundle: /etc/pki/tls/certs/ca-bundle.crt
-- Looking for 3 include files ldap.h, ..., inttypes.h
-- Looking for 3 include files ldap.h, ..., inttypes.h - found
-- Looking for 4 include files ldap.h, ..., sys/filio.h
-- Looking for 4 include files ldap.h, ..., sys/filio.h - not found
-- Looking for 4 include files ldap.h, ..., sys/ioctl.h
-- Looking for 4 include files ldap.h, ..., sys/ioctl.h - found
-- Looking for 5 include files ldap.h, ..., sys/param.h
-- Looking for 5 include files ldap.h, ..., sys/param.h - found
-- Looking for 6 include files ldap.h, ..., sys/poll.h
-- Looking for 6 include files ldap.h, ..., sys/poll.h - found
-- Looking for 7 include files ldap.h, ..., sys/resource.h
-- Looking for 7 include files ldap.h, ..., sys/resource.h - found
-- Looking for 8 include files ldap.h, ..., sys/select.h
-- Looking for 8 include files ldap.h, ..., sys/select.h - found
-- Looking for 9 include files ldap.h, ..., sys/socket.h
-- Looking for 9 include files ldap.h, ..., sys/socket.h - found
-- Looking for 10 include files ldap.h, ..., sys/sockio.h
-- Looking for 10 include files ldap.h, ..., sys/sockio.h - not found
-- Looking for 10 include files ldap.h, ..., sys/stat.h
-- Looking for 10 include files ldap.h, ..., sys/stat.h - found
-- Looking for 11 include files ldap.h, ..., sys/time.h
-- Looking for 11 include files ldap.h, ..., sys/time.h - found
-- Looking for 12 include files ldap.h, ..., sys/types.h
-- Looking for 12 include files ldap.h, ..., sys/types.h - found
-- Looking for 13 include files ldap.h, ..., sys/un.h
-- Looking for 13 include files ldap.h, ..., sys/un.h - found
-- Looking for 14 include files ldap.h, ..., sys/utime.h
-- Looking for 14 include files ldap.h, ..., sys/utime.h - not found
-- Looking for 14 include files ldap.h, ..., sys/xattr.h
-- Looking for 14 include files ldap.h, ..., sys/xattr.h - found
-- Looking for 15 include files ldap.h, ..., arpa/inet.h
-- Looking for 15 include files ldap.h, ..., arpa/inet.h - found
-- Looking for 16 include files ldap.h, ..., arpa/tftp.h
-- Looking for 16 include files ldap.h, ..., arpa/tftp.h - found
-- Looking for 17 include files ldap.h, ..., assert.h
-- Looking for 17 include files ldap.h, ..., assert.h - found
-- Looking for 18 include files ldap.h, ..., errno.h
-- Looking for 18 include files ldap.h, ..., errno.h - found
-- Looking for 19 include files ldap.h, ..., fcntl.h
-- Looking for 19 include files ldap.h, ..., fcntl.h - found
-- Looking for 20 include files ldap.h, ..., idn2.h
-- Looking for 20 include files ldap.h, ..., idn2.h - not found
-- Looking for 20 include files ldap.h, ..., ifaddrs.h
-- Looking for 20 include files ldap.h, ..., ifaddrs.h - found
-- Looking for 21 include files ldap.h, ..., io.h
-- Looking for 21 include files ldap.h, ..., io.h - not found
-- Looking for 21 include files ldap.h, ..., libgen.h
-- Looking for 21 include files ldap.h, ..., libgen.h - found
-- Looking for 22 include files ldap.h, ..., locale.h
-- Looking for 22 include files ldap.h, ..., locale.h - found
-- Looking for 23 include files ldap.h, ..., net/if.h
-- Looking for 23 include files ldap.h, ..., net/if.h - found
-- Looking for 24 include files ldap.h, ..., netdb.h
-- Looking for 24 include files ldap.h, ..., netdb.h - found
-- Looking for 25 include files ldap.h, ..., netinet/in.h
-- Looking for 25 include files ldap.h, ..., netinet/in.h - found
-- Looking for 26 include files ldap.h, ..., netinet/tcp.h
-- Looking for 26 include files ldap.h, ..., netinet/tcp.h - found
-- Looking for linux/tcp.h
-- Looking for linux/tcp.h - found
-- Looking for 27 include files ldap.h, ..., poll.h
-- Looking for 27 include files ldap.h, ..., poll.h - found
-- Looking for 28 include files ldap.h, ..., pwd.h
-- Looking for 28 include files ldap.h, ..., pwd.h - found
-- Looking for 29 include files ldap.h, ..., setjmp.h
-- Looking for 29 include files ldap.h, ..., setjmp.h - found
-- Looking for 30 include files ldap.h, ..., signal.h
-- Looking for 30 include files ldap.h, ..., signal.h - found
-- Looking for 31 include files ldap.h, ..., ssl.h
-- Looking for 31 include files ldap.h, ..., ssl.h - not found
-- Looking for 31 include files ldap.h, ..., stdatomic.h
-- Looking for 31 include files ldap.h, ..., stdatomic.h - found
-- Looking for 32 include files ldap.h, ..., stdbool.h
-- Looking for 32 include files ldap.h, ..., stdbool.h - found
-- Looking for 33 include files ldap.h, ..., stdint.h
-- Looking for 33 include files ldap.h, ..., stdint.h - found
-- Looking for 34 include files ldap.h, ..., stdlib.h
-- Looking for 34 include files ldap.h, ..., stdlib.h - found
-- Looking for 35 include files ldap.h, ..., string.h
-- Looking for 35 include files ldap.h, ..., string.h - found
-- Looking for 36 include files ldap.h, ..., strings.h
-- Looking for 36 include files ldap.h, ..., strings.h - found
-- Looking for 37 include files ldap.h, ..., stropts.h
-- Looking for 37 include files ldap.h, ..., stropts.h - not found
-- Looking for 37 include files ldap.h, ..., termio.h
-- Looking for 37 include files ldap.h, ..., termio.h - found
-- Looking for 38 include files ldap.h, ..., termios.h
-- Looking for 38 include files ldap.h, ..., termios.h - found
-- Looking for 39 include files ldap.h, ..., time.h
-- Looking for 39 include files ldap.h, ..., time.h - found
-- Looking for 40 include files ldap.h, ..., unistd.h
-- Looking for 40 include files ldap.h, ..., unistd.h - found
-- Looking for 41 include files ldap.h, ..., utime.h
-- Looking for 41 include files ldap.h, ..., utime.h - found
-- Looking for 42 include files ldap.h, ..., process.h
-- Looking for 42 include files ldap.h, ..., process.h - not found
-- Looking for 42 include files ldap.h, ..., stddef.h
-- Looking for 42 include files ldap.h, ..., stddef.h - found
-- Looking for 44 include files ldap.h, ..., sys/utsname.h
-- Looking for 44 include files ldap.h, ..., sys/utsname.h - found
-- Check size of size_t
-- Check size of size_t - done
-- Check size of ssize_t
-- Check size of ssize_t - done
-- Check size of long long
-- Check size of long long - done
-- Check size of long
-- Check size of long - done
-- Check size of int
-- Check size of int - done
-- Check size of __int64
-- Check size of __int64 - done
-- Check size of time_t
-- Check size of time_t - done
-- Looking for fchmod
-- Looking for fchmod - found
-- Looking for basename
-- Looking for basename - found
-- Looking for socket
-- Looking for socket - found
-- Looking for select
-- Looking for select - found
-- Looking for strdup
-- Looking for strdup - found
-- Looking for strtok_r
-- Looking for strtok_r - found
-- Looking for strcasecmp
-- Looking for strcasecmp - found
-- Looking for stricmp
-- Looking for stricmp - not found
-- Looking for strcmpi
-- Looking for strcmpi - not found
-- Looking for alarm
-- Looking for alarm - found
-- Looking for getppid
-- Looking for getppid - found
-- Looking for utimes
-- Looking for utimes - found
-- Looking for gettimeofday
-- Looking for gettimeofday - found
-- Looking for closesocket
-- Looking for closesocket - not found
-- Looking for sigsetjmp
-- Looking for sigsetjmp - found
-- Looking for getpass_r
-- Looking for getpass_r - not found
-- Looking for getpwuid
-- Looking for getpwuid - found
-- Looking for getpwuid_r
-- Looking for getpwuid_r - found
-- Looking for geteuid
-- Looking for geteuid - found
-- Looking for utime
-- Looking for utime - found
-- Looking for gmtime_r
-- Looking for gmtime_r - found
-- Looking for gethostbyname_r
-- Looking for gethostbyname_r - found
-- Looking for signal
-- Looking for signal - found
-- Looking for SIGALRM
-- Looking for SIGALRM - found
-- Looking for strtoll
-- Looking for strtoll - found
-- Looking for _strtoi64
-- Looking for _strtoi64 - not found
-- Looking for strerror_r
-- Looking for strerror_r - found
-- Looking for siginterrupt
-- Looking for siginterrupt - found
-- Looking for getaddrinfo
-- Looking for getaddrinfo - found
-- Looking for freeaddrinfo
-- Looking for freeaddrinfo - found
-- Looking for pipe
-- Looking for pipe - found
-- Looking for ftruncate
-- Looking for ftruncate - found
-- Looking for getpeername
-- Looking for getpeername - found
-- Looking for getsockname
-- Looking for getsockname - found
-- Looking for if_nametoindex
-- Looking for if_nametoindex - found
-- Looking for getrlimit
-- Looking for getrlimit - found
-- Looking for setlocale
-- Looking for setlocale - found
-- Looking for setmode
-- Looking for setmode - not found
-- Looking for setrlimit
-- Looking for setrlimit - found
-- Looking for mach_absolute_time
-- Looking for mach_absolute_time - not found
-- Looking for inet_pton
-- Looking for inet_pton - found
-- Looking for fsetxattr
-- Looking for fsetxattr - found
-- Performing Curl Test HAVE_FSETXATTR_5
-- Performing Curl Test HAVE_FSETXATTR_5 - Success
-- Performing Curl Test HAVE_FSETXATTR_6
-- Performing Curl Test HAVE_FSETXATTR_6 - Failed
-- Check size of sa_family_t
-- Check size of sa_family_t - done
-- Check size of ADDRESS_FAMILY
-- Check size of ADDRESS_FAMILY - failed
-- Looking for sigaction
-- Looking for sigaction - found
-- Performing Curl Test HAVE_FCNTL_O_NONBLOCK
-- Performing Curl Test HAVE_FCNTL_O_NONBLOCK - Success
-- Performing Curl Test HAVE_IOCTLSOCKET
-- Performing Curl Test HAVE_IOCTLSOCKET - Failed
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL - Failed
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL_FIONBIO
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL_FIONBIO - Failed
-- Performing Curl Test HAVE_IOCTLSOCKET_FIONBIO
-- Performing Curl Test HAVE_IOCTLSOCKET_FIONBIO - Failed
-- Performing Curl Test HAVE_IOCTL_FIONBIO
-- Performing Curl Test HAVE_IOCTL_FIONBIO - Success
-- Performing Curl Test HAVE_IOCTL_SIOCGIFADDR
-- Performing Curl Test HAVE_IOCTL_SIOCGIFADDR - Success
-- Performing Curl Test HAVE_SETSOCKOPT_SO_NONBLOCK
-- Performing Curl Test HAVE_SETSOCKOPT_SO_NONBLOCK - Failed
-- Performing Curl Test TIME_WITH_SYS_TIME
-- Performing Curl Test TIME_WITH_SYS_TIME - Success
-- Performing Curl Test HAVE_O_NONBLOCK
-- Performing Curl Test HAVE_O_NONBLOCK - Failed
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_3
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_3 - Failed
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_5
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_5 - Failed
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_6
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_6 - Success
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_3_REENTRANT
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_3_REENTRANT - Failed
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_5_REENTRANT
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_5_REENTRANT - Failed
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_6_REENTRANT
-- Performing Curl Test HAVE_GETHOSTBYNAME_R_6_REENTRANT - Success
-- Performing Curl Test HAVE_IN_ADDR_T
-- Performing Curl Test HAVE_IN_ADDR_T - Success
-- Performing Curl Test HAVE_BOOL_T
-- Performing Curl Test HAVE_BOOL_T - Success
-- Performing Curl Test STDC_HEADERS
-- Performing Curl Test STDC_HEADERS - Success
-- Performing Curl Test HAVE_FILE_OFFSET_BITS
-- Performing Curl Test HAVE_FILE_OFFSET_BITS - Success
-- Performing Curl Test HAVE_VARIADIC_MACROS_C99
-- Performing Curl Test HAVE_VARIADIC_MACROS_C99 - Success
-- Performing Curl Test HAVE_VARIADIC_MACROS_GCC
-- Performing Curl Test HAVE_VARIADIC_MACROS_GCC - Success
-- Performing Curl Test HAVE_ATOMIC
-- Performing Curl Test HAVE_ATOMIC - Failed
-- Check size of off_t
-- Check size of off_t - done
-- Check size of curl_off_t
-- Check size of curl_off_t - done
-- Performing Curl Test HAVE_GLIBC_STRERROR_R
-- Performing Curl Test HAVE_GLIBC_STRERROR_R - Failed
-- Performing Curl Test HAVE_POSIX_STRERROR_R
-- Performing Curl Test HAVE_POSIX_STRERROR_R - Success
-- Performing Curl Test HAVE_CLOCK_GETTIME_MONOTONIC
-- Performing Curl Test HAVE_CLOCK_GETTIME_MONOTONIC - Success
-- Performing Curl Test HAVE_BUILTIN_AVAILABLE
-- Performing Curl Test HAVE_BUILTIN_AVAILABLE - Failed
-- Performing Test curl_cv_recv
-- Performing Test curl_cv_recv - Success
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, int, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, int, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, size_t, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, size_t, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, socklen_t, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, unsigned int, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, char *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, int, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, int, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, size_t, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, size_t, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, socklen_t, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, unsigned int, int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Failed
-- Tested: int recv(SOCKET, void *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Success
-- Tested: int recv(int, char *, int, int)
-- Performing Test curl_cv_send
-- Performing Test curl_cv_send - Success
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, size_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, size_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, socklen_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, unsigned int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const char *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, size_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, size_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, socklen_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, unsigned int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, const void *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, size_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, size_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, socklen_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, unsigned int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, void *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, size_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, size_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, socklen_t, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, socklen_t, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, unsigned int, int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Failed
-- Tested: int send(SOCKET, char *, unsigned int, unsigned int)
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Success
-- Tested: int send(int, const char *, int, int)
-- Performing Test HAVE_MSG_NOSIGNAL
-- Performing Test HAVE_MSG_NOSIGNAL - Success
-- Performing Test HAVE_STRUCT_TIMEVAL
-- Performing Test HAVE_STRUCT_TIMEVAL - Success
-- Check size of struct sockaddr_storage
-- Check size of struct sockaddr_storage - done
-- Performing Test HAVE_POLL_FINE
-- Performing Test HAVE_POLL_FINE - Success
-- Enabled features: SSL IPv6 unixsockets libz AsynchDNS Largefile alt-svc HSTS NTLM HTTPS-proxy
-- Enabled protocols: DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS LDAP MQTT POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP
-- Enabled SSL backends: OpenSSL
-- Configuring done
-- Generating done
-- Build files have been written to: /home/home01/arcuser/curl/build
It is normal to specify CMake options by their name with a -D
prepended to the option name.
By default CMake will install software in standard location on our machine, this often means locations such as /usr/local
which requires sudo
rights to write to.
Therefore, it’s often better for software we want to build just for ourselves to specify the -DCMAKE_INSTALL_PREFIX
argument to be a local directory our user has access to.
Note
This example has been picked for its simplicity and doesn’t require any additional libraries that aren’t already installed and available on ARC4. Most software has additional dependencies that you will either need to load as a module or install separately before being able to have CMake configure successfully. Always be sure to check the documentation to understand what the exact requirements are for the software you’re trying to install.
Using ccmake#
You can also do the CMake configuration steps using ccmake
which provides a GUI-like interface for adjusting CMake configuration options.
You can open the ccmake GUI by running the following line within the curl
directory:
$ ccmake -S . -B build
BUILD_CURL_EXE ON
BUILD_SHARED_LIBS ON
BUILD_TESTING ON
CMAKE_BUILD_TYPE
CMAKE_INSTALL_PREFIX /usr/local
CMAKE_LBER_LIB lber
CMAKE_LDAP_INCLUDE_DIR
CMAKE_LDAP_LIB ldap
CURL_BROTLI OFF
CURL_CA_BUNDLE /etc/pki/tls/certs/ca-bundle.crt
CURL_CA_BUNDLE_SET ON
CURL_CA_FALLBACK OFF
CURL_CA_PATH /etc/ssl/certs
CURL_CA_PATH_SET ON
CURL_DISABLE_OPENSSL_AUTO_LOAD OFF
CURL_ENABLE_SSL ON
CURL_LTO OFF
BUILD_CURL_EXE: Set to ON to build curl executable.
Keys: [enter] Edit an entry [d] Delete an entry CMake Version 3.22.3
[l] Show log output [c] Configure
[h] Help [q] Quit without generating
[t] Toggle advanced mode (currently off)
This provides the following interface where we can navigate through options using the arrow keys and adjust entries as required.
Using ccmake
is often a useful way to view all the available configuration settings for a project and adjust them as required.
You can also use c
to run the configuration step to check everything configures successfully before confirming you want to proceed with that configuration by pressing g
for generate.
If you’re using ccmake
for this tutorial rather than cmake
then you’ll need to adjust the settings CMAKE_INSTALL_PREFIX
to be the full path to the install
directory we created earlier and you’ll need to adjust the LIBCURL_OUTPUT_NAME
setting to libcurl2
.
Building CMake configured software#
Now that CMake has configured everything we can proceed to building the software using GNU Make (here we pass the option -j 4
to use multiple threads).
$ cd build
$ make -j 4
Once the make step completes successfully we can install the cURL executable to the previously specified install location with the command:
$ make install
If you’ve set everything up as I have on ARC4 and run this in your /home directory your new cURL executable will be at ~/curl/install/bin
.
However, because we already have a system-installed cURL version we need to do an extra step before testing out our newly built version of cURL.
Crucially, we need to make the libcurl2
library that was also built with cURL available for our new cURL executable to use.
If we try and run our new cURL without doing this step we get the following error:
$ ~/curl/install/bin/curl --version
/home/home01/arcuser/curl/install/bin/curl: error while loading shared libraries: libcurl2.so: cannot open shared object file: No such file or directory
This is because libcurl2
is not available to use via the associated environment variable.
To solve this we need to update the LD_LIBRARY_PATH
variable to include the directory containing libcurl2.so
.
We do this by appending a directory path to the colon-separated LD_LIBRARY_PATH
variable.
$ export "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/curl/install/lib64"
$ ~/curl/install/bin/curl --version
curl 7.85.0-DEV (Linux) libcurl/7.85.0-DEV OpenSSL/1.0.2k-fips zlib/1.2.7
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM SSL UnixSockets
So after adding the directory location containing our libcurl2.so
file our newly created cURL executable is able to find it’s associated library and run correctly.
Note
Editing variables like this during a shell session do not persist between shell sessions.
In order to keep these changes between different shell sessions you will need to add the above export
line the .bashrc
login script that exists in your home directory.
Summary#
Important
Introduces CMake tool for configuring build systems
Linked to CMake download page for installation steps
Showcased an example of deploying
curl
using CMakeIncluded how to configure specific settings using
-D
optionHighlighted using
-DCMAKE_INSTALL_PREFIX
for appropriate installation of software locallyShowed steps to build software using GNU Make after configuring with CMake
Highlighted modifying
LD_LIBRARY_PATH
for locally installed software and libraries