Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CMake build system for valkey #1196

Merged
merged 22 commits into from
Nov 8, 2024
Merged

Conversation

eifrah-aws
Copy link
Contributor

@eifrah-aws eifrah-aws commented Oct 20, 2024

Replacing this PR #1082

NOTE:

This PR was tested on:

  • Amazon Linux 2
  • Ubuntu 22.04
  • AlmaLinux 9
  • macOS Sonoma 14.7 (ARM)
  • FreeBSD 9 - note on FreeBSD, we require gmake for building valkey

With this PR, 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:

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:

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:

mkdir build-asan
cd $_
cmake .. -DBUILD_SANITIZER=address -DBUILD_MALLOC=libc
make -j$(nproc)

ASAN with jemalloc:

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:

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:

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):

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

Current CMake PR status:

  • Targets:
    • valkey-server
    • valkey-cli
    • valkey-benchmark
    • valkey-sentinel
    • RDMA module
    • TLS as module
    • valkey-unit-tests
    • valkey-check-aof
    • valkey-check-rdb
  • Features
    • SSL
    • Sanitizer
    • Different allocators (jemalloc, libc, tcmalloc and tcmalloc_minimal)
    • Support .deb packaging
    • Support for script based installer for non debian systems
  • Python code generation
    • generate release.h
    • generate commands.def
    • generate fmtargs.h
    • generate test_files.h

Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws eifrah-aws marked this pull request as ready for review October 20, 2024 21:20
@eifrah-aws eifrah-aws mentioned this pull request Oct 20, 2024
20 tasks
@eifrah-aws
Copy link
Contributor Author

@PingXie see this PR instead.

Copy link

codecov bot commented Oct 20, 2024

Codecov Report

Attention: Patch coverage is 0% with 1 line in your changes missing coverage. Please review.

Project coverage is 70.69%. Comparing base (2743b7e) to head (da9b98d).
Report is 34 commits behind head on unstable.

Files with missing lines Patch % Lines
src/debug.c 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #1196      +/-   ##
============================================
- Coverage     70.69%   70.69%   -0.01%     
============================================
  Files           114      114              
  Lines         63076    63150      +74     
============================================
+ Hits          44594    44644      +50     
- Misses        18482    18506      +24     
Files with missing lines Coverage Δ
src/server.c 87.70% <ø> (-1.05%) ⬇️
src/debug.c 53.05% <0.00%> (ø)

... and 20 files with indirect coverage changes

Copy link
Contributor

@pizhenwei pizhenwei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use WITH_TLS instead of USE_TLS? Then we have a single TLS related building variable.

@PingXie PingXie added the run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP) label Oct 21, 2024
cmake/Modules/ValkeySetup.cmake Outdated Show resolved Hide resolved
cmake/Modules/ValkeySetup.cmake Outdated Show resolved Hide resolved
Copy link
Member

@PingXie PingXie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @eifrah-aws

.cmake-format.yaml Show resolved Hide resolved
.cmake-format.yaml Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
cmake/Modules/Packaging.cmake Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
cmake/Modules/SourceFiles.cmake Outdated Show resolved Hide resolved
cmake/Modules/ValkeySetup.cmake Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
@pizhenwei
Copy link
Contributor

Is it possible to generate config.h by cmake?
I guess this may be the next step.

- Force function names to lowercase in YAML config file
- Parse version from version.h instead of hard-coding it
- Fixed typo
- Moved utility functions into their own module `Utils.cmake`
- macOS: do not hard code "/usr/bin/clang", instead use `find_program`
- Support for WITH_TLS=module|yes|off|1|0
- Support for WITH_RDMA=module|off|0
- Fixed (never worked for the original Makefile as well): build TLS as module on macOS

Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws
Copy link
Contributor Author

Is it possible to generate config.h by cmake?
I guess this may be the next step.

Yes, but this will break Makefile users. So until CMake is agreed as the main build tool, I wouldn't go this path

Copy link
Contributor

@pizhenwei pizhenwei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I also find the missing CMakeLists.txt for tests:

$ find tests -name Makefile
tests/rdma/Makefile
tests/modules/Makefile

And cmake related help information in README.md is needed?

cmake/Modules/Utils.cmake Outdated Show resolved Hide resolved
cmake/Modules/ValkeySetup.cmake Outdated Show resolved Hide resolved
@PingXie
Copy link
Member

PingXie commented Oct 22, 2024

I wonder if we should drop building TLS as a module now in CMake. Looks like RDMA can only be built as a module now, which is fine, as long as we don't support two build systems.

@valkey-io/core-team thoughts?

- Fixed comment
- Use a more accurate variable name `RDMACM` as the output prefix
- Avoid using condition like `if (USE_TLS EQUAL 2)`, instead use `if (BUILD_TLS_MODULE)`
- Build "hello*" moodules
- Build "test" modules (using conditional variable `-DBUILD_TEST_MODULES=1`)
- Build "rdma-test"

Signed-off-by: Eran Ifrah <[email protected]>
Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws
Copy link
Contributor Author

Hi, I also find the missing CMakeLists.txt for tests:

Fixed with recent commit

Signed-off-by: Eran Ifrah <[email protected]>
Signed-off-by: Eran Ifrah <[email protected]>
Signed-off-by: Eran Ifrah <[email protected]>
Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws
Copy link
Contributor Author

And cmake related help information in README.md is needed?

README updated

