external-api-doc: introduce and improve documentation

This commit is contained in:
Yorick van Pelt 2023-07-30 16:36:51 +02:00 committed by José Luis Lafuente
parent 866558af34
commit b0741f7128
No known key found for this signature in database
GPG key ID: 8A3455EBE455489A
10 changed files with 225 additions and 20 deletions

View file

@ -25,7 +25,10 @@ makefiles = \
misc/zsh/local.mk \ misc/zsh/local.mk \
misc/systemd/local.mk \ misc/systemd/local.mk \
misc/launchd/local.mk \ misc/launchd/local.mk \
misc/upstart/local.mk misc/upstart/local.mk \
doc/manual/local.mk \
doc/internal-api/local.mk \
doc/external-api/local.mk
endif endif
ifeq ($(ENABLE_UNIT_TESTS), yes) ifeq ($(ENABLE_UNIT_TESTS), yes)

View file

@ -150,6 +150,11 @@ AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build th
ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD)
AC_SUBST(ENABLE_UNIT_TESTS) AC_SUBST(ENABLE_UNIT_TESTS)
# Build external API docs by default
AC_ARG_ENABLE(external_api_docs, AS_HELP_STRING([--enable-external-api-docs],[Build API docs for Nix's C interface]),
external_api_docs=$enableval, external_api_docs=yes)
AC_SUBST(external_api_docs)
AS_IF( AS_IF(
[test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"],
[AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])])

3
doc/external-api/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/doxygen.cfg
/html
/latex

View file

@ -0,0 +1,54 @@
# Doxyfile 1.9.5
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Nix"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @PACKAGE_VERSION@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Nix, the purely functional package manager; stable external interfaces"
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
# FIXME Make this list more maintainable somehow. We could maybe generate this
# in the Makefile, but we would need to change how `.in` files are preprocessed
# so they can expand variables despite configure variables.
INPUT = \
src/libutil \
src/libexpr \
src/libstore
FILE_PATTERNS = nix_api_*.h
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = @RAPIDCHECK_HEADERS@
EXCLUDE_PATTERNS = *_internal.h
GENERATE_TREEVIEW = YES
OPTIMIZE_OUTPUT_FOR_C = YES

19
doc/external-api/local.mk Normal file
View file

@ -0,0 +1,19 @@
.PHONY: external-api-html
ifeq ($(internal_api_docs), yes)
$(docdir)/external-api/html/index.html $(docdir)/external-api/latex: $(d)/doxygen.cfg
mkdir -p $(docdir)/external-api
{ cat $< ; echo "OUTPUT_DIRECTORY=$(docdir)/external-api" ; } | doxygen -
# Generate the HTML API docs for Nix's unstable internal interfaces.
external-api-html: $(docdir)/external-api/html/index.html
else
# Make a nicer error message
external-api-html:
@echo "Internal API docs are disabled. Configure with '--enable-external-api-docs', or avoid calling 'make external-api-html'."
@exit 1
endif

View file

@ -1,5 +1,26 @@
#ifndef NIX_API_EXPR_H #ifndef NIX_API_EXPR_H
#define NIX_API_EXPR_H #define NIX_API_EXPR_H
/** @defgroup libexpr libexpr
* @brief Bindings to the Nix evaluator
*
* Example (without error handling):
* @code{.c}
* int main() {
* nix_libexpr_init(NULL);
*
* Store* store = nix_store_open(NULL, "dummy", NULL);
* State* state = nix_state_create(NULL, NULL /* empty NIX_PATH */, store);
*Value *value = nix_alloc_value(NULL, state);
**nix_expr_eval_from_string(NULL, state, "builtins.nixVersion", ".", value);
*nix_value_force(NULL, state, value);
*printf("nix version: %s\n", nix_get_string(NULL, value));
**nix_gc_decref(NULL, value);
*nix_state_free(state);
*nix_store_unref(store);
*return 0;
*
}
*@endcode *@{* /
/** @file /** @file
* @brief Main entry for the libexpr C bindings * @brief Main entry for the libexpr C bindings
*/ */
@ -8,22 +29,25 @@
#include "nix_api_util.h" #include "nix_api_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// cffi start // cffi start
// Type definitions // Type definitions
/** /**
* @brief Represents a nix evaluator state. * @brief Represents a nix evaluator state.
* *
* Multiple can be created for multi-threaded * Multiple can be created for multi-threaded
* operation. * operation.
*/ * @struct State
typedef struct State State; // nix::EvalState */
typedef struct State State; // nix::EvalState
/** /**
* @brief Represents a nix value. * @brief Represents a nix value.
* *
* Owned by the GC. * Owned by the GC.
* @struct Value
* @see value_manip
*/ */
typedef void Value; // nix::Value typedef void Value; // nix::Value
@ -110,23 +134,36 @@ State *nix_state_create(nix_c_context *context, const char **searchPath,
*/ */
void nix_state_free(State *state); void nix_state_free(State *state);
/** @addtogroup GC
* @brief Reference counting and garbage collector operations
*
* Nix's evaluator uses a garbage collector. To ease C interop, we implement
* a reference counting scheme, where objects will be deallocated
* when there are no references from the Nix side, and the reference count kept
* by the C API reaches `0`.
*
* Functions returning a garbage-collected object will automatically increase
* the refcount for you. You should make sure to call `nix_gc_decref` when
* you're done.
* @{
*/
/** /**
* @brief Increase the GC refcount. * @brief Increase the GC refcount.
* *
* The nix C api keeps alive objects by refcounting. * The nix C api keeps alive objects by refcounting.
* When you're done with a refcounted pointer, call nix_gc_decref. * When you're done with a refcounted pointer, call nix_gc_decref.
* *
* Does not fail * @param[out] context Optional, stores error information
*
* @param[in] object The object to keep alive * @param[in] object The object to keep alive
*/ */
nix_err nix_gc_incref(nix_c_context *, const void *); nix_err nix_gc_incref(nix_c_context *context, const void *object);
/** /**
* @brief Decrease the GC refcount * @brief Decrease the GC refcount
* *
* @param[out] context Optional, stores error information
* @param[in] object The object to stop referencing * @param[in] object The object to stop referencing
*/ */
nix_err nix_gc_decref(nix_c_context *, const void *); nix_err nix_gc_decref(nix_c_context *context, const void *object);
/** /**
* @brief Trigger the garbage collector manually * @brief Trigger the garbage collector manually
@ -147,9 +184,12 @@ void nix_gc_now();
void nix_gc_register_finalizer(void *obj, void *cd, void nix_gc_register_finalizer(void *obj, void *cd,
void (*finalizer)(void *obj, void *cd)); void (*finalizer)(void *obj, void *cd));
/** @} */
// cffi end // cffi end
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/** @} */
#endif // NIX_API_EXPR_H #endif // NIX_API_EXPR_H

View file

@ -1,5 +1,10 @@
#ifndef NIX_API_EXTERNAL_H #ifndef NIX_API_EXTERNAL_H
#define NIX_API_EXTERNAL_H #define NIX_API_EXTERNAL_H
/** @ingroup libexpr
* @addtogroup Externals
* @brief Deal with external values
* @{
*/
/** @file /** @file
* @brief libexpr C bindings dealing with external values * @brief libexpr C bindings dealing with external values
*/ */
@ -184,5 +189,6 @@ void *nix_get_external_value_content(nix_c_context *context, ExternalValue *b);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/** @} */
#endif // NIX_API_EXTERNAL_H #endif // NIX_API_EXTERNAL_H

View file

@ -1,6 +1,9 @@
#ifndef NIX_API_VALUE_H #ifndef NIX_API_VALUE_H
#define NIX_API_VALUE_H #define NIX_API_VALUE_H
/** @addtogroup libexpr
* @{
*/
/** @file /** @file
* @brief libexpr C bindings dealing with values * @brief libexpr C bindings dealing with values
*/ */
@ -35,6 +38,7 @@ typedef void Value;
typedef struct State State; typedef struct State State;
// type defs // type defs
/** @brief Stores an under-construction set of bindings /** @brief Stores an under-construction set of bindings
* @ingroup value_manip
* *
* Do not reuse. * Do not reuse.
* @see nix_make_bindings_builder, nix_bindings_builder_free, nix_make_attrs * @see nix_make_bindings_builder, nix_bindings_builder_free, nix_make_attrs
@ -43,18 +47,23 @@ typedef struct State State;
typedef struct BindingsBuilder BindingsBuilder; typedef struct BindingsBuilder BindingsBuilder;
/** @brief PrimOp function /** @brief PrimOp function
* @ingroup primops
* *
* Owned by the GC * Owned by the GC
* @see nix_alloc_primop, nix_set_primop * @see nix_alloc_primop, nix_set_primop
*/ */
typedef struct PrimOp PrimOp; typedef struct PrimOp PrimOp;
/** @brief External Value /** @brief External Value
* @ingroup Externals
* *
* Owned by the GC * Owned by the GC
* @see nix_api_external.h
*/ */
typedef struct ExternalValue ExternalValue; typedef struct ExternalValue ExternalValue;
/** @defgroup primops
* @brief Create your own primops
* @{
*/
/** @brief Function pointer for primops /** @brief Function pointer for primops
* @param[in] state Evaluator state * @param[in] state Evaluator state
* @param[in] pos position of function call * @param[in] pos position of function call
@ -79,6 +88,7 @@ typedef void (*PrimOpFun)(State *state, int pos, Value **args, Value *v);
*/ */
PrimOp *nix_alloc_primop(nix_c_context *context, PrimOpFun fun, int arity, PrimOp *nix_alloc_primop(nix_c_context *context, PrimOpFun fun, int arity,
const char *name, const char **args, const char *doc); const char *name, const char **args, const char *doc);
/** @} */
// Function prototypes // Function prototypes
@ -91,6 +101,10 @@ PrimOp *nix_alloc_primop(nix_c_context *context, PrimOpFun fun, int arity,
* *
*/ */
Value *nix_alloc_value(nix_c_context *context, State *state); Value *nix_alloc_value(nix_c_context *context, State *state);
/** @addtogroup value_manip Manipulating values
* @brief Functions to inspect and change nix Value's
* @{
*/
/** @name Getters /** @name Getters
*/ */
/**@{*/ /**@{*/
@ -328,10 +342,12 @@ nix_err nix_bindings_builder_insert(nix_c_context *context,
* @param[in] builder the builder to free * @param[in] builder the builder to free
*/ */
void nix_bindings_builder_free(BindingsBuilder *builder); void nix_bindings_builder_free(BindingsBuilder *builder);
/**@}*/
// cffi end // cffi end
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/** @} */
#endif // NIX_API_VALUE_H #endif // NIX_API_VALUE_H

View file

@ -1,5 +1,12 @@
#ifndef NIX_API_STORE_H #ifndef NIX_API_STORE_H
#define NIX_API_STORE_H #define NIX_API_STORE_H
/**
* @defgroup libstore libstore
* @brief C bindings for nix libstore
*
* libstore is used for talking to a Nix store
* @{
*/
/** @file /** @file
* @brief Main entry for the libstore C bindings * @brief Main entry for the libstore C bindings
*/ */
@ -121,5 +128,7 @@ nix_err nix_store_get_version(nix_c_context *, Store *store, char *dest,
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/**
* @}
*/
#endif // NIX_API_STORE_H #endif // NIX_API_STORE_H

View file

@ -1,6 +1,13 @@
#ifndef NIX_API_UTIL_H #ifndef NIX_API_UTIL_H
#define NIX_API_UTIL_H #define NIX_API_UTIL_H
/**
* @defgroup libutil libutil
* @brief C bindings for nix libutil
*
* libutil is used for functionality shared between
* different Nix modules.
* @{
*/
/** @file /** @file
* @brief Main entry for the libutil C bindings * @brief Main entry for the libutil C bindings
* *
@ -12,6 +19,31 @@ extern "C" {
#endif #endif
// cffi start // cffi start
/** @defgroup errors Handling errors
* @brief Dealing with errors from the Nix side
*
* To handle errors that can be returned from the Nix API
* nix_c_context can be passed any function that potentially returns an error.
*
* Error information will be stored in this context, and can be retrieved
* using nix_err_code, nix_err_msg.
*
* Passing NULL instead will cause the API to throw C++ errors.
*
* Example:
* @code{.c}
* int main() {
* nix_c_context* ctx = nix_c_context_create();
* nix_libutil_init(ctx);
* if (nix_err_code(ctx) != NIX_OK) {
* printf("error: %s\n", nix_err_msg(NULL, ctx, NULL));
* return 1;
* }
* return 0;
* }
* @endcode
* @{
*/
// Error codes // Error codes
/** /**
* @brief Type for error codes in the NIX system * @brief Type for error codes in the NIX system
@ -67,6 +99,7 @@ typedef int nix_err;
/** /**
* @brief This object stores error state. * @brief This object stores error state.
* @struct nix_c_context
* *
* Passed as a first parameter to C functions that can fail, will store error * Passed as a first parameter to C functions that can fail, will store error
* information. Optional wherever it is used, passing NULL will throw a C++ * information. Optional wherever it is used, passing NULL will throw a C++
@ -92,6 +125,9 @@ nix_c_context *nix_c_context_create();
* @param[out] context The context to free, mandatory. * @param[out] context The context to free, mandatory.
*/ */
void nix_c_context_free(nix_c_context *context); void nix_c_context_free(nix_c_context *context);
/**
* @}
*/
/** /**
* @brief Initializes nix_libutil and its dependencies. * @brief Initializes nix_libutil and its dependencies.
@ -105,6 +141,9 @@ void nix_c_context_free(nix_c_context *context);
*/ */
nix_err nix_libutil_init(nix_c_context *context); nix_err nix_libutil_init(nix_c_context *context);
/** @defgroup settings
* @{
*/
/** /**
* @brief Retrieves a setting from the nix global configuration. * @brief Retrieves a setting from the nix global configuration.
* *
@ -128,8 +167,8 @@ nix_err nix_setting_get(nix_c_context *context, const char *key, char *value,
* *
* Use "extra-<setting name>" to append to the setting's value. * Use "extra-<setting name>" to append to the setting's value.
* *
* Settings only apply for new States. Call nix_plugins_init() when you are done * Settings only apply for new State%s. Call nix_plugins_init() when you are
* with the settings to load any plugins. * done with the settings to load any plugins.
* *
* @param[out] context optional, Stores error information * @param[out] context optional, Stores error information
* @param[in] key The key of the setting to set. * @param[in] key The key of the setting to set.
@ -140,6 +179,9 @@ nix_err nix_setting_get(nix_c_context *context, const char *key, char *value,
nix_err nix_setting_set(nix_c_context *context, const char *key, nix_err nix_setting_set(nix_c_context *context, const char *key,
const char *value); const char *value);
/**
* @}
*/
// todo: nix_plugins_init() // todo: nix_plugins_init()
/** /**
@ -150,6 +192,9 @@ nix_err nix_setting_set(nix_c_context *context, const char *key,
*/ */
const char *nix_version_get(); const char *nix_version_get();
/** @addtogroup errors
* @{
*/
/** /**
* @brief Retrieves the most recent error message from a context. * @brief Retrieves the most recent error message from a context.
* *
@ -215,9 +260,14 @@ nix_err nix_err_name(nix_c_context *context, const nix_c_context *read_context,
*/ */
nix_err nix_err_code(nix_c_context *context, const nix_c_context *read_context); nix_err nix_err_code(nix_c_context *context, const nix_c_context *read_context);
/**
* @}
*/
// cffi end // cffi end
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/** @} */
#endif // NIX_API_UTIL_H #endif // NIX_API_UTIL_H