=head1 NAME

nbdkit-cc-plugin - write small nbdkit plugins in inline C
(and other languages)

=head1 SYNOPSIS

 nbdkit cc /path/to/plugin.c [CC=...] [CFLAGS="..."]
                             [EXTRA_CFLAGS="..."]
                             [other plugin parameters ...]

=for paragraph

 nbdkit cc - <<'EOF'
 ... C code ...
 EOF

=head1 DESCRIPTION

This plugin allows you to write small L<nbdkit(1)> plugins in C (and
some other languages).  When you use this plugin it compiles your
source code to a temporary plugin and then jumps into your compiled
plugin.  It is somewhat similar to L<nbdkit-sh-plugin(3)>, except for
C source code.  This can also be used to write plugins which are "C
scripts".

B<Note> this is not the way you normally write nbdkit plugins in C.
To understand how to write plugins in C normally, read
L<nbdkit-plugin(3)>.

=head2 Simple plugin example

Simple plugins from the nbdkit source tree can be compiled and run
directly using commands such as:

 $ nbdkit cc plugins/example1/example1.c EXTRA_CFLAGS="-I. -Iinclude"

You can also read the source from stdin using C<->:

 $ nbdkit cc - EXTRA_CFLAGS="-I. -Iinclude" \
             < plugins/example1/example1.c

To replace the compiler flags:

 $ nbdkit cc plugins/example1/example1.c \
             CFLAGS="-O3 -mavx2 -fPIC -shared"

=head2 Compiler name and flags

The plugin parameters C<CC>, C<CFLAGS> and C<EXTRA_CFLAGS> (written in
uppercase) can be used to control which C compiler and C compiler
flags are used.  If not set, the default compiler and flags from when
nbdkit was itself compiled from source are used.  To see what those
were you can do:

 $ nbdkit cc --dump-plugin
 ...
 CC=gcc
 CFLAGS=-g -O2 -fPIC -shared

The C<CFLAGS> parameter overrides the built-in flags completely.  The
C<EXTRA_CFLAGS> parameter adds extra flags to the built-in flags.

=head2 Plugin API version

Plugins compiled this way must use the same API version as the cc
plugin itself uses.  Currently this is C<NBDKIT_API_VERSION=2>.

=head2 C plugin as a self-contained script

You can create a C plugin which is a self-contained script by adding
the following lines at the top and ensuring the C source is executable
(S<C<chmod +x plugin.c>>):

 #if 0
 exec nbdkit cc "$0" "$@"
 #endif

The script can be run as a command with additional nbdkit flags and
plugin parameters, eg:

 ./plugin.c -f -v
 ./plugin.c -p 10000 --filter=cow
 ./plugin.c param=1

=head2 Using this plugin with C++

 nbdkit cc CC=g++ source.cpp

C++ plugin scripts can be created similarly to C, but you must add
C<CC=g++> as a parameter to exec nbdkit.

=head2 Using this plugin with OCaml

 nbdkit cc CC=ocamlopt \
           CFLAGS="-output-obj -runtime-variant _pic __OCAML_STD_INCLUDES__ __OCAML_PLUGIN_LIBRARIES__ NBDKit.cmx -cclib -lnbdkitocaml" \
           source.ml

OCaml plugin scripts can be created using this trick:

 (*/.)>/dev/null 2>&1
 exec nbdkit cc "$0" \
      CC=ocamlopt \
      CFLAGS="-output-obj -runtime-variant _pic __OCAML_STD_INCLUDES__ __OCAML_PLUGIN_LIBRARIES__ NBDKit.cmx -cclib -lnbdkitocaml" \
      "$@"
 *)
 (* followed by OCaml code for the plugin here *)

As with C plugin scripts, the file must be executable.  See also
L<nbdkit-ocaml-plugin(3)>.

=head2 Using this plugin with other programming languages

This plugin can be used with most ahead-of-time compiled programming
languages if they can create shared objects (F<.so> files).  The only
requirement is that the compiler (C<CC>) supports an I<-o> option to
write a shared object.

=head1 PARAMETERS

The script name, or C<->, must appear as the first parameter.

=over 4

=item B<CC=>CC

=item B<CFLAGS=">CFLAGSB<">

=item B<EXTRA_CFLAGS=">EXTRA_CFLAGSB<">

Override the compiler and flags.  See L</Compiler name and flags>
above.

=back

All other parameters on the command line are passed to the plugin.

=head1 EXAMPLE

 $ nbdkit cc - <<'EOF'
 #include <stdint.h>
 #include <string.h>

 #define NBDKIT_API_VERSION 2
 #include <nbdkit-plugin.h>

 char data[10*1024*1024];

 #define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL

 static void *
 my_open (int readonly)
 {
   return NBDKIT_HANDLE_NOT_NEEDED;
 }

 static int64_t
 my_get_size (void *handle)
 {
   return (int64_t) sizeof (data);
 }

 static int
 my_pread (void *handle, void *buf,
           uint32_t count, uint64_t offset,
           uint32_t flags)
 {
   memcpy (buf, data+offset, count);
   return 0;
 }

 static int
 my_pwrite (void *handle, const void *buf,
            uint32_t count, uint64_t offset,
            uint32_t flags)
 {
   memcpy (data+offset, buf, count);
   return 0;
 }

 static struct nbdkit_plugin plugin = {
   .name              = "myplugin",
   .open              = my_open,
   .get_size          = my_get_size,
   .pread             = my_pread,
   .pwrite            = my_pwrite,
 };

 NBDKIT_REGISTER_PLUGIN(plugin)
 EOF

=head1 FILES

=over 4

=item F<$plugindir/nbdkit-cc-plugin.so>

The plugin.

Use C<nbdkit --dump-config> to find the location of C<$plugindir>.

=back

=head1 VERSION

C<nbdkit-cc-plugin> first appeared in nbdkit 1.22.

=head1 SEE ALSO

L<nbdkit(1)>,
L<nbdkit-plugin(3)>,
L<nbdkit-eval-plugin(3)>,
L<nbdkit-ocaml-plugin(3)>,
L<nbdkit-sh-plugin(3)>.

=head1 AUTHORS

Richard W.M. Jones

=head1 COPYRIGHT

Copyright Red Hat
