summaryrefslogtreecommitdiff
path: root/docs/handbook/libnbtplusplus/building.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/handbook/libnbtplusplus/building.md')
-rw-r--r--docs/handbook/libnbtplusplus/building.md401
1 files changed, 401 insertions, 0 deletions
diff --git a/docs/handbook/libnbtplusplus/building.md b/docs/handbook/libnbtplusplus/building.md
new file mode 100644
index 0000000000..61bd5a57a3
--- /dev/null
+++ b/docs/handbook/libnbtplusplus/building.md
@@ -0,0 +1,401 @@
+# Building libnbt++
+
+## Build System
+
+libnbt++ uses **CMake** (minimum version 3.15) as its build system. The root `CMakeLists.txt` defines the project, its options, source files, dependencies, and installation rules.
+
+---
+
+## Prerequisites
+
+### Required
+
+- **C++11 compatible compiler**: GCC 4.8+, Clang 3.3+, or MSVC 2015+
+- **CMake**: Version 3.15 or later
+
+### Optional
+
+- **zlib**: Required for compressed NBT support (gzip/deflate). Enabled by default.
+- **CxxTest**: Required for building and running unit tests. Must be discoverable by CMake's `find_package(CxxTest)`.
+- **objcopy**: Required for test data embedding on Linux (binary test files are converted to object files via `objcopy`).
+
+---
+
+## CMake Options
+
+The following options are available when configuring the project:
+
+| Option | Default | Description |
+|-------------------|---------|----------------------------------------------------------|
+| `NBT_BUILD_SHARED` | `OFF` | Build as a shared (dynamic) library instead of static |
+| `NBT_USE_ZLIB` | `ON` | Enable zlib compression support |
+| `NBT_BUILD_TESTS` | `ON` | Build the unit test executables |
+| `NBT_NAME` | `nbt++` | Override the output library name |
+| `NBT_DEST_DIR` | (unset) | If set, enables install target with specified destination|
+
+### Option Details
+
+#### NBT_BUILD_SHARED
+
+When `NBT_BUILD_SHARED=OFF` (default), a static library (`libnbt++.a` or `nbt++.lib`) is produced.
+
+When `NBT_BUILD_SHARED=ON`, a shared library is produced. In this case, CMake is configured to:
+- Set `CXX_VISIBILITY_PRESET` to `hidden`
+- Set `VISIBILITY_INLINES_HIDDEN` to `1`
+- Use the `NBT_EXPORT` macro (generated by `generate_export_header()`) to control symbol visibility
+
+This means only classes and functions explicitly marked with `NBT_EXPORT` are exported from the shared library.
+
+#### NBT_USE_ZLIB
+
+When enabled (default), the build:
+1. Calls `find_package(ZLIB REQUIRED)` to locate the system zlib
+2. Adds the zlib source files to the library: `src/io/izlibstream.cpp` and `src/io/ozlibstream.cpp`
+3. Defines the preprocessor macro `NBT_HAVE_ZLIB`
+4. Links the library against `ZLIB::ZLIB`
+
+The zlib headers (`include/io/izlibstream.h`, `include/io/ozlibstream.h`, `include/io/zlib_streambuf.h`) include `<zlib.h>` directly. If zlib is not available, these headers cannot be included.
+
+#### NBT_NAME
+
+Allows overriding the library target name. By default, the target is called `nbt++`, producing `libnbt++.a`. Setting `NBT_NAME=mynbt` would produce `libmynbt.a`:
+
+```cmake
+cmake -DNBT_NAME=mynbt ..
+```
+
+---
+
+## Source Files
+
+### Core Library Sources
+
+The `NBT_SOURCES` variable lists all non-zlib source files:
+
+```cmake
+set(NBT_SOURCES
+ src/endian_str.cpp
+ src/tag.cpp
+ src/tag_compound.cpp
+ src/tag_list.cpp
+ src/tag_string.cpp
+ src/value.cpp
+ src/value_initializer.cpp
+ src/io/stream_reader.cpp
+ src/io/stream_writer.cpp
+ src/text/json_formatter.cpp)
+```
+
+### Zlib Sources (Conditional)
+
+Only added when `NBT_USE_ZLIB=ON`:
+
+```cmake
+set(NBT_SOURCES_Z
+ src/io/izlibstream.cpp
+ src/io/ozlibstream.cpp)
+```
+
+---
+
+## Building Step by Step
+
+### 1. Clone and Navigate
+
+```bash
+git clone https://github.com/Project-Tick/Project-Tick.git
+cd Project-Tick/libnbtplusplus/
+```
+
+### 2. Create Build Directory
+
+```bash
+mkdir build
+cd build
+```
+
+### 3. Configure
+
+#### Default (static library, with zlib, with tests):
+
+```bash
+cmake ..
+```
+
+#### Static library, no zlib, no tests:
+
+```bash
+cmake -DNBT_USE_ZLIB=OFF -DNBT_BUILD_TESTS=OFF ..
+```
+
+#### Shared library:
+
+```bash
+cmake -DNBT_BUILD_SHARED=ON ..
+```
+
+#### Custom library name:
+
+```bash
+cmake -DNBT_NAME=nbtpp ..
+```
+
+#### Specify a different compiler:
+
+```bash
+cmake -DCMAKE_CXX_COMPILER=clang++ ..
+```
+
+#### With install destination:
+
+```bash
+cmake -DNBT_DEST_DIR=/usr/local/lib ..
+```
+
+### 4. Build
+
+```bash
+cmake --build .
+```
+
+Or with make directly:
+
+```bash
+make -j$(nproc)
+```
+
+### 5. Run Tests (if enabled)
+
+```bash
+ctest --output-on-failure
+```
+
+### 6. Install (optional)
+
+Only works if `NBT_DEST_DIR` was set:
+
+```bash
+cmake --install .
+```
+
+---
+
+## Integration into Other Projects
+
+### As a CMake Subdirectory
+
+The most common integration method is adding libnbt++ as a subdirectory in your project:
+
+```cmake
+# In your project's CMakeLists.txt
+
+# Optional: disable tests for the dependency
+set(NBT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
+
+add_subdirectory(libnbtplusplus)
+
+add_executable(myapp main.cpp)
+target_link_libraries(myapp nbt++)
+```
+
+The `target_include_directories` in libnbt++'s CMakeLists already uses `PUBLIC`, so include paths propagate automatically:
+
+```cmake
+target_include_directories(${NBT_NAME} PUBLIC include ${CMAKE_CURRENT_BINARY_DIR})
+```
+
+The `${CMAKE_CURRENT_BINARY_DIR}` is included because `generate_export_header()` creates `nbt_export.h` in the build directory.
+
+### Include Paths
+
+After linking against the `nbt++` target, your code can include:
+
+```cpp
+#include <nbt_tags.h> // All tag types
+#include <io/stream_reader.h> // Reading
+#include <io/stream_writer.h> // Writing
+#include <io/izlibstream.h> // Decompression (if NBT_USE_ZLIB)
+#include <io/ozlibstream.h> // Compression (if NBT_USE_ZLIB)
+```
+
+### Manually (without CMake)
+
+If not using CMake, you need to:
+
+1. Add `libnbtplusplus/include/` to your include path
+2. Compile all `.cpp` files in `src/` (and `src/io/`, `src/text/`)
+3. If using zlib: add `-DNBT_HAVE_ZLIB`, link against `-lz`
+4. Create your own `nbt_export.h` or define `NBT_EXPORT` as empty:
+
+```cpp
+// nbt_export.h — manual version for static builds
+#ifndef NBT_EXPORT_H
+#define NBT_EXPORT_H
+#define NBT_EXPORT
+#endif
+```
+
+5. Set C++ standard to C++11 or later: `-std=c++11`
+
+---
+
+## The nbt_export.h Header
+
+This header is **auto-generated** by CMake's `generate_export_header()` command at configure time. It is placed in `${CMAKE_CURRENT_BINARY_DIR}` and defines:
+
+- `NBT_EXPORT` — marks symbols for export from shared libraries
+- `NBT_NO_EXPORT` — marks symbols as hidden
+
+For static builds, `NBT_EXPORT` typically expands to nothing. For shared builds, it maps to compiler-specific visibility attributes:
+
+```cpp
+// Example generated content (GCC/Clang)
+#define NBT_EXPORT __attribute__((visibility("default")))
+#define NBT_NO_EXPORT __attribute__((visibility("hidden")))
+```
+
+The binary directory is added to include paths so all source files can `#include "nbt_export.h"`.
+
+---
+
+## C++ Standard
+
+The library enforces C++11 via:
+
+```cmake
+set_property(TARGET ${NBT_NAME} PROPERTY CXX_STANDARD 11)
+```
+
+This does not set `CXX_STANDARD_REQUIRED`, so CMake may use a higher standard if the compiler defaults to one. The code is compatible with C++11 through C++20+.
+
+---
+
+## Compile-Time Assertions
+
+The library includes several `static_assert` checks to ensure platform compatibility:
+
+In `src/tag.cpp`:
+```cpp
+static_assert(
+ std::numeric_limits<float>::is_iec559 &&
+ std::numeric_limits<double>::is_iec559,
+ "The floating point values for NBT must conform to IEC 559/IEEE 754");
+```
+
+In `src/endian_str.cpp`:
+```cpp
+static_assert(CHAR_BIT == 8, "Assuming that a byte has 8 bits");
+static_assert(sizeof(float) == 4, "Assuming that a float is 4 byte long");
+static_assert(sizeof(double) == 8, "Assuming that a double is 8 byte long");
+```
+
+These ensure that the platform's floating-point representation matches the NBT format's IEEE 754 requirement.
+
+---
+
+## Platform-Specific Notes
+
+### Linux
+
+Tests are only supported on `x86_64` and `i686` architectures due to the use of `objcopy` for binary test data embedding:
+
+```cmake
+if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64)
+ set(OBJCOPY_TARGET "elf64-x86-64")
+ set(OBJCOPY_ARCH "x86_64")
+elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686)
+ set(OBJCOPY_TARGET "elf32-i386")
+ set(OBJCOPY_ARCH "i386")
+else()
+ message(AUTHOR_WARNING "This is not a platform that would support testing nbt++")
+ return()
+endif()
+```
+
+### macOS / Windows
+
+The core library compiles on any platform with a C++11 compiler and optionally zlib. However, the test suite uses Linux-specific `objcopy` commands and may not build on non-Linux platforms without modifications.
+
+---
+
+## Shared Library Visibility
+
+When building as a shared library (`NBT_BUILD_SHARED=ON`), the CMake configuration applies strict visibility rules:
+
+```cmake
+if(${BUILD_SHARED_LIBS})
+ set_target_properties(${NBT_NAME} PROPERTIES
+ CXX_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN 1)
+endif()
+```
+
+This means:
+- All symbols are hidden by default
+- Inline functions are also hidden
+- Only symbols marked `NBT_EXPORT` are exported
+
+This reduces binary size and prevents symbol collision when multiple libraries are loaded.
+
+---
+
+## Typical Build Output
+
+After a successful build with all options enabled, you will have:
+
+```
+build/
+├── libnbt++.a # The static library (or libnbt++.so for shared)
+├── nbt_export.h # Generated export header
+└── test/
+ ├── nbttest # Core tag tests
+ ├── endian_str_test # Endianness tests
+ ├── read_test # Reading tests
+ ├── write_test # Writing tests
+ ├── zlibstream_test # Compression tests (if NBT_USE_ZLIB)
+ ├── format_test # JSON formatter test
+ └── test_value # Value assignment tests
+```
+
+---
+
+## Troubleshooting
+
+### "Could not find ZLIB"
+
+Install the zlib development package:
+
+```bash
+# Debian/Ubuntu
+sudo apt install zlib1g-dev
+
+# Fedora
+sudo dnf install zlib-devel
+
+# macOS
+brew install zlib
+```
+
+Or disable zlib: `cmake -DNBT_USE_ZLIB=OFF ..`
+
+### "Could not find CxxTest"
+
+Install CxxTest:
+
+```bash
+# Debian/Ubuntu
+sudo apt install cxxtest
+
+# macOS
+brew install cxxtest
+```
+
+Or disable tests: `cmake -DNBT_BUILD_TESTS=OFF ..`
+
+### "nbt_export.h not found"
+
+This file is generated at configure time. Make sure you've run `cmake ..` (the configure step) before building. If building manually without CMake, create a minimal `nbt_export.h` as described in the manual integration section above.
+
+### Linking Errors with Shared Builds
+
+If you see undefined symbol errors when linking against the shared library, ensure your code includes the correct headers and that `nbt_export.h` was generated during the shared build configuration. Verify `NBT_EXPORT` expands to the visibility attribute.