Manual docs tweaks still in preparation for including docs with code pushes
This commit is contained in:
parent
a743249a55
commit
b77e5c7625
@ -174,9 +174,9 @@ We list the most frequently used macros below. For a complete list, see file
|
|||||||
### Multi-threaded Tests
|
### Multi-threaded Tests
|
||||||
|
|
||||||
Google Test is thread-safe where the pthread library is available. After
|
Google Test is thread-safe where the pthread library is available. After
|
||||||
`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
`#include "gtest/gtest.h"`, you can check the
|
||||||
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||||
undefined.).
|
`#defined` to 1, no if it's undefined.).
|
||||||
|
|
||||||
If Google Test doesn't correctly detect whether pthread is available in your
|
If Google Test doesn't correctly detect whether pthread is available in your
|
||||||
environment, you can force it with
|
environment, you can force it with
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
## Using GoogleTest from various build systems ##
|
## Using GoogleTest from various build systems
|
||||||
|
|
||||||
GoogleTest comes with pkg-config files that can be used to determine all
|
GoogleTest comes with pkg-config files that can be used to determine all
|
||||||
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
|
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
|
||||||
Pkg-config is a standardised plain-text format containing
|
Pkg-config is a standardised plain-text format containing
|
||||||
|
|
||||||
* the includedir (-I) path
|
* the includedir (-I) path
|
||||||
* necessary macro (-D) definitions
|
* necessary macro (-D) definitions
|
||||||
* further required flags (-pthread)
|
* further required flags (-pthread)
|
||||||
* the library (-L) path
|
* the library (-L) path
|
||||||
* the library (-l) to link to
|
* the library (-l) to link to
|
||||||
|
|
||||||
All current build systems support pkg-config in one way or another. For
|
All current build systems support pkg-config in one way or another. For all
|
||||||
all examples here we assume you want to compile the sample
|
examples here we assume you want to compile the sample
|
||||||
`samples/sample3_unittest.cc`.
|
`samples/sample3_unittest.cc`.
|
||||||
|
|
||||||
|
### CMake
|
||||||
### CMake ###
|
|
||||||
|
|
||||||
Using `pkg-config` in CMake is fairly easy:
|
Using `pkg-config` in CMake is fairly easy:
|
||||||
|
|
||||||
``` cmake
|
```cmake
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
cmake_policy(SET CMP0048 NEW)
|
cmake_policy(SET CMP0048 NEW)
|
||||||
@ -43,11 +42,10 @@ that all libraries have been compiled with threading enabled. In addition,
|
|||||||
GoogleTest might also require `-pthread` in the compiling step, and as such
|
GoogleTest might also require `-pthread` in the compiling step, and as such
|
||||||
splitting the pkg-config `Cflags` variable into include dirs and macros for
|
splitting the pkg-config `Cflags` variable into include dirs and macros for
|
||||||
`target_compile_definitions()` might still miss this). The same recommendation
|
`target_compile_definitions()` might still miss this). The same recommendation
|
||||||
goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which
|
goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
|
||||||
happens to discard `-L` flags and `-pthread`.
|
to discard `-L` flags and `-pthread`.
|
||||||
|
|
||||||
|
### Autotools
|
||||||
### Autotools ###
|
|
||||||
|
|
||||||
Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
|
Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
|
||||||
|
|
||||||
@ -77,8 +75,7 @@ testapp_CXXFLAGS = $(GTEST_CFLAGS)
|
|||||||
testapp_LDADD = $(GTEST_LIBS)
|
testapp_LDADD = $(GTEST_LIBS)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Meson
|
||||||
### Meson ###
|
|
||||||
|
|
||||||
Meson natively uses pkgconfig to query dependencies:
|
Meson natively uses pkgconfig to query dependencies:
|
||||||
|
|
||||||
@ -96,13 +93,12 @@ testapp = executable(
|
|||||||
test('first_and_only_test', testapp)
|
test('first_and_only_test', testapp)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Plain Makefiles
|
||||||
|
|
||||||
### Plain Makefiles ###
|
Since `pkg-config` is a small Unix command-line utility, it can be used in
|
||||||
|
handwritten `Makefile`s too:
|
||||||
|
|
||||||
Since `pkg-config` is a small Unix command-line utility, it can be used
|
```Makefile
|
||||||
in handwritten `Makefile`s too:
|
|
||||||
|
|
||||||
``` Makefile
|
|
||||||
GTEST_CFLAGS = `pkg-config --cflags gtest_main`
|
GTEST_CFLAGS = `pkg-config --cflags gtest_main`
|
||||||
GTEST_LIBS = `pkg-config --libs gtest_main`
|
GTEST_LIBS = `pkg-config --libs gtest_main`
|
||||||
|
|
||||||
@ -120,12 +116,11 @@ testapp.o: samples/sample3_unittest.cc
|
|||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Help! pkg-config can't find GoogleTest!
|
||||||
### Help! pkg-config can't find GoogleTest! ###
|
|
||||||
|
|
||||||
Let's say you have a `CMakeLists.txt` along the lines of the one in this
|
Let's say you have a `CMakeLists.txt` along the lines of the one in this
|
||||||
tutorial and you try to run `cmake`. It is very possible that you get a
|
tutorial and you try to run `cmake`. It is very possible that you get a failure
|
||||||
failure along the lines of:
|
along the lines of:
|
||||||
|
|
||||||
```
|
```
|
||||||
-- Checking for one of the modules 'gtest_main'
|
-- Checking for one of the modules 'gtest_main'
|
||||||
@ -135,9 +130,9 @@ CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
|
|||||||
|
|
||||||
These failures are common if you installed GoogleTest yourself and have not
|
These failures are common if you installed GoogleTest yourself and have not
|
||||||
sourced it from a distro or other package manager. If so, you need to tell
|
sourced it from a distro or other package manager. If so, you need to tell
|
||||||
pkg-config where it can find the `.pc` files containing the information.
|
pkg-config where it can find the `.pc` files containing the information. Say you
|
||||||
Say you installed GoogleTest to `/usr/local`, then it might be that the
|
installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
|
||||||
`.pc` files are installed under `/usr/local/lib64/pkgconfig`. If you set
|
installed under `/usr/local/lib64/pkgconfig`. If you set
|
||||||
|
|
||||||
```
|
```
|
||||||
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
|
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
|
||||||
|
@ -1,52 +1,51 @@
|
|||||||
|
|
||||||
|
|
||||||
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
||||||
|
|
||||||
# The Problem #
|
# The Problem
|
||||||
|
|
||||||
Template and macro libraries often need to define many classes,
|
Template and macro libraries often need to define many classes, functions, or
|
||||||
functions, or macros that vary only (or almost only) in the number of
|
macros that vary only (or almost only) in the number of arguments they take.
|
||||||
arguments they take. It's a lot of repetitive, mechanical, and
|
It's a lot of repetitive, mechanical, and error-prone work.
|
||||||
error-prone work.
|
|
||||||
|
|
||||||
Variadic templates and variadic macros can alleviate the problem.
|
Variadic templates and variadic macros can alleviate the problem. However, while
|
||||||
However, while both are being considered by the C++ committee, neither
|
both are being considered by the C++ committee, neither is in the standard yet
|
||||||
is in the standard yet or widely supported by compilers. Thus they
|
or widely supported by compilers. Thus they are often not a good choice,
|
||||||
are often not a good choice, especially when your code needs to be
|
especially when your code needs to be portable. And their capabilities are still
|
||||||
portable. And their capabilities are still limited.
|
limited.
|
||||||
|
|
||||||
As a result, authors of such libraries often have to write scripts to
|
As a result, authors of such libraries often have to write scripts to generate
|
||||||
generate their implementation. However, our experience is that it's
|
their implementation. However, our experience is that it's tedious to write such
|
||||||
tedious to write such scripts, which tend to reflect the structure of
|
scripts, which tend to reflect the structure of the generated code poorly and
|
||||||
the generated code poorly and are often hard to read and edit. For
|
are often hard to read and edit. For example, a small change needed in the
|
||||||
example, a small change needed in the generated code may require some
|
generated code may require some non-intuitive, non-trivial changes in the
|
||||||
non-intuitive, non-trivial changes in the script. This is especially
|
script. This is especially painful when experimenting with the code.
|
||||||
painful when experimenting with the code.
|
|
||||||
|
|
||||||
# Our Solution #
|
# Our Solution
|
||||||
|
|
||||||
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
||||||
Programming, or Practical Utility for Meta Programming, whichever you
|
Programming, or Practical Utility for Meta Programming, whichever you prefer) is
|
||||||
prefer) is a simple meta-programming tool for C++. The idea is that a
|
a simple meta-programming tool for C++. The idea is that a programmer writes a
|
||||||
programmer writes a `foo.pump` file which contains C++ code plus meta
|
`foo.pump` file which contains C++ code plus meta code that manipulates the C++
|
||||||
code that manipulates the C++ code. The meta code can handle
|
code. The meta code can handle iterations over a range, nested iterations, local
|
||||||
iterations over a range, nested iterations, local meta variable
|
meta variable definitions, simple arithmetic, and conditional expressions. You
|
||||||
definitions, simple arithmetic, and conditional expressions. You can
|
can view it as a small Domain-Specific Language. The meta language is designed
|
||||||
view it as a small Domain-Specific Language. The meta language is
|
to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and
|
||||||
designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
|
concise, making Pump code intuitive and easy to maintain.
|
||||||
for example) and concise, making Pump code intuitive and easy to
|
|
||||||
maintain.
|
|
||||||
|
|
||||||
## Highlights ##
|
## Highlights
|
||||||
|
|
||||||
* The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
|
* The implementation is in a single Python script and thus ultra portable: no
|
||||||
* Pump tries to be smart with respect to [Google's style guide](https://github.com/google/styleguide): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
|
build or installation is needed and it works cross platforms.
|
||||||
* The format is human-readable and more concise than XML.
|
* Pump tries to be smart with respect to
|
||||||
* The format works relatively well with Emacs' C++ mode.
|
[Google's style guide](https://github.com/google/styleguide): it breaks long
|
||||||
|
lines (easy to have when they are generated) at acceptable places to fit
|
||||||
|
within 80 columns and indent the continuation lines correctly.
|
||||||
|
* The format is human-readable and more concise than XML.
|
||||||
|
* The format works relatively well with Emacs' C++ mode.
|
||||||
|
|
||||||
## Examples ##
|
## Examples
|
||||||
|
|
||||||
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
|
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are
|
||||||
|
meta brackets, and `$$` starts a meta comment that ends with the line):
|
||||||
|
|
||||||
```
|
```
|
||||||
$var n = 3 $$ Defines a meta variable n.
|
$var n = 3 $$ Defines a meta variable n.
|
||||||
@ -71,7 +70,7 @@ $if i == 0 [[
|
|||||||
|
|
||||||
will be translated by the Pump compiler to:
|
will be translated by the Pump compiler to:
|
||||||
|
|
||||||
``` cpp
|
```cpp
|
||||||
// Foo0 does blah for 0-ary predicates.
|
// Foo0 does blah for 0-ary predicates.
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
class Foo0 {
|
class Foo0 {
|
||||||
@ -105,9 +104,10 @@ Func($for i + [[a$i]]);
|
|||||||
$$ The text between i and [[ is the separator between iterations.
|
$$ The text between i and [[ is the separator between iterations.
|
||||||
```
|
```
|
||||||
|
|
||||||
will generate one of the following lines (without the comments), depending on the value of `n`:
|
will generate one of the following lines (without the comments), depending on
|
||||||
|
the value of `n`:
|
||||||
|
|
||||||
``` cpp
|
```cpp
|
||||||
Func(); // If n is 0.
|
Func(); // If n is 0.
|
||||||
Func(a1); // If n is 1.
|
Func(a1); // If n is 1.
|
||||||
Func(a1 + a2); // If n is 2.
|
Func(a1 + a2); // If n is 2.
|
||||||
@ -115,32 +115,38 @@ Func(a1 + a2 + a3); // If n is 3.
|
|||||||
// And so on...
|
// And so on...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Constructs ##
|
## Constructs
|
||||||
|
|
||||||
We support the following meta programming constructs:
|
We support the following meta programming constructs:
|
||||||
|
|
||||||
| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
|
| `$var id = exp` | Defines a named constant value. `$id` is |
|
||||||
|:----------------|:-----------------------------------------------------------------------------------------------|
|
: : valid util the end of the current meta :
|
||||||
| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later. |
|
: : lexical block. :
|
||||||
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`. |
|
| :------------------------------- | :--------------------------------------- |
|
||||||
| `$($)` | Generates a single `$` character. |
|
| `$range id exp..exp` | Sets the range of an iteration variable, |
|
||||||
| `$id` | Value of the named constant or iteration variable. |
|
: : which can be reused in multiple loops :
|
||||||
| `$(exp)` | Value of the expression. |
|
: : later. :
|
||||||
| `$if exp [[ code ]] else_branch` | Conditional. |
|
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have |
|
||||||
| `[[ code ]]` | Meta lexical block. |
|
: : been defined earlier. `$id` is valid in :
|
||||||
| `cpp_code` | Raw C++ code. |
|
: : `code`. :
|
||||||
| `$$ comment` | Meta comment. |
|
| `$($)` | Generates a single `$` character. |
|
||||||
|
| `$id` | Value of the named constant or iteration |
|
||||||
|
: : variable. :
|
||||||
|
| `$(exp)` | Value of the expression. |
|
||||||
|
| `$if exp [[ code ]] else_branch` | Conditional. |
|
||||||
|
| `[[ code ]]` | Meta lexical block. |
|
||||||
|
| `cpp_code` | Raw C++ code. |
|
||||||
|
| `$$ comment` | Meta comment. |
|
||||||
|
|
||||||
**Note:** To give the user some freedom in formatting the Pump source
|
**Note:** To give the user some freedom in formatting the Pump source code, Pump
|
||||||
code, Pump ignores a new-line character if it's right after `$for foo`
|
ignores a new-line character if it's right after `$for foo` or next to `[[` or
|
||||||
or next to `[[` or `]]`. Without this rule you'll often be forced to write
|
`]]`. Without this rule you'll often be forced to write very long lines to get
|
||||||
very long lines to get the desired output. Therefore sometimes you may
|
the desired output. Therefore sometimes you may need to insert an extra new-line
|
||||||
need to insert an extra new-line in such places for a new-line to show
|
in such places for a new-line to show up in your output.
|
||||||
up in your output.
|
|
||||||
|
|
||||||
## Grammar ##
|
## Grammar
|
||||||
|
|
||||||
``` ebnf
|
```ebnf
|
||||||
code ::= atomic_code*
|
code ::= atomic_code*
|
||||||
atomic_code ::= $var id = exp
|
atomic_code ::= $var id = exp
|
||||||
| $var id = [[ code ]]
|
| $var id = [[ code ]]
|
||||||
@ -159,19 +165,26 @@ else_branch ::= $else [[ code ]]
|
|||||||
exp ::= simple_expression_in_Python_syntax
|
exp ::= simple_expression_in_Python_syntax
|
||||||
```
|
```
|
||||||
|
|
||||||
## Code ##
|
## Code
|
||||||
|
|
||||||
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still
|
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py).
|
||||||
very unpolished and lacks automated tests, although it has been
|
It is still very unpolished and lacks automated tests, although it has been
|
||||||
successfully used many times. If you find a chance to use it in your
|
successfully used many times. If you find a chance to use it in your project,
|
||||||
project, please let us know what you think! We also welcome help on
|
please let us know what you think! We also welcome help on improving Pump.
|
||||||
improving Pump.
|
|
||||||
|
|
||||||
## Real Examples ##
|
## Real Examples
|
||||||
|
|
||||||
You can find real-world applications of Pump in [Google Test](https://github.com/google/googletest/tree/master/googletest) and [Google Mock](https://github.com/google/googletest/tree/master/googlemock). The source file `foo.h.pump` generates `foo.h`.
|
You can find real-world applications of Pump in
|
||||||
|
[Google Test](https://github.com/google/googletest/tree/master/googletest) and
|
||||||
|
[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The
|
||||||
|
source file `foo.h.pump` generates `foo.h`.
|
||||||
|
|
||||||
## Tips ##
|
## Tips
|
||||||
|
|
||||||
* If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
|
* If a meta variable is followed by a letter or digit, you can separate them
|
||||||
* To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
|
using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper`
|
||||||
|
generate `Foo1Helper` when `j` is 1.
|
||||||
|
* To avoid extra-long Pump source lines, you can break a line anywhere you
|
||||||
|
want by inserting `[[]]` followed by a new line. Since any new-line
|
||||||
|
character next to `[[` or `]]` is ignored, the generated code won't contain
|
||||||
|
this new line.
|
||||||
|
Loading…
Reference in New Issue
Block a user