-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8699 from tweag/nix-c-bindings
(Towards) stable C bindings for libutil, libexpr
- Loading branch information
Showing
47 changed files
with
3,624 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/doxygen.cfg | ||
/html | ||
/latex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Getting started | ||
|
||
> **Warning** These bindings are **experimental**, which means they can change | ||
> at any time or be removed outright; nevertheless the plan is to provide a | ||
> stable external C API to the Nix language and the Nix store. | ||
The language library allows evaluating Nix expressions and interacting with Nix | ||
language values. The Nix store API is still rudimentary, and only allows | ||
initialising and connecting to a store for the Nix language evaluator to | ||
interact with. | ||
|
||
Currently there are two ways to interface with the Nix language evaluator | ||
programmatically: | ||
|
||
1. Embedding the evaluator | ||
2. Writing language plug-ins | ||
|
||
Embedding means you link the Nix C libraries in your program and use them from | ||
there. Adding a plug-in means you make a library that gets loaded by the Nix | ||
language evaluator, specified through a configuration option. | ||
|
||
Many of the components and mechanisms involved are not yet documented, therefore | ||
please refer to the [Nix source code](https://github.com/NixOS/nix/) for | ||
details. Additions to in-code documentation and the reference manual are highly | ||
appreciated. | ||
|
||
The following examples, for simplicity, don't include error handling. See the | ||
[Handling errors](@ref errors) section for more information. | ||
|
||
# Embedding the Nix Evaluator | ||
|
||
In this example we programmatically start the Nix language evaluator with a | ||
dummy store (that has no store paths and cannot be written to), and evaluate the | ||
Nix expression `builtins.nixVersion`. | ||
|
||
**main.c:** | ||
|
||
```C | ||
#include <nix_api_util.h> | ||
#include <nix_api_expr.h> | ||
#include <nix_api_value.h> | ||
#include <stdio.h> | ||
|
||
// NOTE: This example lacks all error handling. Production code must check for | ||
// errors, as some return values will be undefined. | ||
int main() { | ||
nix_libexpr_init(NULL); | ||
|
||
Store* store = nix_store_open(NULL, "dummy://", NULL); | ||
EvalState* state = nix_state_create(NULL, NULL, store); // empty search path (NIX_PATH) | ||
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_free(store); | ||
return 0; | ||
} | ||
``` | ||
|
||
**Usage:** | ||
|
||
```ShellSession | ||
$ gcc main.c $(pkg-config nix-expr-c --libs --cflags) -o main | ||
$ ./main | ||
Nix version: 2.17 | ||
``` | ||
|
||
# Writing a Nix language plug-in | ||
|
||
In this example we add a custom primitive operation (_primop_) to `builtins`. It | ||
will increment the argument if it is an integer and throw an error otherwise. | ||
|
||
**plugin.c:** | ||
|
||
```C | ||
#include <nix_api_util.h> | ||
#include <nix_api_expr.h> | ||
#include <nix_api_value.h> | ||
|
||
void increment(void* user_data, nix_c_context* ctx, EvalState* state, Value** args, Value* v) { | ||
nix_value_force(NULL, state, args[0]); | ||
if (nix_get_type(NULL, args[0]) == NIX_TYPE_INT) { | ||
nix_init_int(NULL, v, nix_get_int(NULL, args[0]) + 1); | ||
} else { | ||
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "First argument should be an integer."); | ||
} | ||
} | ||
|
||
void nix_plugin_entry() { | ||
const char* args[] = {"n", NULL}; | ||
PrimOp *p = nix_alloc_primop(NULL, increment, 1, "increment", args, "Example custom built-in function: increments an integer", NULL); | ||
nix_register_primop(NULL, p); | ||
nix_gc_decref(NULL, p); | ||
} | ||
``` | ||
**Usage:** | ||
```ShellSession | ||
$ gcc plugin.c $(pkg-config nix-expr-c --libs --cflags) -shared -o plugin.so | ||
$ nix --plugin-files ./plugin.so repl | ||
nix-repl> builtins.increment 1 | ||
2 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# 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: C API (experimental)" | ||
|
||
# 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-c \ | ||
src/libexpr-c \ | ||
src/libstore-c \ | ||
doc/external-api/README.md | ||
|
||
FILE_PATTERNS = nix_api_*.h *.md | ||
|
||
# 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 | ||
|
||
USE_MDFILE_AS_MAINPAGE = doc/external-api/README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
$(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 C bindings | ||
.PHONY: external-api-html | ||
external-api-html: $(docdir)/external-api/html/index.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
libraries += libexprc | ||
|
||
libexprc_NAME = libnixexprc | ||
|
||
libexprc_DIR := $(d) | ||
|
||
libexprc_SOURCES := \ | ||
$(wildcard $(d)/*.cc) \ | ||
|
||
# Not just for this library itself, but also for downstream libraries using this library | ||
|
||
INCLUDE_libexprc := -I $(d) | ||
libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ | ||
$(INCLUDE_libfetchers) \ | ||
$(INCLUDE_libstore) $(INCLUDE_libstorec) \ | ||
$(INCLUDE_libexpr) $(INCLUDE_libexprc) | ||
|
||
libexprc_LIBS = libutil libutilc libstore libstorec libexpr | ||
|
||
libexprc_LDFLAGS += -pthread | ||
|
||
$(eval $(call install-file-in, $(d)/nix-expr-c.pc, $(libdir)/pkgconfig, 0644)) | ||
|
||
libexprc_FORCE_INSTALL := 1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
prefix=@prefix@ | ||
libdir=@libdir@ | ||
includedir=@includedir@ | ||
|
||
Name: Nix | ||
Description: Nix Language Evaluator - C API | ||
Version: @PACKAGE_VERSION@ | ||
Requires: nix-store-c | ||
Libs: -L${libdir} -lnixexprc | ||
Cflags: -I${includedir}/nix |
Oops, something went wrong.