diff options
Diffstat (limited to 'docs/handbook/libnbtplusplus/building.md')
| -rw-r--r-- | docs/handbook/libnbtplusplus/building.md | 401 |
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. |
