DaanDeMeyer / reproc

A cross-platform (C99/C++11) process library
MIT License
552 stars 65 forks source link
c cmake cpp cross-platform library posix processes windows

reproc

What is reproc?

reproc (Redirected Process) is a cross-platform C/C++ library that simplifies starting, stopping and communicating with external programs. The main use case is executing command line applications directly from C or C++ code and retrieving their output.

reproc consists out of two libraries: reproc and reproc++. reproc is a C99 library that contains the actual code for working with external programs. reproc++ depends on reproc and adapts its API to an idiomatic C++11 API. It also adds a few extras that simplify working with external programs from C++.

Features

Usage

#include <reproc/run.h>

int main(void)
{
  const char *args[] = { "echo", "Hello, world!", NULL };
  return reproc_run(args, (reproc_options) { 0 });
}

Questions

If you have any questions after reading the readme and documentation you can either make an issue or ask questions directly in the reproc gitter channel.

Installation

Note: Building reproc requires CMake 3.12 or higher.

There are multiple ways to get reproc into your project. One way is to build reproc as part of your project using CMake. To do this, we first have to get the reproc source code into the project. This can be done using any of the following options:

After including reproc's source code in your project, it can be built from the root CMakeLists.txt file as follows:

add_subdirectory(<path-to-reproc>) # For example: add_subdirectory(external/reproc)

CMake options can be specified before calling add_subdirectory:

set(REPROC++ ON)
add_subdirectory(<path-to-reproc>)

Note: If the option has already been cached in a previous CMake run, you'll have to clear CMake's cache to apply the new default value.

For more information on configuring reproc's build, see CMake options.

You can also depend on an installed version of reproc. You can either build and install reproc yourself or install reproc via a package manager. reproc is available in the following package repositories:

If using a package manager is not an option, you can build and install reproc from source (CMake 3.13+):

cmake -B build
cmake --build build
cmake --install build

Enable the REPROC_TEST option and build the test target to run the tests (CMake 3.13+):

cmake -B build -DREPROC_TEST=ON
cmake --build build
cmake --build build --target test

After installing reproc your build system will have to find it. reproc provides both CMake config files and pkg-config files to simplify finding a reproc installation using CMake and pkg-config respectively. Note that reproc and reproc++ are separate libraries and as a result have separate config files as well. Make sure to search for the one you want to use.

To find an installed version of reproc using CMake:

find_package(reproc) # Find reproc.
find_package(reproc++) # Find reproc++.

After building reproc as part of your project or finding a installed version of reproc, you can link against it from within your CMakeLists.txt file as follows:

target_link_libraries(myapp reproc) # Link against reproc.
target_link_libraries(myapp reproc++) # Link against reproc++.

From Meson 0.53.2 onwards, reproc can be included as a CMake subproject in Meson build scripts. See https://mesonbuild.com/CMake-module.html for more information.

Dependencies

By default, reproc has a dependency on pthreads on POSIX systems (-pthread) and a dependency on Winsock 2.2 on Windows systems (-lws2_32). CMake and pkg-config handle these dependencies automatically.

CMake options

reproc's build can be configured using the following CMake options:

User

Advanced

Developer

Documentation

Each function and class is documented extensively in its header file. Examples can be found in the examples subdirectory of reproc and reproc++.

Error handling

On failure, Most functions in reproc's API return a negative errno (POSIX) or GetLastError (Windows) style error code. For actionable errors, reproc provides constants (REPROC_ETIMEDOUT, REPROC_EPIPE, ...) that can be used to match against the error without having to write platform-specific code. To get a string representation of an error, pass it to reproc_strerror.

reproc++'s API integrates with the C++ standard library error codes mechanism (std::error_code and std::error_condition). Most methods in reproc++'s API return std::error_code values that contain the actual system error that occurred. You can test against these error codes using values from the std::errc enum.

See the examples for more information on how to handle errors when using reproc.

Note:

Both reproc and reproc++ APIs take options argument that may define one or more stop actions such as terminate or kill. For that reason if the child process is being terminated or killed using a signal on POSIX, the error code will not reflect an error.

It's up to the downstream project to interpret status codes reflecting unexpected behaviors alongside error codes (see this example).

Multithreading

Don't call the same operation on the same child process from more than one thread at the same time. For example: reading and writing to a child process from different threads is fine but waiting on the same child process from two different threads at the same time will result in issues.

Gotchas