.. _ContributingToLibcxx:

======================
Contributing to libc++
======================

This file contains information useful when contributing to libc++. If this is your first time contributing,
please also read `this document <https://www.llvm.org/docs/Contributing.html>`__ on general rules for
contributing to LLVM.

If you plan on contributing to libc++, it can be useful to join the ``#libcxx`` channel
on `LLVM's Discord server <https://discord.gg/jzUbyP26tQ>`__.

Looking for pre-existing pull requests
======================================

Before you start working on any feature, please take a look at the open libc++ pull
requests to avoid duplicating someone else's work. You can do that on GitHub by
filtering pull requests `tagged with libc++ <https://github.com/llvm/llvm-project/pulls?q=is%3Apr+is%3Aopen+label%3Alibc%2B%2B>`__.
If you see that your feature is already being worked on, please consider chiming in
and helping review the code instead of duplicating work!

RFCs for significant user-affecting changes
===========================================

Before you start working on a change that can have significant impact on users of the library,
please consider creating a RFC on the `libc++ forum <https://discourse.llvm.org/c/runtimes/libcxx>`_.
This will ensure that you work in a direction that the project endorses and will ease reviewing your
contribution as directional questions can be raised early. Including a WIP patch is not mandatory,
but it can be useful to ground the discussion in something concrete.

Writing tests and running the test suite
========================================

Every change in libc++ must come with appropriate tests. Libc++ has an extensive test suite that
should be run locally by developers before submitting patches and is also run as part of our CI
infrastructure. The documentation about writing tests and running them is :ref:`here <testing>`.

Coding Guidelines
=================

libc++'s coding guidelines are documented :ref:`here <CodingGuidelines>`.


Resources
=========

Libc++ specific
---------------

- ``libcxx/include/__config`` -- this file contains the commonly used
  macros in libc++. Libc++ supports all C++ language versions. Newer versions
  of the Standard add new features. For example, making functions ``constexpr``
  in C++20 is done by using ``_LIBCPP_CONSTEXPR_SINCE_CXX20``. This means the
  function is ``constexpr`` in C++20 and later. The Standard does not allow
  making this available in C++17 or earlier, so we use a macro to implement
  this requirement.
- ``libcxx/test/support/test_macros.h`` -- similar to the above, but for the
  test suite.


ISO C++ Standard
----------------

Libc++ implements the library part of the ISO C++ standard. The official
publication must be bought from ISO or your national body. This is not
needed to work on libc++, there are other free resources available.

- The `LaTeX sources <https://github.com/cplusplus/draft>`_  used to
  create the official C++ standard. This can be used to create your own
  unofficial build of the standard.

- An `HTML rendered version of the draft <https://eel.is/c++draft/>`_  is
  available. This is the most commonly used place to look for the
  wording of the standard.

- An `alternative <https://github.com/timsong-cpp/cppwp>`_ is available.
  This link has both recent and historic versions of the standard.

- When implementing features, there are
  `general requirements <https://eel.is/c++draft/#library>`_.
  Most papers use this
  `jargon <http://eel.is/c++draft/structure#specifications>`_
  to describe how library functions work.

- The `WG21 redirect service <https://wg21.link/>`_ is a tool to quickly locate
  papers, issues, and wording in the standard.

- The `paper trail <https://github.com/cplusplus/papers/issues>`_ of
  papers is publicly available, including the polls taken. It
  contains links to the minutes of paper's discussion. Per ISO rules,
  these minutes are only accessible by members of the C++ committee.

- `Feature-Test Macros and Policies
  <https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations>`_
  contains information about feature-test macros in C++.
  It contains a list with all feature-test macros, their versions, and the paper
  that introduced them.

- `cppreference <https://en.cppreference.com/w/>`_ is a good resource
  for the usage of C++ library and language features. It's easier to
  read than the C++ Standard, but it lacks details needed to properly implement
  library features.


Pre-commit check list
=====================

Before committing or creating a review, please go through this check-list to make
sure you don't forget anything:

- Do you have :ref:`tests <testing>` for every public class and/or function you're adding or modifying?
- Did you update the synopsis of the relevant headers?
- Did you update the relevant files to track implementation status (in ``docs/Status/``)?
- Did you mark all functions and type declarations with the :ref:`proper visibility macro <visibility-macros>`?
- Did you add all new named declarations to the ``std`` module?
- If you added a header:

  - Did you add it to ``include/module.modulemap.in``?
  - Did you add it to ``include/CMakeLists.txt``?
  - If it's a public header, did you update ``utils/libcxx/header_information.py``?

- Did you add the relevant feature test macro(s) for your feature? Did you update the ``generate_feature_test_macro_components.py`` script with it?
- Did you run the ``libcxx-generate-files`` target and verify its output?
- If needed, did you add ``_LIBCPP_PUSH_MACROS`` and ``_LIBCPP_POP_MACROS`` to the relevant headers?

