From abfccf6b5c15caefd7be64f17e64c33a606ed5e0 Mon Sep 17 00:00:00 2001 From: fef Date: Mon, 26 Jul 2021 22:40:50 +0200 Subject: [PATCH] doc: refactor and normalize comments --- CMakeLists.txt | 2 ++ doc/CMakeLists.txt | 57 +++++++++++++++++++++++++++++++++++++++++++ doc/Doxyfile.in | 2 +- include/neo.h | 2 +- include/neo/_error.h | 12 ++++++--- include/neo/_nalloc.h | 2 +- include/neo/_nbuf.h | 18 ++++++++++++-- include/neo/_nref.h | 28 +++++++++++++++++++++ include/neo/_nstr.h | 28 +++++++++++++++------ include/neo/_stddef.h | 46 ++++++++++++++++++++++++++++------ include/neo/_types.h | 22 ++++++++++++++--- include/neo/hashtab.h | 7 +++--- include/neo/list.h | 21 +++++++++------- include/neo/utf.h | 28 ++++++++++++--------- src/CMakeLists.txt | 44 --------------------------------- 15 files changed, 224 insertions(+), 95 deletions(-) create mode 100644 doc/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 64348be..0c58744 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ add_subdirectory(src) add_subdirectory(demo) +add_subdirectory(doc) + option(BUILD_TESTING "Build tests" ON) if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR NEO_BUILD_TESTING) AND BUILD_TESTING) enable_testing() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..ed58266 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,57 @@ +# See the end of this file for copyright and license terms. + +option(BUILD_DOCS "Build documentation" OFF) +option(BUILD_DOCS_HTML "Build documentation in HTML format" ON) +option(BUILD_DOCS_LATEX "Build documentation in LaTEX format" OFF) +option(BUILD_DOCS_RTF "Build documentation in Rich Text Format" OFF) +option(BUILD_DOCS_XML "Build documentation in XML format" OFF) + +if(BUILD_DOCS) + find_package(Doxygen REQUIRED) + add_custom_target(neo_docs ALL + DEPENDS neo + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building documentation" + VERBATIM + ) + + set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) + set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) + + if(BUILD_DOCS_HTML) + set(neo_BUILD_DOCS_HTML YES) + else() + set(neo_BUILD_DOCS_HTML NO) + endif() + + if(BUILD_DOCS_LATEX) + set(neo_BUILD_DOCS_LATEX YES) + else() + set(neo_BUILD_DOCS_LATEX NO) + endif() + + if(BUILD_DOCS_RTF) + set(neo_BUILD_DOCS_RTF YES) + else() + set(neo_BUILD_DOCS_RTF NO) + endif() + + if(BUILD_DOCS_XML) + set(neo_BUILD_DOCS_XML YES) + else() + set(neo_BUILD_DOCS_XML NO) + endif() +endif() + +# This file is part of libneo. +# Copyright (c) 2021 Fefie . +# +# libneo is non-violent software: you may only use, redistribute, +# and/or modify it under the terms of the CNPLv6+ as found in +# the LICENSE file in the source code root directory or at +# . +# +# libneo comes with ABSOLUTELY NO WARRANTY, to the extent +# permitted by applicable law. See the CNPLv6+ for details. diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index c2dfd57..98f12e2 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/../doc/ +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and diff --git a/include/neo.h b/include/neo.h index 9d9f79f..d5a3810 100644 --- a/include/neo.h +++ b/include/neo.h @@ -1,7 +1,7 @@ /* See the end of this file for copyright and license terms. */ /** - * @file Main libneo header file providing core functionalities. + * @brief Main libneo header file providing core functionalities. */ #pragma once diff --git a/include/neo/_error.h b/include/neo/_error.h index 1834d5b..1c35b31 100644 --- a/include/neo/_error.h +++ b/include/neo/_error.h @@ -28,9 +28,9 @@ void yeet(error *err, u32 number, const char *restrict fmt, ...) __attribute__(( __format__(printf, 3, 4) )); /** - * Indicate an operation has completed successfully. + * @brief Indicate an operation has completed successfully. * Functions accepting an `error` pointer must call either `yeet()` or `neat()`, - * or the begavior is undefined. + * or the behavior is undefined. * * @param err Error object */ @@ -55,10 +55,16 @@ void errput(error *err); * * Execute the expression after this macro call if the error pointed to * by `err` is an actual error, i.e. it has been `yeet()`ed to. - * Resources for the error must be released using `nput()`. + * Resources for the error must be released using `errput()`. */ #define ncatch(err) if ((err) != nil && (err)->_number != 0) #ifndef __cplusplus + /** + * @brief Catch an error. + * + * This is just a wrapper intended to piss off C++ developers, and thus + * should be used instead of `ncatch()` wherever possible. + */ # define catch(err) ncatch(err) #endif diff --git a/include/neo/_nalloc.h b/include/neo/_nalloc.h index 8a50e2d..44b733c 100644 --- a/include/neo/_nalloc.h +++ b/include/neo/_nalloc.h @@ -19,7 +19,7 @@ void nfree(void *ptr); /** - * Allocate `size` bytes of memory and return a pointer to the memory region. + * @brief Allocate `size` bytes of memory and return a pointer to the memory region. * The memory is *not* initialized; use `nzalloc()` if you want it to be. * If `size` is 0, the allocation fails. * If the allocation fails, the error is set and `nil` is returned. diff --git a/include/neo/_nbuf.h b/include/neo/_nbuf.h index 9886b5d..9aa91aa 100644 --- a/include/neo/_nbuf.h +++ b/include/neo/_nbuf.h @@ -91,6 +91,12 @@ nbuf_t *nbuf_clone(nbuf_t *buf, error *err); __byte; \ }) +/** + * @brief Iterate over every byte in a buffer. + * + * @param cursor A `const u8 *` to be used as an iteration cursor + * @param buf `nbuf_t *` to iterate over + */ #define nbuf_foreach(cursor, buf) \ for (cursor = &buf->_data[0]; \ cursor != &buf->_data[nlen(buf)]; \ @@ -100,8 +106,8 @@ nbuf_t *nbuf_clone(nbuf_t *buf, error *err); * @brief Compare two buffers. * * If the first buffer is found to be greater than the second one, the return - * value is greater than 0. - * If the two buffers are equal, the return value is zero. + * value is greater than 0.\n + * If the two buffers are equal, the return value is zero.\n * If the first buffer is found to be less than the second one, the return * value is less than 0. * @@ -114,6 +120,14 @@ nbuf_t *nbuf_clone(nbuf_t *buf, error *err); */ int nbuf_cmp(const nbuf_t *buf1, const nbuf_t *buf2, error *err); +/** + * @brief Determine whether two buffers are equal. + * + * @param buf1 First `nbuf_t *` to compare + * @param buf2 Second `nbuf_t *` to compare + * @param err Error pointer + * @returns `true` if the two buffers are found to be equal, `false` if not + */ #define nbuf_eq(buf1, buf2, err) ( (bool)(nbuf_cmp(buf1, buf2, err) == 0) ) /** @} */ diff --git a/include/neo/_nref.h b/include/neo/_nref.h index 49fa849..3daf392 100644 --- a/include/neo/_nref.h +++ b/include/neo/_nref.h @@ -55,6 +55,34 @@ int _neo_nput(struct _neo_nref *ref); ptr = nil; \ }) +/** + * @brief Borrow a refcounted structure. + * + * Increment the refcounter of a structure embedding `NREF_FIELD` and return + * a pointer to its `nref_t` field so that it can be stored in your own struct + * that depends on its existence. + * + * The borrowed structure is guaranteed to not be destroyed before you call + * `unborrow()` (unless you make the error of calling `nput()` ) + * + * @param ptr Pointer to the refcounted entity to borrow + * @returns An `nref_t *` that must be passed to `unborrow()` when the borrow + * is no longer used + */ +#define borrow(ptr) ({ \ + nref_t *__nref = &(ptr)->__neo_nref; \ + _neo_nget(__nref); \ + __nref; \ +}) + +/** + * @brief Decrement the reference counter of a borrowed structure after usage. + * Call this in the borrowing structure's teardown routine. + * + * @param nref The `nref_t *` returned by `borrow()` + */ +#define unborrow(nref) ((void)_neo_nput(nref)) + /** * @brief Return the current reference count of a structure embedding `NREF_FIELD`. * You usually shouldn't need this though. diff --git a/include/neo/_nstr.h b/include/neo/_nstr.h index 80f4d74..6cbcb9a 100644 --- a/include/neo/_nstr.h +++ b/include/neo/_nstr.h @@ -13,6 +13,7 @@ * * Changing this might require also changing the linker script because of * alignment requirements. + * @private */ struct _neo_nstr_init_info { nstr_t **dest; @@ -39,20 +40,31 @@ struct _neo_nstr_init_info { #define nstr_raw(nstr) ((nstr)->_data) /** - * @brief Statically define a neo string (file scope only). + * @brief Statically initialize a neo string (file scope only). + * + * The string will be initialized before `main` is called. + * + * @param name Name of the (already declared) `nstr_t *` to initialize + * @param content A `const char *` with the contents of the string + */ +#define NSTR_INIT(name, content) \ + __neo_section(.data.__neo.nstr_array) \ + struct _neo_nstr_init_info __neo_nstr_init_info_##name = { \ + .dest = &name, \ + .data = content, \ + } + +/** + * @brief Statically declare and define a neo string (file scope only). * * The string will be initialized before `main` is called. * * @param name Name of the `nstr_t *` variable to be declared * @param content A `const char *` with the contents of the string */ -#define NSTR_DEFINE(name, content) \ - nstr_t *name = nil; \ - __neo_section(.data.__neo.nstr_array) \ - struct _neo_nstr_init_info __neo_nstr_init_info_##name = { \ - .dest = &name, \ - .data = content, \ - } +#define NSTR_DEFINE(name, content) \ + nstr_t *name = nil; \ + NSTR_INIT(name, content) /** * @brief Copy a regular C string to a neo string. diff --git a/include/neo/_stddef.h b/include/neo/_stddef.h index 358835b..8d5e9c5 100644 --- a/include/neo/_stddef.h +++ b/include/neo/_stddef.h @@ -13,34 +13,66 @@ #ifdef __cplusplus # define nil nullptr #else + /** @brief Null pointer. */ # define nil ((void *)0) #endif #ifndef offsetof + /** + * @brief Get the byte offset of a member within a struct. + * + * @param type Type of the structure + * @param member Name of the member within the struct + * @returns The byte offset of `member` within `type` + */ # define offsetof(type, member) __builtin_offsetof(type, member) #endif #ifndef typeof + /** + * @brief Get the type an expression evaluates to (for generic macros). + * + * @param expr Expression to get the type of + * @returns The type, can be used for casting or declarations + */ # define typeof(expr) __typeof(expr) #endif -/** @brief Get the absolute (non negative) value of an integer */ -#define nabs(n) ({ \ - /* n is an expression, not a variable, evaluate it only once */ \ - typeof(n) __neo_local_n = (n); \ - __neo_local_n < 0 ? -__neo_local_n : __neo_local_n; \ +/** + * @brief Get the absolute (non negative) value of an integer. + * + * @param n The integer + * @returns The absolute value + */ +#define nabs(n) ({ \ + typeof(n) __n = (n); \ + __n < 0 ? -__n : __n; \ }) +/** + * @brief Get the maximum value of two integer expressions. + * + * @param x1 First expression + * @param x2 Second expression + * @returns The bigger value + */ #define nmax(x1, x2) ({ \ typeof(x1) __x1 = (x1); \ typeof(x2) __x2 = (x2); \ __x1 > __x2 ? __x1 : __x2; \ }) +/** + * @brief Get the minimum value of two integer expressions. + * + * @param x1 First expression + * @param x2 Second expression + * @returns The smaller value + */ #define nmin(x1, x2) ({ \ typeof(x1) __x1 = (x1); \ typeof(x2) __x2 = (x2); \ - __x1 < __x2 ? __x1 : x2; \ + __x1 < __x2 ? __x1 : __x2; \ }) /** @@ -54,7 +86,7 @@ */ #define nlen(thing) ((thing)->__neo_nlen) -/* @} */ +/** @} */ /* * This file is part of libneo. diff --git a/include/neo/_types.h b/include/neo/_types.h index b782ea0..f933c40 100644 --- a/include/neo/_types.h +++ b/include/neo/_types.h @@ -10,26 +10,38 @@ * @{ */ +/** @brief Signed 8-bit integer. */ typedef __INT8_TYPE__ i8; +/** @brief Signed 16-bit integer. */ typedef __INT16_TYPE__ i16; +/** @brief Signed 32-bit integer. */ typedef __INT32_TYPE__ i32; +/** @brief Signed 64-bit integer. */ typedef __INT64_TYPE__ i64; +/** @brief Unsigned 8-bit integer. */ typedef __UINT8_TYPE__ u8; +/** @brief Alias for @a `u8`. */ typedef __UINT8_TYPE__ byte; +/** @brief Unsigned 16-bit integer. */ typedef __UINT16_TYPE__ u16; +/** @brief Unsigned 32-bit integer. */ typedef __UINT32_TYPE__ u32; +/** @brief Unsigned 64-bit integer. */ typedef __UINT64_TYPE__ u64; +/** @brief Platform-dependent unsigned integer for storing sizes. */ typedef __SIZE_TYPE__ usize; +/** @brief Platform-dependent signed integer for storing sizes. */ typedef __PTRDIFF_TYPE__ isize; -/** @brief A single Unicode character (32 bits) */ +/** @brief A single Unicode character (32 bits). */ typedef u32 nchar; +/** @brief Single precision (32-bit) floating-point number. */ typedef float f32; +/** @brief Double precision (64-bit) floating-point number. */ typedef double f64; -typedef long double f128; /** @} */ @@ -47,7 +59,7 @@ typedef long double f128; /** * @brief Declare a length field in a structure. - * This makes it compatible with the `nlen` macro. + * This makes it compatible with the `nlen()` macro. * * @param name field name, will be of type `usize` * @@ -59,6 +71,7 @@ typedef long double f128; volatile const usize __neo_nlen; \ } +/** @private */ struct _neo_nref { void (*_destroy)(void *); /** byte offset into the struct this is embedded in */ @@ -85,6 +98,7 @@ typedef struct _neo_nref nref_t; */ #define NREF_FIELD nref_t __neo_nref +/** @private */ struct _neo_nbuf { NREF_FIELD; NLEN_FIELD(_size); @@ -102,6 +116,7 @@ struct _neo_nbuf { */ typedef struct _neo_nbuf nbuf_t; +/** @private */ struct _neo_nstr { /* The *amount of Unicode code points*, NOT amount of bytes */ NLEN_FIELD(_len); @@ -122,6 +137,7 @@ struct _neo_nstr { */ typedef struct _neo_nstr nstr_t; +/** @private */ struct _neo_error { nstr_t *_message; u32 _number; diff --git a/include/neo/hashtab.h b/include/neo/hashtab.h index d2ed419..73a1240 100644 --- a/include/neo/hashtab.h +++ b/include/neo/hashtab.h @@ -1,9 +1,5 @@ /* See the end of this file for copyright and license terms. */ -/** - * @file Hashtable API - */ - #pragma once #ifdef __cplusplus @@ -15,12 +11,14 @@ extern "C" { #include "neo/_types.h" #include "neo/list.h" +/** @private */ struct _neo_hashtab_entry { listnode_t link; nbuf_t *key; void *val; }; +/** @private */ struct _neo_hashtab { NLEN_FIELD(_len); NREF_FIELD; @@ -119,6 +117,7 @@ void *hashtab_del(hashtab_t *table, nbuf_t *key, error *err); * the iteration stops if the return value is nonzero * @param extra Optional pointer that is passed as an extra argument to the * callback function + * @param err Error pointer * @returns The last return value of the callback, unless an error occurred */ int hashtab_foreach(hashtab_t *table, diff --git a/include/neo/list.h b/include/neo/list.h index 7a0ba89..d7a9d0b 100644 --- a/include/neo/list.h +++ b/include/neo/list.h @@ -1,9 +1,5 @@ /* See the end of this file for copyright and license terms. */ -/** - * @file List API - */ - #pragma once #ifdef __cplusplus @@ -15,6 +11,7 @@ extern "C" { struct _neo_list; +/** @private */ struct _neo_listnode { struct _neo_listnode *_next; struct _neo_listnode *_prev; @@ -27,6 +24,7 @@ struct _neo_listnode { */ typedef struct _neo_listnode listnode_t; +/** @private */ struct _neo_list { struct _neo_listnode _root; NLEN_FIELD(_len); @@ -46,6 +44,7 @@ typedef struct _neo_list list_t; * @param casted `struct *` that the @a `listnode_t *` was casted out to * @param list @a `list_t *` storing the root @a `listnode_t` * @param member Name of the @a `listnode_t` member embedded within the `struct *` + * @private */ #define _neo_list_is_root(casted, list, member) \ ( &(casted)->member == &(list)->_root ) @@ -55,15 +54,19 @@ typedef struct _neo_list list_t; * external compiler settings which my complain about calculating with void * */ +/** @private */ #define _neo_list_first(list, type, member) \ ((type *)( (u8 *)((list)->_root._next) - offsetof(type, member) )) +/** @private */ #define _neo_list_last(list, type, member) \ ((type *)( (u8 *)((list)->_root._prev) - offsetof(type, member) )) +/** @private */ #define _neo_list_next(current, member) \ ((typeof(current))( (u8 *)((current)->member._next) - offsetof(typeof(*(current)), member) )) +/** @private */ #define _neo_list_prev(current, member) \ ((typeof(current))( (u8 *)((current)->member._prev) - offsetof(typeof(*(current)), member) )) @@ -74,7 +77,7 @@ typedef struct _neo_list list_t; */ /** - * Initialize a list. + * @brief Initialize a list. * * @param list The list */ @@ -104,7 +107,7 @@ void list_del(listnode_t *node); void list_add_first(list_t *list, listnode_t *new_node); /** - * Insert a new node after the specified list node. + * @brief Insert a new node after the specified list node. * * @param pos List node to insert the new node after * @param new_node Node to insert after the specified position @@ -112,7 +115,7 @@ void list_add_first(list_t *list, listnode_t *new_node); void list_insert(listnode_t *pos, listnode_t *new_node); /** - * Insert a new node before the specified list node. + * @brief Insert a new node before the specified list node. * * @param pos List node to insert the new node before * @param new_node Node to insert before the specified position @@ -126,7 +129,7 @@ void list_insert_before(listnode_t *pos, listnode_t *new_node); * * @param cursor `type *` to use as a cursor * @param list `list_t *` to iterate over - * @param member Name of the `listnode_t` member embedded within \a `cursor` + * @param member Name of the `listnode_t` member embedded within `cursor` */ #define list_foreach(cursor, list, member) \ for (typeof(cursor) __tmp = _neo_list_next( \ @@ -143,7 +146,7 @@ void list_insert_before(listnode_t *pos, listnode_t *new_node); * * @param cursor `type *` to use as a cursor * @param list `list_t *` to iterate over - * @param member Name of the `listnode_t` member embedded within \a `cursor` + * @param member Name of the `listnode_t` member embedded within `cursor` */ #define list_foreach_reverse(cursor, list, member) \ for (typeof(cursor) __tmp = _neo_list_prev( \ diff --git a/include/neo/utf.h b/include/neo/utf.h index 6b658d5..2c715fc 100644 --- a/include/neo/utf.h +++ b/include/neo/utf.h @@ -1,7 +1,16 @@ /* See the end of this file for copyright and license terms. */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "neo/_toolchain.h" +#include "neo/_types.h" + /** - * @file Conversion utilities for raw UTF. + * @defgroup utf Raw UTF Handling * * Note that libneo strings already have native UTF-8 support, so you only * really need this if you explicitly need to deal with different encodings or @@ -12,17 +21,10 @@ * for them if the string contains a malformed UTF sequence. * * Believe me when i say you do not want to use these. + * + * @{ */ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "neo/_toolchain.h" -#include "neo/_types.h" - /** * @brief Check whether a NUL terminated string is valid UTF-8. * @@ -37,7 +39,7 @@ usize utf8_check(const char *restrict s, error *err); /** * @brief Check whether a NUL terminated string is valid UTF-8. - * At most `maxsize + 3` bytes are read (this function uses `utf8_to_nchr` internally). + * At most `maxsize + 3` bytes are read (this function uses `utf8_to_nchr()` internally). * * If a NUL terminator is encountered before `maxsize` bytes, reading stops * before the specified size. If the string contains any malformed code @@ -55,7 +57,7 @@ usize utf8_ncheck(const char *restrict s, usize maxsize, error *err); * @brief Compute the length of a raw UTF-8 encoded, NUL terminated string. * * The string is *not* checked for malformed code sequences, - * use `utf8_check` for that. + * use `utf8_check()` for that. * * @param s String to get the length of * @returns String length as in Unicode code points (not bytes), @@ -109,6 +111,8 @@ usize utf8_from_nchr(char *restrict dest, nchar c, error *err); */ usize utf8_to_nchr(nchar *c, const char *restrict utf8chr, error *err); +/** @} */ + #ifdef __cplusplus }; /* extern "C" */ #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b50394..cc11af7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,50 +17,6 @@ configure_file( ${CMAKE_BINARY_DIR}/include/neo/buildconfig.h ) -option(BUILD_DOCS "Build documentation" ON) -option(BUILD_DOCS_HTML "Build documentation in HTML format" ON) -option(BUILD_DOCS_LATEX "Build documentation in LaTEX format" OFF) -option(BUILD_DOCS_RTF "Build documentation in Rich Text Format" OFF) -option(BUILD_DOCS_XML "Build documentation in XML format" OFF) -if(BUILD_DOCS) - find_package(Doxygen REQUIRED) - set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/../doc/Doxyfile.in) - set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - - configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) - - if(BUILD_DOCS_HTML) - set(neo_BUILD_DOCS_HTML YES) - else() - set(neo_BUILD_DOCS_HTML NO) - endif() - - if(BUILD_DOCS_LATEX) - set(neo_BUILD_DOCS_LATEX YES) - else() - set(neo_BUILD_DOCS_LATEX NO) - endif() - - if(BUILD_DOCS_RTF) - set(neo_BUILD_DOCS_RTF YES) - else() - set(neo_BUILD_DOCS_RTF NO) - endif() - - if(BUILD_DOCS_XML) - set(neo_BUILD_DOCS_XML YES) - else() - set(neo_BUILD_DOCS_XML NO) - endif() - - add_custom_target(neo_docs ALL - COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Building documentation" - VERBATIM - ) -endif() - target_include_directories(neo PUBLIC ../include) target_include_directories(neo PRIVATE ./include