diff --git a/Makefile b/Makefile index c3dc83c77..4f60d0d8b 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,10 @@ makefiles = \ misc/zsh/local.mk \ misc/systemd/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 ifeq ($(ENABLE_UNIT_TESTS), yes) diff --git a/configure.ac b/configure.ac index 676b145a5..c3823c01c 100644 --- a/configure.ac +++ b/configure.ac @@ -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) 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( [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'.])]) diff --git a/doc/external-api/.gitignore b/doc/external-api/.gitignore new file mode 100644 index 000000000..dab28b6b0 --- /dev/null +++ b/doc/external-api/.gitignore @@ -0,0 +1,3 @@ +/doxygen.cfg +/html +/latex diff --git a/doc/external-api/doxygen.cfg.in b/doc/external-api/doxygen.cfg.in new file mode 100644 index 000000000..19350b2c6 --- /dev/null +++ b/doc/external-api/doxygen.cfg.in @@ -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 diff --git a/doc/external-api/local.mk b/doc/external-api/local.mk new file mode 100644 index 000000000..a0f6e26fc --- /dev/null +++ b/doc/external-api/local.mk @@ -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 diff --git a/src/libexpr/nix_api_expr.h b/src/libexpr/nix_api_expr.h index c56ef89bb..f67a3d13f 100644 --- a/src/libexpr/nix_api_expr.h +++ b/src/libexpr/nix_api_expr.h @@ -1,5 +1,26 @@ #ifndef 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 * @brief Main entry for the libexpr C bindings */ @@ -8,22 +29,25 @@ #include "nix_api_util.h" #ifdef __cplusplus -extern "C" { + extern "C" { #endif -// cffi start + // cffi start -// Type definitions -/** - * @brief Represents a nix evaluator state. - * - * Multiple can be created for multi-threaded - * operation. - */ -typedef struct State State; // nix::EvalState + // Type definitions + /** + * @brief Represents a nix evaluator state. + * + * Multiple can be created for multi-threaded + * operation. + * @struct State + */ + typedef struct State State; // nix::EvalState /** * @brief Represents a nix value. * * Owned by the GC. + * @struct Value + * @see value_manip */ 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); +/** @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. * * The nix C api keeps alive objects by refcounting. * 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 */ -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 * + * @param[out] context Optional, stores error information * @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 @@ -147,9 +184,12 @@ void nix_gc_now(); void nix_gc_register_finalizer(void *obj, void *cd, void (*finalizer)(void *obj, void *cd)); +/** @} */ // cffi end #ifdef __cplusplus } #endif +/** @} */ + #endif // NIX_API_EXPR_H diff --git a/src/libexpr/nix_api_external.h b/src/libexpr/nix_api_external.h index 45e95346b..692f8000c 100644 --- a/src/libexpr/nix_api_external.h +++ b/src/libexpr/nix_api_external.h @@ -1,5 +1,10 @@ #ifndef NIX_API_EXTERNAL_H #define NIX_API_EXTERNAL_H +/** @ingroup libexpr + * @addtogroup Externals + * @brief Deal with external values + * @{ + */ /** @file * @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 } #endif +/** @} */ #endif // NIX_API_EXTERNAL_H diff --git a/src/libexpr/nix_api_value.h b/src/libexpr/nix_api_value.h index 8fa85b25d..110dd086f 100644 --- a/src/libexpr/nix_api_value.h +++ b/src/libexpr/nix_api_value.h @@ -1,6 +1,9 @@ #ifndef NIX_API_VALUE_H #define NIX_API_VALUE_H +/** @addtogroup libexpr + * @{ + */ /** @file * @brief libexpr C bindings dealing with values */ @@ -35,6 +38,7 @@ typedef void Value; typedef struct State State; // type defs /** @brief Stores an under-construction set of bindings + * @ingroup value_manip * * Do not reuse. * @see nix_make_bindings_builder, nix_bindings_builder_free, nix_make_attrs @@ -43,18 +47,23 @@ typedef struct State State; typedef struct BindingsBuilder BindingsBuilder; /** @brief PrimOp function + * @ingroup primops * * Owned by the GC * @see nix_alloc_primop, nix_set_primop */ typedef struct PrimOp PrimOp; /** @brief External Value + * @ingroup Externals * * Owned by the GC - * @see nix_api_external.h */ typedef struct ExternalValue ExternalValue; +/** @defgroup primops + * @brief Create your own primops + * @{ + */ /** @brief Function pointer for primops * @param[in] state Evaluator state * @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, const char *name, const char **args, const char *doc); +/** @} */ // 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); +/** @addtogroup value_manip Manipulating values + * @brief Functions to inspect and change nix Value's + * @{ + */ /** @name Getters */ /**@{*/ @@ -328,10 +342,12 @@ nix_err nix_bindings_builder_insert(nix_c_context *context, * @param[in] builder the builder to free */ void nix_bindings_builder_free(BindingsBuilder *builder); +/**@}*/ // cffi end #ifdef __cplusplus } #endif +/** @} */ #endif // NIX_API_VALUE_H diff --git a/src/libstore/nix_api_store.h b/src/libstore/nix_api_store.h index 6157faa82..bc01f0ad2 100644 --- a/src/libstore/nix_api_store.h +++ b/src/libstore/nix_api_store.h @@ -1,5 +1,12 @@ #ifndef 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 * @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 } #endif - +/** + * @} + */ #endif // NIX_API_STORE_H diff --git a/src/libutil/nix_api_util.h b/src/libutil/nix_api_util.h index 095564296..f626f2ccb 100644 --- a/src/libutil/nix_api_util.h +++ b/src/libutil/nix_api_util.h @@ -1,6 +1,13 @@ #ifndef 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 * @brief Main entry for the libutil C bindings * @@ -12,6 +19,31 @@ extern "C" { #endif // 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 /** * @brief Type for error codes in the NIX system @@ -67,6 +99,7 @@ typedef int nix_err; /** * @brief This object stores error state. + * @struct nix_c_context * * 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++ @@ -92,6 +125,9 @@ nix_c_context *nix_c_context_create(); * @param[out] context The context to free, mandatory. */ void nix_c_context_free(nix_c_context *context); +/** + * @} + */ /** * @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); +/** @defgroup settings + * @{ + */ /** * @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-" to append to the setting's value. * - * Settings only apply for new States. Call nix_plugins_init() when you are done - * with the settings to load any plugins. + * Settings only apply for new State%s. Call nix_plugins_init() when you are + * done with the settings to load any plugins. * * @param[out] context optional, Stores error information * @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, const char *value); +/** + * @} + */ // 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(); +/** @addtogroup errors + * @{ + */ /** * @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); +/** + * @} + */ + // cffi end #ifdef __cplusplus } #endif +/** @} */ #endif // NIX_API_UTIL_H