The review process
==================

After uploading your patch, you should see that the "libc++" review group is automatically
added as a reviewer for your patch. Once the group is marked as having approved your patch,
you can commit it. However, if you get an approval very quickly for a significant patch,
please try to wait a couple of business days before committing to give the opportunity for
other reviewers to chime in. If you need someone else to commit the patch for you, please
mention it and provide your ``Name <email@domain>`` for us to attribute the commit properly.

Note that the rule for accepting as the "libc++" review group is to wait for two members
of the group to have approved the patch, excluding the patch author. This is not a hard
rule -- for very simple patches, use your judgement. The `"libc++" review group <https://reviews.llvm.org/project/members/64/>`__
consists of frequent libc++ contributors with a good understanding of the project's
guidelines -- if you would like to be added to it, please reach out on Discord.

Some tips:

- Keep the number of formatting changes in patches minimal.
- Provide separate patches for style fixes and for bug fixes or features. Keep in
  mind that large formatting patches may cause merge conflicts with other patches
  under review. In general, we prefer to avoid large reformatting patches.
- Keep patches self-contained. Large and/or complicated patches are harder to
  review and take a significant amount of time. It's fine to have multiple
  patches to implement one feature if the feature can be split into
  self-contained sub-tasks.

Exporting new symbols from the library
======================================

When exporting new symbols from libc++, you must update the ABI lists located in ``lib/abi``.
To test whether the lists are up-to-date, please run the target ``check-cxx-abilist``.
To regenerate the lists, use the target ``generate-cxx-abilist``.
The ABI lists must be updated for all supported platforms; currently Linux and
Apple.  If you don't have access to one of these platforms, you can download an
updated list from the failed build at
`Buildkite <https://buildkite.com/llvm-project/libcxx-ci>`__.
Look for the failed build and select the ``artifacts`` tab. There, download the
abilist for the platform, e.g.:

* C++<version>.
* macOS X86_64 and macOS arm64 for the Apple platform.


Pre-commit CI
=============

Introduction
------------

Unlike most parts of the LLVM project, libc++ uses a pre-commit CI [#]_. Some of
this CI is hosted on `Buildkite <https://buildkite.com/llvm-project/libcxx-ci>`__,
but some has migrated to the LLVM CI infrastructure. The build results are
visible in the review on GitHub. Please make sure the CI is green before
committing a patch.

The CI tests libc++ for all :ref:`supported platforms <SupportedPlatforms>`.
The build is started for every commit added to a Pull Request. A complete CI
run takes approximately one hour. To reduce the load:

* The build is cancelled when a new commit is pushed to a PR that is already running CI.
* The build is done in several stages and cancelled when a stage fails.

Typically, the libc++ jobs use a Ubuntu Docker image. This image contains
recent `nightly builds <https://apt.llvm.org>`__ of all supported versions of
Clang and the current version of the ``main`` branch. These versions of Clang
are used to build libc++ and execute its tests.

Unless specified otherwise, the configurations:

* use a nightly build of the ``main`` branch of Clang,
* execute the tests using the language C++<latest>. This is the version
  "developed" by the C++ committee.

.. note:: Updating the Clang nightly builds in the Docker image is a manual
   process and is done at an irregular interval on purpose. When you need to
   have the latest nightly build to test recent Clang changes, ask in the
   ``#libcxx`` channel on `LLVM's Discord server
   <https://discord.gg/jzUbyP26tQ>`__.

.. [#] There's `LLVM Dev Meeting talk <https://www.youtube.com/watch?v=B7gB6van7Bw>`__
   explaining the benefits of libc++'s pre-commit CI.

Builds
------

Below is a short description of the most interesting CI builds [#]_:

* ``Format`` runs ``clang-format`` and uploads its output as an artifact. At the
  moment this build is a soft error and doesn't fail the build.
* ``Generated output`` runs the ``libcxx-generate-files`` build target and
  tests for non-ASCII characters in libcxx. Some files are excluded since they
  use Unicode, mainly tests. The output of these commands are uploaded as
  artifact.
* ``Documentation`` builds the documentation. (This is done early in the build
  process since it is cheap to run.)
* ``C++<version>`` these build steps test the various C++ versions, making sure all
  C++ language versions work with the changes made.
* ``Clang <version>`` these build steps test whether the changes work with all
  supported Clang versions.
* ``Booststrapping build`` builds Clang using the revision of the patch and
  uses that Clang version to build and test libc++. This validates the current
  Clang and lib++ are compatible.

  When a crash occurs in this build, the crash reproducer is available as an
  artifact.

* ``Modular build`` tests libc++ using Clang modules [#]_.
* ``GCC <version>`` tests libc++ with the latest stable GCC version. Only C++11
  and the latest C++ version are tested.
* ``Santitizers`` tests libc++ using the Clang sanitizers.
* ``Parts disabled`` tests libc++ with certain libc++ features disabled.
* ``Windows`` tests libc++ using MinGW and clang-cl.
* ``Apple`` tests libc++ on macOS.
* ``ARM`` tests libc++ on various Linux ARM platforms.
* ``AIX`` tests libc++ on AIX.

.. [#] Not all steps are listed: steps are added and removed when the need arises.
.. [#] Clang modules are not the same as C++20's modules.

Infrastructure
--------------

The files for the CI infrastructure are split between the llvm-project
and the llvm-zorg repositories. All files of the CI infrastructure in
the llvm-project are in the directory ``libcxx/utils/ci``. Note that
quite a bit of this infrastructure is heavily Linux focused. This is
the platform used by most of libc++'s Buildkite runners and
developers.

Dockerfile/Container Images
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Contains the Docker image for the Ubuntu CI. Because the same Docker image is
used for the ``main`` and ``release`` branch, it should contain no hard-coded
versions. It contains the used versions of Clang, various clang-tools,
GCC, and CMake.

.. note:: This image is pulled from Docker hub and not rebuild when changing
   the Dockerfile.

Updating the CI testing container images
----------------------------------------

The libcxx linux premerge testing can run on one of three sets of runner
groups. The three runner group names are ``llvm-premerge-libcxx-runners``,
``llvm-premerge-libcxx-release-runners`` and ``llvm-premerge-libcxx-next-runners``.
The runner set currently in use is controlled by the contents of
https://github.com/llvm/llvm-project/blob/main/.github/workflows/libcxx-build-and-test.yaml.
By default, it uses ``llvm-premerge-libcxx-runners``. To switch to one of the
other runner sets, just replace all uses of ``llvm-premerge-libcxx-runners`` in
the yaml file with the desired runner set.

The container image used by these three runner sets is controlled by the contents
of the corresponding text files in ``libcxx/utils/ci/images``. The content of these
files is read by the `Terraform configuration in llvm-zorg
<https://github.com/llvm/llvm-zorg/blob/main/premerge/premerge_resources/main.tf>`__.

When updating the container image, you can either update just the runner binary (the part
that connects to Github), or you can update everything (tools, etc.). To update the runner
binary, bump the value of ``GITHUB_RUNNER_VERSION`` in ``libcxx/utils/ci/docker/docker-compose.yml``.
To update all of the tools, bump ``BASE_IMAGE_VERSION`` to a newer version of the ``libcxx-linux-builder-base``
image. You can see all versions of that image at https://github.com/llvm/llvm-project/pkgs/container/libcxx-linux-builder-base.

On push to ``main``, a new version of both the ``libcxx-linux-builder`` and the ``libcxx-android-builder``
images will be built and pushed to https://github.com/llvm/llvm-project/packages.

You can then update the image used by the actual runners by changing the image encoded in
``libcxx/utils/ci/images`` and asking an LLVM premerge maintainer (a Google employee) to
actually deploy the changes to the GKE cluster via Terraform.

Monitoring premerge testing performance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The llvm-premerge-libcxx runners mentioned above collect metrics regarding the
time the tests spend queued up before they start running and also the time it
takes the tests to actually complete running. These metrics are collected and
aggregated (based on stage and PR), and the results can be seen at the
`Libc++ Premerge Testing dashboard
<https://llvm.grafana.net/public-dashboards/0bd453e8b3034733a1b0ff8c7728086d>`__
.

run-buildbot-container
~~~~~~~~~~~~~~~~~~~~~~

Helper script that pulls and runs the Docker image. This image mounts the LLVM
monorepo at ``/llvm``. This can be used to test with compilers not available on
your system.

run-buildbot
~~~~~~~~~~~~

This is the script executed by the CI runners. This script can be executed
locally or inside ``run-buildbot-container``. The script must be called with
the target to test. For example, ``run-buildbot generic-cxx20`` will build
libc++ and test it using C++20.

.. warning:: This script will overwrite the directory ``<llvm-root>/build/XX``
  where ``XX`` is the target of ``run-buildbot``.

This script contains as little version information as possible. This makes it
easy to use the script with a different compiler. This allows testing a
combination not in the libc++ CI. It can be used to add a new (temporary)
job to the CI. For example, testing the C++17 build with Clang-14 can be done
like:

.. code-block:: bash

  CC=clang-14 CXX=clang++-14 run-buildbot generic-cxx17

buildkite-pipeline.yml
~~~~~~~~~~~~~~~~~~~~~~

Contains the jobs executed in the CI. This file contains the version
information of the jobs being executed. Since this script differs between the
``main`` and ``release`` branch, both branches can use different compiler
versions.
