Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,32 @@ jobs:
- name: Test
run: ctest --test-dir build --output-on-failure --timeout 600

system-sodium:
name: ubuntu-24.04 system sodium
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- name: Install libsodium
run: sudo apt-get update && sudo apt-get install -y libsodium-dev

- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DNETCODE_SYSTEM_SODIUM=ON -DBUILD_SHARED_LIBS=ON

- name: Build
run: cmake --build build --parallel

- name: Test
run: ctest --test-dir build --output-on-failure --timeout 600

- name: Install
run: |
cmake --install build --prefix stage
test -f stage/include/netcode.h
test -f stage/lib/libnetcode.so || test -L stage/lib/libnetcode.so
echo "install layout ok"

sanitizers:
name: sanitizers (asan+ubsan)
runs-on: ubuntu-24.04
Expand Down
14 changes: 14 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ Then you can run binaries like this:

For a debug build, use `-DCMAKE_BUILD_TYPE=Debug` and a separate build directory, e.g. `-B build-debug`.

## Installing, shared libraries, and system libsodium

By default netcode builds as a static library against the vendored libsodium subset, and nothing needs to be installed. For packaging (e.g. homebrew), three options change that:

cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DNETCODE_SYSTEM_SODIUM=ON \
-DBUILD_SHARED_LIBS=ON
cmake --build build --parallel
cmake --install build --prefix /some/prefix

- `NETCODE_SYSTEM_SODIUM=ON` links the system libsodium instead of the vendored copy (they are interchangeable — the vendored subset is a byte-identical slice of upstream).
- `BUILD_SHARED_LIBS=ON` builds `libnetcode` as a shared library.
- `cmake --install` installs `netcode.h` and the library (`NETCODE_INSTALL=OFF` disables the install target, e.g. when embedding netcode as a subproject).

## Sanitizers and fuzzing

To build everything with AddressSanitizer and UndefinedBehaviorSanitizer, configure with `-DNETCODE_SANITIZE=ON` and run the tests as usual:
Expand Down
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ independent implementations (C#, Go, Rust, TypeScript).
`netcode_test` target compiles netcode.c into itself with `NETCODE_ENABLE_TESTS`, so it
links only sodium. `-DNETCODE_SANITIZE=ON` adds ASan+UBSan (sodium gets ASan only);
`-DNETCODE_FUZZ=ON` builds the `fuzz/` harnesses (libFuzzer where available, else a
standalone file replayer). CI (`.github/workflows/ci.yml`) builds and tests Debug +
standalone file replayer). For packaging: `-DNETCODE_SYSTEM_SODIUM=ON` links the
system libsodium instead of the vendored copy, `-DBUILD_SHARED_LIBS=ON` builds
libnetcode shared, and `cmake --install` installs netcode.h + the library
(this is the homebrew configuration, covered by a CI leg). CI (`.github/workflows/ci.yml`) builds and tests Debug +
Release on Linux x64, Linux arm64, macOS Apple Silicon, and Windows x64 (MSVC + a
MinGW leg), plus a Linux ASan+UBSan leg and a bounded smoke-fuzz leg. A separate
nightly workflow (`.github/workflows/scheduled.yml`) runs deep fuzzing with an
Expand Down
76 changes: 54 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)

project(netcode LANGUAGES C CXX)
project(netcode VERSION 1.3.1 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
Expand Down Expand Up @@ -32,6 +32,8 @@ endif()

option(NETCODE_SANITIZE "Build with AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
option(NETCODE_FUZZ "Build the fuzz targets" OFF)
option(NETCODE_SYSTEM_SODIUM "Link against the system libsodium instead of the vendored copy" OFF)
option(NETCODE_INSTALL "Generate the install target (netcode.h and the netcode library)" ON)

# sanitizers apply to the whole build. the vendored crypto is exempted from UBSan
# below (third-party SIMD code uses intentional type punning / unaligned access that
Expand All @@ -46,34 +48,66 @@ if(NETCODE_SANITIZE)
endif()
endif()

# vendored libsodium subset, amalgamated into a single header + source pair.
# see sodium/NOTES.md for how it is generated and validated.

add_library(sodium STATIC sodium/sodium.c sodium/sodium.h)
target_include_directories(sodium PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/sodium)
if(NOT MSVC)
target_compile_options(sodium PRIVATE
-Wall -Wextra
-Wno-unused-parameter
-Wno-unused-function
-Wno-unknown-pragmas
-Wno-unused-variable
-Wno-type-limits)
if(NETCODE_SANITIZE)
target_compile_options(sodium PRIVATE -fno-sanitize=undefined)
if(NETCODE_SYSTEM_SODIUM)

# link the system libsodium (e.g. homebrew or apt) instead of the vendored copy.
# the vendored subset is a byte-identical slice of upstream, so the two are
# interchangeable. package managers prefer this so their libsodium supplies the
# crypto and receives security updates.

find_path(NETCODE_SODIUM_INCLUDE_DIR sodium.h REQUIRED)
find_library(NETCODE_SODIUM_LIBRARY sodium REQUIRED)

add_library(sodium INTERFACE)
target_include_directories(sodium INTERFACE ${NETCODE_SODIUM_INCLUDE_DIR})
target_link_libraries(sodium INTERFACE ${NETCODE_SODIUM_LIBRARY})

else()

# vendored libsodium subset, amalgamated into a single header + source pair.
# see sodium/NOTES.md for how it is generated and validated.

add_library(sodium STATIC sodium/sodium.c sodium/sodium.h)
target_include_directories(sodium PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/sodium)
set_target_properties(sodium PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(NOT MSVC)
target_compile_options(sodium PRIVATE
-Wall -Wextra
-Wno-unused-parameter
-Wno-unused-function
-Wno-unknown-pragmas
-Wno-unused-variable
-Wno-type-limits)
if(NETCODE_SANITIZE)
target_compile_options(sodium PRIVATE -fno-sanitize=undefined)
endif()
endif()

endif()

# the netcode library
# the netcode library. static by default; -DBUILD_SHARED_LIBS=ON builds it shared
# (the vendored sodium objects are position independent, so they fold in either way)

add_library(netcode STATIC netcode.c netcode.h)
add_library(netcode netcode.c netcode.h)
target_include_directories(netcode PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(netcode PRIVATE ${NETCODE_WARNINGS})
target_link_libraries(netcode PUBLIC sodium)
set_target_properties(netcode PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
if(WIN32)
target_link_libraries(netcode PUBLIC ws2_32 iphlpapi)
endif()

if(NETCODE_INSTALL)
include(GNUInstallDirs)
install(TARGETS netcode
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES netcode.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()

# examples and long-running harnesses

foreach(example client server client_server soak profile)
Expand Down Expand Up @@ -118,10 +152,8 @@ if(NETCODE_FUZZ)

foreach(fuzzer fuzz_read_packet fuzz_connect_token fuzz_parse_address)
add_executable(${fuzzer} fuzz/${fuzzer}.c)
target_include_directories(${fuzzer} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/sodium)
target_link_libraries(${fuzzer} PRIVATE sodium)
target_include_directories(${fuzzer} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(${fuzzer} PRIVATE sodium) # provides the sodium include dir, vendored or system
if(WIN32)
target_link_libraries(${fuzzer} PRIVATE ws2_32 iphlpapi)
endif()
Expand Down
Loading