Copy link
Member

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine removing building TLS as a module. No longer really seems necessary.

Before merging, we should all add it to the CI to make sure it runs as expected.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
src/modules/CMakeLists.txt Outdated Show resolved Hide resolved
src/debug.c Outdated Show resolved Hide resolved
src/server.c Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
- Make `main` + `serverAssert` "weak" symbols
- Set LTO using CMake proper syntax instead of hacking it into the build
  flags
- For consistency, change all args starting with `WITH_*` to `BUILD_*`.
  for example: `cmake .. -DBUILD_TLS=module -DBUILD_MALLOC=jemalloc -DBUILD_UNIT_TESTS=1`
- Only search for OpenSSL if BUILD_TLS is "on" or "module"

Signed-off-by: Eran Ifrah <[email protected]>
Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws
Copy link
Contributor Author

@madolson per your suggestion, I made the symbols main & serverAssert "weak" to allow them to be overridden by symbols from test_main.c file. Tested on Ubuntu. Amzn Linux 2, FreeBSD & macOS

@eifrah-aws
Copy link
Contributor Author

eifrah-aws commented Oct 27, 2024

@PingXie @madolson can one of you re-start the failing CI job?

@eifrah-aws
Copy link
Contributor Author

@PingXie / @madolson can one of you please re-run the the flaky test? (I am pretty sure its flaky as this PR does not change any source file, nor it tests the artifacts produced by CMake 😉 )

Also, are there any outstanding issues that preventing us from merging this PR?

@PingXie
Copy link
Member

PingXie commented Oct 31, 2024

Yeah that is a flaky test.

Also, are there any outstanding issues that preventing us from merging this PR?

Can we drop the option to build TLS as a module? I think now it is a good time to make this change.

@pizhenwei do you have any concerns?

@pizhenwei
Copy link
Contributor

Yeah that is a flaky test.

Also, are there any outstanding issues that preventing us from merging this PR?

Can we drop the option to build TLS as a module? I think now it is a good time to make this change.

@pizhenwei do you have any concerns?

Dropping tls module option is OK to me!

@eifrah-aws
Copy link
Contributor Author

eifrah-aws commented Oct 31, 2024

Can we drop the option to build TLS as a module? I think now it is a good time to make this change.

Great, will drop it

@madolson madolson added the major-decision-pending Major decision pending by TSC team label Oct 31, 2024
Copy link
Member

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, was able to test and run everything locally on my x86 mac. The only pending item I have now is I would like us to add it to CI so that we don't silently break it. Let's add a separate test here: https://github.com/valkey-io/valkey/blob/unstable/.github/workflows/ci.yml#L13 that does cmake + make. I think for now just doing it on linux is fine.

@valkey-io/core-team I added the approved tag since we did discuss this in our weekly meeting. But tagging again incase anyone else would like to review before we merge.

@madolson madolson added major-decision-approved Major decision approved by TSC team and removed major-decision-pending Major decision pending by TSC team labels Oct 31, 2024
Copy link
Member

@enjoy-binbin enjoy-binbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look ok to me. (i don't know much about it so did not do the review)

- Drop TLS module build
- Added CI for building on Ubuntu (latest) using CMake and running tests (unit tests + tcl tests)
- lualib: create a proper CMake file and don't rely on the old Makefile

Signed-off-by: Eran Ifrah <[email protected]>
- YAML formatting
- CMake: use the correct keyword "WARNING" instead of "WARN"

Signed-off-by: Eran Ifrah <[email protected]>
@eifrah-aws
Copy link
Contributor Author

eifrah-aws commented Nov 5, 2024

@madolson / @PingXie

Signed-off-by: Eran Ifrah <[email protected]>
Copy link
Member

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't see anyone else complain, so I guess we can merge it and work to maintain it now.

@madolson madolson added the release-notes This issue should get a line item in the release notes label Nov 7, 2024
Copy link
Member

@PingXie PingXie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, eifrah-aws! Appreciate it


Other options supported by Valkey's `CMake` build system:

## Special build flags
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking this PR but can we also document the default settings for these flags?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be fixed as part of this small PR: #1276

@@ -0,0 +1,44 @@
set(CPACK_PACKAGE_NAME "valkey")

valkey_parse_version(CPACK_PACKAGE_VERSION_MAJOR CPACK_PACKAGE_VERSION_MINOR CPACK_PACKAGE_VERSION_PATCH)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we consider a custom versioning scheme for the unstable branch such as ${CPACK_PACKAGE_NAME}-unstable-${CMAKE_SYSTEM_NAME}? It will look like ${CPACK_PACKAGE_NAME}-255.255.255-${CMAKE_SYSTEM_NAME} otherwise. I am a bit more in favor of explicitness. Separate PR is totally fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for ${CPACK_PACKAGE_NAME}-unstable-${CMAKE_SYSTEM_NAME} for unstable branch

@madolson madolson merged commit 07b3e7a into valkey-io:unstable Nov 8, 2024
57 checks passed
@eifrah-aws eifrah-aws deleted the cmake branch November 8, 2024 05:04
proost pushed a commit to proost/valkey that referenced this pull request Nov 9, 2024
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 <[email protected]>
zvi-code pushed a commit to zvi-code/valkey-z that referenced this pull request Nov 13, 2024
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 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major-decision-approved Major decision approved by TSC team release-notes This issue should get a line item in the release notes run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants