Skip to content
P4_16 prototype compiler
C++ Python C CMake P4 LLVM Other
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
backends Support table.apply().miss (#2051) Nov 6, 2019
cmake Revert "remove test_args from p4c_add_test_with_args, always pass arg… Nov 1, 2019
control-plane Add pthreads to move to protobuf v3.6.1 (#2047) Oct 9, 2019
docs Add a useful link to the p4c developer docs (#1893) Apr 24, 2019
frontends Support table.apply().miss (#2051) Nov 6, 2019
ir IR/json support for bitvec fields (#2078) Nov 7, 2019
lib IR/json support for bitvec fields (#2078) Nov 7, 2019
midend Support table.apply().miss (#2051) Nov 6, 2019
p4include Make argument in only; fixes #2057 (#2061) Oct 22, 2019
test IR/json support for bitvec fields (#2078) Nov 7, 2019
testdata Support table.apply().miss (#2051) Nov 6, 2019
tools WIP: Add non-unified builds to Travis (#2031) Oct 28, 2019
.dockerignore Exclude some unnecessary files from the Docker image Apr 10, 2017
.gdbinit Move exit; statement to actions in actionSynthesis (#1920) May 5, 2019
.gitignore add ior/xor operators to IR::Constant (#1594) Nov 7, 2018
.gitmodules Remove PI submodule and use p4runtime instead Oct 22, 2018
.travis.yml Do unified and non-unified builds in separate Travis instances (#2076) Oct 31, 2019
CMakeLists.txt Update version to match language specification (#2059) Nov 7, 2019
CPPLINT.cfg Remove unreasonable cpplint casting check Sep 8, 2017
Dockerfile WIP: Add non-unified builds to Travis (#2031) Oct 28, 2019
LICENSE Update LICENSE Dec 17, 2016 Add Dec 17, 2016 Update first paragraph of README to no longer say alpha-quality (#2081) Nov 11, 2019 removes automake build Jul 22, 2017

Build Status


p4c is a reference compiler for the P4 programming language. It supports both P4-14 and P4-16; you can find more information about P4 here and the specifications for both versions of the language here. One fact attesting to the level of quality and completeness of p4c's code is that its front-end code, mid-end code, and p4c-graphs back end are used as the basis for at least one commercially supported P4 compiler.

p4c is modular; it provides a standard frontend and midend which can be combined with a target-specific backend to create a complete P4 compiler. The goal is to make adding new backends easy.

The code contains four sample backends:

  • p4c-bm2-ss: can be used to target the P4 simple_switch written using the BMv2 behavioral model
  • p4c-ebpf: can be used to generate C code which can be compiled to EBPF and then loaded in the Linux kernel for packet filtering
  • p4test: a source-to-source P4 translator which can be used for testing, learning compiler internals and debugging.
  • p4c-graphs: can be used to generate visual representations of a P4 program; for now it only supports generating graphs of top-level control flows.

Sample command lines:

Compile P4_16 or P4_14 source code. If your program successfully compiles, the command will create files with the same base name as the P4 program you supplied, and the following suffixes instead of the .p4:

  • a file with suffix .p4i, which is the output from running the preprocessor on your P4 program.
  • a file with suffix .json that is the JSON file format expected by BMv2 behavioral model simple_switch.
p4c --target bmv2 --arch v1model my-p4-16-prog.p4
p4c --target bmv2 --arch v1model --std p4-14 my-p4-14-prog.p4

By adding the option --p4runtime-files <filename>.txt as shown in the example commands below, p4c will also create a file <filename>.txt. This is a text format "P4Info" file, containing a description of the tables and other objects in your P4 program that have an auto-generated control plane API.

p4c --target bmv2 --arch v1model --p4runtime-files my-p4-16-prog.p4info.txt my-p4-16-prog.p4
p4c --target bmv2 --arch v1model --p4runtime-files my-p4-14-prog.p4info.txt --std p4-14 my-p4-14-prog.p4

All of these commands take the --help argument to show documentation of supported command line options. p4c --target-help shows the supported "target, arch" pairs.

p4c --help
p4c --target-help

Auto-translate P4_14 source to P4_16 source:

p4test --std p4-14 my-p4-14-prog.p4 --pp auto-translated-p4-16-prog.p4

Check syntax of P4_16 or P4_14 source code, without limitations that might be imposed by any particular compiler back end. There is no output for these commands other than error and/or warning messages.

p4test my-p4-16-prog.p4
p4test --std p4-14 my-p4-14-prog.p4

Generate GraphViz ".dot" files for parsers and controls of a P4_16 or P4_14 source program.

p4c-graphs my-p4-16-prog.p4
p4c-graphs --std p4-14 my-p4-14-prog.p4

Generate PDF of parser instance named "ParserImpl" generated by the p4c-graphs command above (search for graphviz below for its install instructions):

dot -Tpdf > ParserImpl.pdf

Getting started

  1. Clone the repository. It includes submodules, so be sure to use --recursive to pull them in:

    git clone --recursive

    If you forgot --recursive, you can update the submodules at any time using:

    git submodule update --init --recursive
  2. Install dependencies. You can find specific instructions for Ubuntu 16.04 here and for macOS 10.12 here.

  3. Build. Building should also take place in a subdirectory named build.

    mkdir build
    cd build
    cmake .. <optional arguments>
    make -j4
    make -j4 check

    The cmake command takes the following optional arguments to further customize the build:

    • -DCMAKE_BUILD_TYPE=RELEASE|DEBUG -- set CMAKE_BUILD_TYPE to RELEASE or DEBUG to build with optimizations or with debug symbols to run in gdb. Default is RELEASE.
    • -DCMAKE_INSTALL_PREFIX=<path> -- set the directory where make install installs the compiler. Defaults to /usr/local.
    • -DENABLE_BMV2=ON|OFF. Enable the bmv2 backend. Default ON.
    • -DENABLE_EBPF=ON|OFF. Enable the ebpf backend. Default ON.
    • -DENABLE_P4C_GRAPHS=ON|OFF. Enable the p4c-graphs backend. Default ON.
    • -DENABLE_P4TEST=ON|OFF. Enable the p4test backend. Default ON.
    • -DENABLE_DOCS=ON|OFF. Build documentation. Default is OFF.
    • -DENABLE_GC=ON|OFF. Enable the use of the garbage collection library. Default is ON.
    • -DENABLE_GTESTS=ON|OFF. Enable building and running GTest unit tests. Default is ON.
    • -DENABLE_PROTOBUF_STATIC=ON|OFF. Enable the use of static protobuf libraries. Default is ON.

    If adding new targets to this build system, please see instructions.

  4. (Optional) Install the compiler and the P4 shared headers globally.

    sudo make install

    The compiler driver p4c and binaries for each of the backends are installed in /usr/local/bin by default; the P4 headers are placed in /usr/local/share/p4c.

  5. You're ready to go! You should be able to compile a P4-16 program for BMV2 using:

    p4c -b bmv2-ss-p4org program.p4 -o program.bmv2.json

If you plan to contribute to p4c, you'll find more useful information here.


Ubuntu 16.04 is the officially supported platform for p4c. There's also unofficial support for macOS 10.12. Other platforms are untested; you can try to use them, but YMMV.

  • A C++11 compiler. GCC 4.9 or later or Clang 3.3 or later is required.

  • git for version control

  • GNU autotools for the build process

  • CMake 3.0.2 or higher

  • Boehm-Weiser garbage-collector C++ library

  • GNU Bison and Flex for the parser and lexical analyzer generators.

  • Google Protocol Buffers 3.0 or higher for control plane API generation

  • GNU multiple precision library GMP

  • C++ boost library (minimally used)

  • Python 2.7 for scripting and running tests

  • Optional: Documentation generation (enabled when configuring with --enable-doxygen-doc) requires Doxygen (1.8.10 or higher) and Graphviz (2.38.0 or higher).

Backends may have additional dependencies. The dependencies for the backends included with p4c are documented here:

Ubuntu dependencies

Most dependencies can be installed using apt-get install:

sudo apt-get install cmake g++ git automake libtool libgc-dev bison flex libfl-dev libgmp-dev libboost-dev libboost-iostreams-dev libboost-graph-dev llvm pkg-config python python-scapy python-ipaddr python-ply tcpdump

For documentation building: sudo apt-get install -y doxygen graphviz texlive-full

An exception is Google Protocol Buffers; p4c depends on version 3.0 or higher, which is not available until Ubuntu 16.10. For earlier releases of Ubuntu, you'll need to install from source. You can find instructions here. We recommend that you use version 3.2.0. Earlier versions in the 3 series may not be supported by other p4lang projects, such as p4lang/PI. More recent versions may work as well, but all our CI testing is done with version 3.2.0. After cloning protobuf and before you build, check-out version 3.2.0:

git checkout v3.2.0

Please note that while all protobuf versions newer than 3.0 should work for p4c itself, you may run into trouble with some extensions and other p4lang projects unless you install version 3.2.0, so you may want to install from source even on newer releases of Ubuntu.

macOS dependencies

Installing on macOS:

  • Enable XCode's command-line tools:

    xcode-select --install
  • Install Homebrew:

    /usr/bin/ruby -e "$(curl -fsSL"

    Be sure to add /usr/local/bin/ to your $PATH.

  • Install dependencies using Homebrew:

    brew install autoconf automake libtool bdw-gc boost bison pkg-config

    Install GMP built in C++11 mode:

    brew install gmp --c++11

    By default, Homebrew doesn't link programs into /usr/local/bin if they would conflict with a version provided by the base system. This includes Bison, since an older version ships with macOS. make check depends on the newer Bison we just installed from Homebrew (see #83), so you'll want to add it to your $PATH one way or another. One simple way to do that is to request that Homebrew link it into /usr/local/bin:

    brew link --force bison

    Optional documentation building tools:

    brew install doxygen graphviz

    Homebrew offers a protobuf formula. It installs version 3.2, which should work for p4c itself but may cause problems with some extensions. It's preferable to install Protocol Buffers 3.0 from source using the instructions here. Check out the newest tag in the 3.0 series (v3.0.2 as of this writing) before you build.

Garbage collector

P4c relies on BDW garbage collector to manage its memory. By default, the p4c exectuables are linked with the garbage collector library. In rare cases when the GC causes problems, this can be disabled by setting ENABLE_GC cmake option to OFF. However, this will dramatically increase the memory usage by the compiler, and may become impractical for compiling large programs. Do not disable the GC, unless you really have to.

Development tools

There is a variety of design and development documentation here.

We recommend using clang++ with no optimizations for speeding up compilation and simplifying debugging.

We recommend installing a new version of gdb., because older gdb versions do not always handle C++11 correctly.

We recommend exuberant ctags for navigating source code in Emacs and vi. sudo apt-get install exuberant-ctags. The Makefile targets make ctags and make etags generate tags for vi and Emacs respectively. (Make sure that you are using the correct version of ctags; there are several competing programs with the same name in existence.)

To enable building code documentation, please run cmake .. -DENABLE_DOCS=ON. This enables the make docs rule to generate documentation. The HTML output is available in build/doxygen-out/html/index.html.


A Dockerfile is included. You can generate an image which contains a copy of p4c in /p4c/build by running:

docker build -t p4c .

On some platforms Docker limits the memory usage of any container, even containers used during the docker build process. On macOS in particular the default is 2GB, which is not enough to build p4c. Increase the memory limit to at least 4GB via Docker preferences or you are likely to see "internal compiler errors" from gcc which are caused by low memory.

Build system

The build system is based on cmake. This section describes how it can be customized.

Defining new CMake targets

When building a new backend target, add it into the development tree in the extensions subdirectory. The cmake-based build system will automatically include it if it contains a CMakeLists.txt file.

For a new backend, the cmake file should contain the following rules:

IR definition files

Backend specific IR definition files should be added to the global list of IR_DEF_FILES as they are processed together with the core IR files. Use the following rule:


where MY_IR_DEF_FILES is a list of file names with absolute path (for example, use ${CMAKE_CURRENT_SOURCE_DIR}).

If in addition you have additional supporting source files, they should be added to the frontend sources, as follows:


Again, MY_IR_SRCS is a list of file names with absolute path.

Source files

Sources (.cpp and .h) should be added to the cpplint target using the following rule:


where mybackend is the name of the directory you added under extensions. The p4c CMakeLists.txt will use that name to figure the full path of the files to lint.


Define a target for your executable. The target should link against the core P4C_LIBRARIES and P4C_LIB_DEPS. P4C_LIB_DEPS are package dependencies. If you need additional libraries for your project, add them to P4C_LIB_DEPS.

In addition, your target should depend on the genIR target, since you need all the IR generation to happen before you start compiling your backend. If you chose to have your backend as a library (seem the backends/bmv2 example), the library should depend on genIR, and there is no longer necessary for your executable to depend on it.

add_executable(p4c-mybackend ${MY_SOURCES})
target_link_libraries (p4c-mybackend ${P4C_LIBRARIES} ${P4C_LIB_DEPS})
add_dependencies(p4c-mybackend genIR)


We implemented support equivalent to the automake make check rules. All tests should be included in make check and in addition, we support make check-* rules. To enable this support, add the following rules:

set(MY_DRIVER <driver or compiler executable>)

p4c_add_tests("mybackend" ${MY_DRIVER} "${MY_TEST_SUITES}" "${MY_XFAIL_TESTS}")

In addition, you can add individual tests to a suite using the following macro:

set(isXFail FALSE)
set(SWITCH_P4 testdata/p4_14_samples/switch_20160512/switch.p4)

p4c_add_test_with_args ("mybackend" ${MY_DRIVER} ${isXFail}
  "switch_with_custom_profile" ${SWITCH_P4} "-DCUSTOM_PROFILE")

See the documentation for p4c_add_test_with_args and p4c_add_tests for more information on the arguments to these macros.

To pass custom arguments to p4c, you can set the environment variable P4C_ARGS:

make check P4C_ARGS="-Xp4c=MY_CUSTOM_FLAG"


Define rules to install your backend. Typically you need to install the binary, the additional architecture headers, and the configuration file for the p4c driver.

install (TARGETS p4c-mybackend
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/driver/p4c.mybackend.cfg

Known issues

The P4C compiler is in early development. Issues with the compiler are tracked on GitHub. Before opening a new issue, please check whether a similar issue is already opened. Opening issues and submitting a pull request with fixes for those issues is much appreciated.

In addition to the list of issues on Github, there are a number of currently unsupported features listed below:


P4_14 features not supported in P4_16

  • extern/blackbox attributes -- there is support for carrying them in the IR, but they are lost if P4_16 code is output. Backends can access them from the IR

  • Nonstandard extension primitives from P4_14

    • Execute_meter extra arguments
    • Recirculate variants
    • Bypass_egress
    • Sample_ primitives
    • invalidate
  • No support for P4_14 parser exceptions.


Bmv2 Backend

  • Range "set" not supported in parser transitions
  • Tables with multiple apply calls

See also unsupported P4_16 language features.

You can’t perform that action at this time.