
With this commit, users are able to build valkey using `CMake`. ## Example usage: Build `valkey-server` in Release mode with TLS enabled and using `jemalloc` as the allocator: ```bash mkdir build-release cd $_ cmake .. -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/tmp/valkey-install \ -DBUILD_MALLOC=jemalloc -DBUILD_TLS=1 make -j$(nproc) install # start valkey /tmp/valkey-install/bin/valkey-server ``` Build `valkey-unit-tests`: ```bash mkdir build-release-ut cd $_ cmake .. -DCMAKE_BUILD_TYPE=Release \ -DBUILD_MALLOC=jemalloc -DBUILD_UNIT_TESTS=1 make -j$(nproc) # Run the tests ./bin/valkey-unit-tests ``` Current features supported by this PR: - Building against different allocators: (`jemalloc`, `tcmalloc`, `tcmalloc_minimal` and `libc`), e.g. to enable `jemalloc` pass `-DBUILD_MALLOC=jemalloc` to `cmake` - OpenSSL builds (to enable TLS, pass `-DBUILD_TLS=1` to `cmake`) - Sanitizier: pass `-DBUILD_SANITIZER=<address|thread|undefined>` to `cmake` - Install target + redis symbolic links - Build `valkey-unit-tests` executable - Standard CMake variables are supported. e.g. to install `valkey` under `/home/you/root` pass `-DCMAKE_INSTALL_PREFIX=/home/you/root` Why using `CMake`? To list *some* of the advantages of using `CMake`: - Superior IDE integrations: cmake generates the file `compile_commands.json` which is required by `clangd` to get a compiler accuracy code completion (in other words: your VScode will thank you) - Out of the source build tree: with the current build system, object files are created all over the place polluting the build source tree, the best practice is to build the project on a separate folder - Multiple build types co-existing: with the current build system, it is often hard to have multiple build configurations. With cmake you can do it easily: - It is the de-facto standard for C/C++ project these days More build examples: ASAN build: ```bash mkdir build-asan cd $_ cmake .. -DBUILD_SANITIZER=address -DBUILD_MALLOC=libc make -j$(nproc) ``` ASAN with jemalloc: ```bash mkdir build-asan-jemalloc cd $_ cmake .. -DBUILD_SANITIZER=address -DBUILD_MALLOC=jemalloc make -j$(nproc) ``` As seen by the previous examples, any combination is allowed and co-exist on the same source tree. ## Valkey installation With this new `CMake`, it is possible to install the binary by running `make install` or creating a package `make package` (currently supported on Debian like distros) ### Example 1: build & install using `make install`: ```bash mkdir build-release cd $_ cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/valkey-install -DCMAKE_BUILD_TYPE=Release make -j$(nproc) install # valkey is now installed under $HOME/valkey-install ``` ### Example 2: create a `.deb` installer: ```bash mkdir build-release cd $_ cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) package # ... CPack deb generation output sudo gdebi -n ./valkey_8.1.0_amd64.deb # valkey is now installed under /opt/valkey ``` ### Example 3: create installer for non Debian systems (e.g. FreeBSD or macOS): ```bash mkdir build-release cd $_ cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) package mkdir -p /opt/valkey && ./valkey-8.1.0-Darwin.sh --prefix=/opt/valkey --exclude-subdir # valkey-server is now installed under /opt/valkey ``` Signed-off-by: Eran Ifrah <eifrah@amazon.com>
103 lines
3.2 KiB
CMake
103 lines
3.2 KiB
CMake
# Return the current host distro name. For example: ubuntu, debian, amzn etc
|
|
function (valkey_get_distro_name DISTRO_NAME)
|
|
if (LINUX AND NOT APPLE)
|
|
execute_process(
|
|
COMMAND /bin/bash "-c" "cat /etc/os-release |grep ^ID=|cut -d = -f 2"
|
|
OUTPUT_VARIABLE _OUT_VAR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
# clean the output
|
|
string(REPLACE "\"" "" _OUT_VAR "${_OUT_VAR}")
|
|
string(REPLACE "." "" _OUT_VAR "${_OUT_VAR}")
|
|
set(${DISTRO_NAME}
|
|
"${_OUT_VAR}"
|
|
PARENT_SCOPE)
|
|
elseif (APPLE)
|
|
set(${DISTRO_NAME}
|
|
"darwin"
|
|
PARENT_SCOPE)
|
|
elseif (IS_FREEBSD)
|
|
set(${DISTRO_NAME}
|
|
"freebsd"
|
|
PARENT_SCOPE)
|
|
else ()
|
|
set(${DISTRO_NAME}
|
|
"unknown"
|
|
PARENT_SCOPE)
|
|
endif ()
|
|
endfunction ()
|
|
|
|
function (valkey_parse_version OUT_MAJOR OUT_MINOR OUT_PATCH)
|
|
# Read and parse package version from version.h file
|
|
file(STRINGS ${CMAKE_SOURCE_DIR}/src/version.h VERSION_LINES)
|
|
foreach (LINE ${VERSION_LINES})
|
|
string(FIND "${LINE}" "#define VALKEY_VERSION " VERSION_STR_POS)
|
|
if (VERSION_STR_POS GREATER -1)
|
|
string(REPLACE "#define VALKEY_VERSION " "" LINE "${LINE}")
|
|
string(REPLACE "\"" "" LINE "${LINE}")
|
|
# Change "." to ";" to make it a list
|
|
string(REPLACE "." ";" LINE "${LINE}")
|
|
list(GET LINE 0 _MAJOR)
|
|
list(GET LINE 1 _MINOR)
|
|
list(GET LINE 2 _PATCH)
|
|
message(STATUS "Valkey version: ${_MAJOR}.${_MINOR}.${_PATCH}")
|
|
# Set the output variables
|
|
set(${OUT_MAJOR}
|
|
${_MAJOR}
|
|
PARENT_SCOPE)
|
|
set(${OUT_MINOR}
|
|
${_MINOR}
|
|
PARENT_SCOPE)
|
|
set(${OUT_PATCH}
|
|
${_PATCH}
|
|
PARENT_SCOPE)
|
|
endif ()
|
|
endforeach ()
|
|
endfunction ()
|
|
|
|
# Given input argument `OPTION_VALUE`, check that the `OPTION_VALUE` is from the allowed values (one of:
|
|
# module/yes/no/1/0/true/false)
|
|
#
|
|
# Return value:
|
|
#
|
|
# If ARG is valid, return its number where:
|
|
#
|
|
# ~~~
|
|
# - `no` | `0` | `off` => return `0`
|
|
# - `yes` | `1` | `on` => return `1`
|
|
# - `module` => return `2`
|
|
# ~~~
|
|
function (valkey_parse_build_option OPTION_VALUE OUT_ARG_ENUM)
|
|
list(APPEND VALID_OPTIONS "yes")
|
|
list(APPEND VALID_OPTIONS "1")
|
|
list(APPEND VALID_OPTIONS "on")
|
|
list(APPEND VALID_OPTIONS "no")
|
|
list(APPEND VALID_OPTIONS "0")
|
|
list(APPEND VALID_OPTIONS "off")
|
|
list(APPEND VALID_OPTIONS "module")
|
|
|
|
string(TOLOWER "${OPTION_VALUE}" OPTION_VALUE)
|
|
list(FIND VALID_OPTIONS "${ARG}" OPT_INDEX)
|
|
if (VERSION_STR_POS GREATER -1)
|
|
message(FATAL_ERROR "Invalid value passed ''${OPTION_VALUE}'")
|
|
endif ()
|
|
|
|
if ("${OPTION_VALUE}" STREQUAL "yes"
|
|
OR "${OPTION_VALUE}" STREQUAL "1"
|
|
OR "${OPTION_VALUE}" STREQUAL "on")
|
|
set(${OUT_ARG_ENUM}
|
|
1
|
|
PARENT_SCOPE)
|
|
elseif (
|
|
"${OPTION_VALUE}" STREQUAL "no"
|
|
OR "${OPTION_VALUE}" STREQUAL "0"
|
|
OR "${OPTION_VALUE}" STREQUAL "off")
|
|
set(${OUT_ARG_ENUM}
|
|
0
|
|
PARENT_SCOPE)
|
|
else ()
|
|
set(${OUT_ARG_ENUM}
|
|
2
|
|
PARENT_SCOPE)
|
|
endif ()
|
|
endfunction ()
|