Commit aa0c1ec1 authored by Rusty Russell's avatar Rusty Russell

tools/configurator: add manual page.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent e8821223
ccanlint.1: ccanlint.1.txt
a2x --format=manpage ccanlint.1.txt
default: ccanlint.1 configurator.1
%.1: %.1.txt
a2x --format=manpage $<
distclean:
rm -f ccanlint.1
rm -f ccanlint.1 configurator.1
'\" t
.\" Title: configurator
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 03/01/2018
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "CONFIGURATOR" "1" "03/01/2018" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
configurator \- Generate a simple config\&.h or variable file
.SH "SYNOPSIS"
.sp
\fBconfigurator\fR [\fIOPTIONS\fR] [\fICC\fR] [\fICFLAGS\fR\&...]
.SH "DESCRIPTION"
.sp
\fBconfigurator\fR is a standalone C program which evaluates the C environment using code snippets\&.
.sp
The C compiler (and flags) can be provided on the command\-line, otherwise built\-in defaults are used\&.
.sp
It has a builtin set of tests, to which more can be added\&. By default it produces a C header file to standard output, but it can also produce a file containing simple "key=value" lines suitable for parsing by \fBsh\fR or \fBmake\fR\&.
.SH "OPTIONS"
.PP
\fB\-v\fR
.RS 4
Print out every test result; specified twice, print out each test too\&.
.RE
.PP
\fB\-vv\fR
.RS 4
Shortcut for two
\fB\-v\fR
options\&.
.RE
.PP
\fB\-\-var\-file=<file>\fR
.RS 4
Output results in format
\fI<key>=<value>\fR
to
\fI<file>\fR, or stdout if
\fI<file>\fR
is
\fI\-\fR\&. Default is not to output this\&.
.RE
.PP
\fB\-\-header\-file=<file>\fR
.RS 4
Output C\-style header to
\fI<file>\fR
instead out stdout\&.
.RE
.PP
\fB\-\-autotools\-style\fR
.RS 4
Produce output to stdout like autotools\*(Aq configure script\&. This usually means you want to use
\fB\-\-header\-file\fR
so that doesn\(cqt mix with stdout\&.
.RE
.PP
\fB\-O<outflag>\fR
.RS 4
Override option to set compiler output file\&.
.RE
.PP
\fB\-\-configurator\-cc=<command>\fR
.RS 4
This gives the real compiler command to use for tests, instead of the first commandline argument or the default\&.
.RE
.PP
\fB\-\-extra\-tests\fR
.RS 4
Read additional tests from stdin, see
\fIEXTRA TESTS\fR
below\&.
.RE
.SH "OUTPUT"
.sp
The header output is \fI#ifndef/#define\fR idempotent\-wrapped using \fICCAN_CONFIG_H\fR, and defines \fI_GNU_SOURCE\fR\&. It also defines \fICCAN_COMPILER\fR, \fICCAN_CFLAGS\fR and \fICCAN_OUTPUT_EXE_CFLAG\fR as either the built\-in definitions or those provided on the command line\&. The remainder is \fI#define\fR of the test names followed by a \fI0\fR or \fI1\fR: note that this means you should use \fI#if\fR not \fI#ifdef\fR to test features in your C programs!
.sp
The var\-file output is simply the test names followed by \fI=1\fR or \fI=0\fR\&.
.SH "EXTRA TESTS"
.sp
Extra tests must be formatted as \fI<key>=<value>\fR pairs, with leading whitespace and \fI#\fR lines ignored\&.
.sp
The first three lines are always the same:
.PP
\fBvar=<varname>\fR
.RS 4
Define the variable set by the test, e\&.g\&.
\fIvar=HAVE_FOO\fR\&.
.RE
.PP
\fBdesc=<description>\fR
.RS 4
The description printed out with
\fB\-\-autotools\-style\fR, e\&.g\&.
\fIfoo support\fR\&.
.RE
.PP
\fBstyle=<style>\fR
.RS 4
The set of strings defining how to treat the code snippet\&. It must include one of
\fIOUTSIDE_MAIN\fR,
\fIDEFINES_FUNC\fR,
\fIINSIDE_MAIN\fR
or
\fIDEFINES_EVERYTHING\fR
which control the boilerplate to surround the file, and may include
\fIEXECUTE\fR
or both
\fIEXECUTE\fR
and
\fIMAY_NOT_COMPILE\fR\&. e\&.g\&.
\fIINSIDE_MAIN|EXECUTE\fR\&.
.RE
.sp
The following styles are defined:
.PP
\fBOUTSIDE_MAIN\fR
.RS 4
means we put a simple boilerplate main below it\&.
.RE
.PP
\fBDEFINES_FUNC\fR
.RS 4
put a simple boilerplate main below it, which references
\fIfunc\fR
(to avoid any unused warnings)\&.
.RE
.PP
\fBINSIDE_MAIN\fR
.RS 4
put this inside main()\&. This also means it must exit with status 0 if it compiles, unless
\fBEXECUTE\fR
is added\&.
.RE
.PP
\fBDEFINES_EVERYTHING\fR
.RS 4
don\(cqt add any boilerplate at all\&.
.RE
.PP
\fBEXECUTE\fR
.RS 4
this is an execution test; it must compile, but may not exit with status 0 when run\&.
.RE
.PP
\fBMAY_NOT_COMPILE\fR
.RS 4
Only useful with EXECUTE: don\(cqt get upset if it doesn\(cqt compile\&.
.RE
.sp
The following lines are optional, and may follow in any order:
.PP
\fBdepends=<varnames>\fR
.RS 4
A space\-separates set of vars which must pass to even try to pass this one\&. If the var begins with
\fI!\fR
then the dependency must fail to try this one\&. e\&.g\&.
\fIdepends=HAVE_UCONTEXT !HAVE_VALGRIND_MEMCHECK_H\fR\&.
.RE
.PP
\fBlink=<linkargs>\fR
.RS 4
Extra arguments for linking with this test, e\&.g\&.
\fIlink=\-lrt\fR\&.
.RE
.PP
\fBflags=<cflags>\fR
.RS 4
Extra flags for compiling with this test, e\&.g\&.
\fIflags=\-fopenmp\fR\&.
.RE
.PP
\fBoverrides=<varname>\fR
.RS 4
Tests to force passing if this one passes\&. e\&.g\&.
\fIoverrides=HAVE_SOME_FOO\fR\&.
.RE
.sp
The final line is the code to test, itself, either as a single \fIcode=<oneline>\fR or as multiple lines starting with \fIcode=\fR and ending with \fI/*END*/\fR on a line by itself\&. e\&.g\&. \fIcode=return 0;\fR\&.
.SH "EXIT STATUS"
.sp
It will exit with non\-zero status if it has a problem\&. \fB1\fR means bad commandline options\&. \fB2\fR means some operational problem creating and running tests\&. \fB3\fR means a bad test\&. \fB4\fR means failure to parse an extra test\&.
.SH "AUTHOR"
.sp
Rusty Russell wrote \fBconfigurator\fR\&.
.SH "RESOURCES"
.sp
Main web site: http://ccodearchive\&.net/
.sp
Wiki: https://github\&.com/rustyrussell/ccan/wiki/
.SH "COPYING"
.sp
This program is under the MIT\-style BSD license; see code for details\&.
CONFIGURATOR(1)
===============
:doctype: manpage
NAME
----
configurator - Generate a simple config.h or variable file
SYNOPSIS
--------
*configurator* ['OPTIONS'] ['CC'] ['CFLAGS'...]
DESCRIPTION
-----------
*configurator* is a standalone C program which evaluates the C
environment using code snippets.
The C compiler (and flags) can be provided on the command-line,
otherwise built-in defaults are used.
It has a builtin set of tests, to which more can be added. By default
it produces a C header file to standard output, but it can also
produce a file containing simple "key=value" lines suitable for parsing
by *sh* or *make*.
OPTIONS
-------
*-v*::
Print out every test result; specified twice, print out each test too.
*-vv*::
Shortcut for two *-v* options.
*--var-file=<file>*::
Output results in format '<key>=<value>' to '<file>', or stdout if '<file>'
is '-'. Default is not to output this.
*--header-file=<file>*::
Output C-style header to '<file>' instead out stdout.
*--autotools-style*::
Produce output to stdout like autotools' configure script. This
usually means you want to use *--header-file* so that doesn't mix with stdout.
*-O<outflag>*::
Override option to set compiler output file.
*--configurator-cc=<command>*::
This gives the real compiler command to use for tests, instead of the first
commandline argument or the default.
*--extra-tests*::
Read additional tests from stdin, see 'EXTRA TESTS' below.
OUTPUT
------
The header output is '#ifndef/#define' idempotent-wrapped using
'CCAN_CONFIG_H', and defines '_GNU_SOURCE'. It also defines
'CCAN_COMPILER', 'CCAN_CFLAGS' and 'CCAN_OUTPUT_EXE_CFLAG' as
either the built-in definitions or those provided on the command line.
The remainder is '#define' of the test names followed by a '0' or '1':
note that this means you should use '#if' not '#ifdef' to test features
in your C programs!
The var-file output is simply the test names followed by '=1' or '=0'.
EXTRA TESTS
-----------
Extra tests must be formatted as '<key>=<value>' pairs, with leading
whitespace and '#' lines ignored.
The first three lines are always the same:
*var=<varname>*::
Define the variable set by the test, e.g. 'var=HAVE_FOO'.
*desc=<description>*::
The description printed out with *--autotools-style*, e.g. 'foo support'.
*style=<style>*::
The set of strings defining how to treat the code snippet. It must
include one of 'OUTSIDE_MAIN', 'DEFINES_FUNC', 'INSIDE_MAIN' or
'DEFINES_EVERYTHING' which control the boilerplate to surround the
file, and may include 'EXECUTE' or both 'EXECUTE' and
'MAY_NOT_COMPILE'. e.g. 'INSIDE_MAIN|EXECUTE'.
The following styles are defined:
*OUTSIDE_MAIN*::
means we put a simple boilerplate main below it.
*DEFINES_FUNC*::
put a simple boilerplate main below it, which references 'func' (to
avoid any unused warnings).
*INSIDE_MAIN*::
put this inside main(). This also means it must exit with status 0
if it compiles, unless *EXECUTE* is added.
*DEFINES_EVERYTHING*::
don't add any boilerplate at all.
*EXECUTE*::
this is an execution test; it must compile, but may not exit with
status 0 when run.
*MAY_NOT_COMPILE*::
Only useful with EXECUTE: don't get upset if it doesn't compile.
The following lines are optional, and may follow in any order:
*depends=<varnames>*::
A space-separates set of vars which must pass to even try to pass this
one. If the var begins with '!' then the dependency must fail to try
this one. e.g. 'depends=HAVE_UCONTEXT !HAVE_VALGRIND_MEMCHECK_H'.
*link=<linkargs>*::
Extra arguments for linking with this test, e.g. 'link=-lrt'.
*flags=<cflags>*::
Extra flags for compiling with this test, e.g. 'flags=-fopenmp'.
*overrides=<varname>*::
Tests to force passing if this one passes. e.g. 'overrides=HAVE_SOME_FOO'.
The final line is the code to test, itself, either as a single
'code=<oneline>' or as multiple lines starting with 'code=' and ending
with '/\*END*/' on a line by itself. e.g. 'code=return 0;'
EXIT STATUS
-----------
It will exit with non-zero status if it has a problem. *1* means bad
commandline options. *2* means some operational problem creating and
running tests. *3* means a bad test. *4* means failure to parse an
extra test.
AUTHOR
------
Rusty Russell wrote *configurator*.
RESOURCES
---------
Main web site: http://ccodearchive.net/
Wiki: https://github.com/rustyrussell/ccan/wiki/
COPYING
-------
This program is under the MIT-style BSD license; see code for details.
......@@ -26,6 +26,11 @@
*/
#define _POSIX_C_SOURCE 200809L /* For pclose, popen, strdup */
#define EXIT_BAD_USAGE 1
#define EXIT_TROUBLE_RUNNING 2
#define EXIT_BAD_TEST 3
#define EXIT_BAD_INPUT 4
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
......@@ -544,7 +549,7 @@ static char *grab_stream(FILE *file)
}
size += ret;
if (ferror(file))
c12r_err(1, "reading from command");
c12r_err(EXIT_TROUBLE_RUNNING, "reading from command");
buffer[size] = '\0';
return buffer;
}
......@@ -564,7 +569,7 @@ static char *run(const char *cmd, int *exitstatus)
cmdout = popen(cmdredir, "r");
if (!cmdout)
c12r_err(1, "popen \"%s\"", cmdredir);
c12r_err(EXIT_TROUBLE_RUNNING, "popen \"%s\"", cmdredir);
free(cmdredir);
......@@ -605,7 +610,7 @@ static struct test *find_test(const char *name)
if (strcmp(tests[i].name, name) == 0)
return &tests[i];
}
c12r_errx(2, "Unknown test %s", name);
c12r_errx(EXIT_BAD_TEST, "Unknown test %s", name);
abort();
}
......@@ -661,7 +666,7 @@ static bool run_test(const char *cmd, struct test *test)
outf = fopen(INPUT_FILE, verbose > 1 ? "w+" : "w");
if (!outf)
c12r_err(1, "creating %s", INPUT_FILE);
c12r_err(EXIT_TROUBLE_RUNNING, "creating %s", INPUT_FILE);
fprintf(outf, "%s", PRE_BOILERPLATE);
......@@ -683,7 +688,7 @@ static bool run_test(const char *cmd, struct test *test)
} else if (strstr(test->style, "DEFINES_EVERYTHING")) {
fprintf(outf, "%s", test->fragment);
} else
c12r_errx(2, "Unknown style for test %s: %s",
c12r_errx(EXIT_BAD_TEST, "Unknown style for test %s: %s",
test->name, test->style);
if (verbose > 1) {
......@@ -725,7 +730,8 @@ static bool run_test(const char *cmd, struct test *test)
test->name, status, output);
if (strstr(test->style, "EXECUTE")
&& !strstr(test->style, "MAY_NOT_COMPILE"))
c12r_errx(1, "Test for %s did not compile:\n%s",
c12r_errx(EXIT_BAD_TEST,
"Test for %s did not compile:\n%s",
test->name, output);
test->answer = false;
free(output);
......@@ -737,7 +743,8 @@ static bool run_test(const char *cmd, struct test *test)
|| strstr(test->style, "INSIDE_MAIN")) {
output = run("." DIR_SEP OUTPUT_FILE, &status);
if (!strstr(test->style, "EXECUTE") && status != 0)
c12r_errx(1, "Test for %s failed with %i:\n%s",
c12r_errx(EXIT_BAD_TEST,
"Test for %s failed with %i:\n%s",
test->name, status, output);
if (verbose && status)
printf("%s exited %i\n", test->name, status);
......@@ -774,7 +781,7 @@ static char *any_field(char **fieldname)
eq = strchr(p, '=');
if (!eq)
c12r_errx(2, "no = in line: %s", p);
c12r_errx(EXIT_BAD_INPUT, "no = in line: %s", p);
*eq = '\0';
*fieldname = strdup(p);
p = eq + 1;
......@@ -792,10 +799,11 @@ static char *read_field(const char *name, bool compulsory)
if (!value) {
if (!compulsory)
return NULL;
c12r_errx(2, "Could not read field %s", name);
c12r_errx(EXIT_BAD_INPUT, "Could not read field %s", name);
}
if (strcmp(fieldname, name) != 0)
c12r_errx(2, "Expected field %s not %s", name, fieldname);
c12r_errx(EXIT_BAD_INPUT,
"Expected field %s not %s", name, fieldname);
return value;
}
......@@ -845,11 +853,11 @@ static bool read_test(struct test *test)
else if (strcmp(field, "code") == 0)
break;
else
c12r_errx(2, "Unknown field %s in %s",
c12r_errx(EXIT_BAD_INPUT, "Unknown field %s in %s",
field, test->name);
}
if (!value)
c12r_errx(2, "Missing code in %s", test->name);
c12r_errx(EXIT_BAD_INPUT, "Missing code in %s", test->name);
if (strlen(value) == 0) {
/* Multiline program, read to END comment */
......@@ -909,7 +917,7 @@ int main(int argc, const char *argv[])
fprintf(stderr,
"%s: option requires an argument -- O\n",
argv[0]);
exit(1);
exit(EXIT_BAD_USAGE);
}
} else if (strcmp(argv[1], "-v") == 0) {
argc--;
......@@ -942,7 +950,7 @@ int main(int argc, const char *argv[])
} else if (strcmp(argv[1], "--") == 0) {
break;
} else if (argv[1][0] == '-') {
c12r_errx(2, "Unknown option %s", argv[1]);
c12r_errx(EXIT_BAD_USAGE, "Unknown option %s", argv[1]);
} else {
break;
}
......@@ -985,13 +993,15 @@ int main(int argc, const char *argv[])
start_test("Writing variables to ", varfile);
vars = fopen(varfile, "a");
if (!vars)
c12r_err(2, "Could not open %s", varfile);
c12r_err(EXIT_TROUBLE_RUNNING,
"Could not open %s", varfile);
}
for (i = 0; tests[i].name; i++)
fprintf(vars, "%s=%u\n", tests[i].name, tests[i].answer);
if (vars != stdout) {
if (fclose(vars) != 0)
c12r_err(2, "Closing %s", varfile);
c12r_err(EXIT_TROUBLE_RUNNING,
"Closing %s", varfile);
end_test(1);
}
}
......@@ -1000,7 +1010,8 @@ int main(int argc, const char *argv[])
start_test("Writing header to ", headerfile);
outf = fopen(headerfile, "w");
if (!outf)
c12r_err(2, "Could not open %s", headerfile);
c12r_err(EXIT_TROUBLE_RUNNING,
"Could not open %s", headerfile);
} else
outf = stdout;
......@@ -1023,7 +1034,7 @@ int main(int argc, const char *argv[])
if (headerfile) {
if (fclose(outf) != 0)
c12r_err(2, "Closing %s", headerfile);
c12r_err(EXIT_TROUBLE_RUNNING, "Closing %s", headerfile);
end_test(1);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment