FEniCS / dolfinx

Next generation FEniCS problem solving environment
https://fenicsproject.org
GNU Lesser General Public License v3.0
769 stars 182 forks source link

Start a "How to contribute" guide in the docs #3365

Open RemDelaporteMathurin opened 2 months ago

RemDelaporteMathurin commented 2 months ago

Currently the only developer resources are C++ guidelines.

I recently wanted to test a PR and used this dockerfile to create a container within which I could run some tests.

FROM ghcr.io/fenics/dolfinx/dolfinx:nightly

ARG CMAKE_NUM_PROCESSES=4
ARG DOLFINX_MODE=real
ARG DOLFINX_PRECISION=64
ARG DOLFINX_CMAKE_CXX_FLAGS="-march=native"
ARG BUILD_TYPE=Developer

ENV DOLFINX_DIR=/usr/local/dolfinx-${DOLFINX_MODE}${DOLFINX_PRECISION}
WORKDIR /src

RUN git clone --branch=dokken/improve-mixed-packing --single-branch https://github.com/fenics/dolfinx.git
RUN CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES} cmake -G Ninja -B build-dir-${DOLFINX_MODE}${DOLFINX_PRECISION} -DCMAKE_INSTALL_PREFIX=${DOLFINX_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_FLAGS="${DOLFINX_CMAKE_CXX_FLAGS}" -S ./dolfinx/cpp

RUN CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES} cmake --build build-dir-${DOLFINX_MODE}${DOLFINX_PRECISION}
RUN cmake --install build-dir-${DOLFINX_MODE}${DOLFINX_PRECISION}
RUN python3 -m pip -v install --check-build-dependencies --config-settings=build-dir="build-${DOLFINX_CMAKE_BUILD_TYPE}-${DOLFINX_MODE}-${DOLFINX_PRECISION}" --config-settings=install.strip=false --config-settings=cmake.build-type="${DOLFINX_CMAKE_BUILD_TYPE}" --config-settings=cmake.define.CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES}  --no-build-isolation -e ./dolfinx/python/

We could adapt this Dockerfile to install any branch/commit to easily test PRs.

Would it be worth adding a section to Developer resources with this as an alternative to build everything locally? What do people think?

ampdes commented 2 months ago

The following gist by @jorgensd is also helpful:

https://gist.github.com/jorgensd/e1984f6055b0f91197be6e406f0c901f

jorgensd commented 1 month ago

To properly install any branch one needs slightly more control than the above:

# Build dolfinx from scratch with custom branches defined through user arguments
# Author: Jørgen S. Dokken
FROM ghcr.io/fenics/dolfinx/dev-env:current

ARG DOLFINX_BRANCH=main
ARG UFL_BRANCH=main
ARG FFCX_BRANCH=main
ARG BASIX_BRANCH=main

ARG CMAKE_NUM_PROCESSES=4
ARG DOLFINX_MODE=real
ARG DOLFINX_PRECISION=64
ARG DOLFINX_CMAKE_CXX_FLAGS="-march=native"
ARG BUILD_TYPE=Developer

ENV DOLFINX_DIR=/usr/local/dolfinx-${DOLFINX_MODE}${DOLFINX_PRECISION}
ENV PETSC_DIR=/usr/local/petsc
ENV PETSC_ARCH=linux-gnu-${DOLFINX_MODE}${DOLFINX_PRECISION}-32
ENV CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES}
ENV CMAKE_PREFIX_PATH=${DOLFINX_DIR}/lib/cmake

WORKDIR /src

RUN pip install --no-cache-dir nanobind scikit-build-core[pyproject]

# Install UFL
RUN git clone --branch=${UFL_BRANCH} --single-branch https://github.com/fenics/ufl.git && \
    python3 -m pip install -e ./ufl

# Install basix
RUN git clone --branch=${BASIX_BRANCH} --single-branch https://github.com/fenics/basix.git
RUN cmake -G Ninja -B build-dir-basix -DCMAKE_INSTALL_PREFIX=${DOLFINX_DIR} -DCMAKE_BUILD_TYPE="Release" -S ./basix/cpp
RUN cmake --build  build-dir-basix
RUN cmake --install  build-dir-basix
RUN python3 -m pip -v install --check-build-dependencies --config-settings=build-dir=build-dir-basix --config-settings=install.strip=false --config-settings=cmake.build-type="Release" --config-settings=cmake.define.CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES}  --no-build-isolation -e ./basix/python/

# Install FFCx
RUN git clone --branch=${FFCX_BRANCH} --single-branch https://github.com/fenics/ffcx.git && \
    python3 -m pip install ./ffcx

# Install DOLFINx
RUN git clone --branch=${DOLFINX_BRANCH} --single-branch https://github.com/fenics/dolfinx.git
RUN cmake -G Ninja -B build-dir-${DOLFINX_MODE}-${DOLFINX_PRECISION} -DCMAKE_INSTALL_PREFIX=${DOLFINX_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_FLAGS="${DOLFINX_CMAKE_CXX_FLAGS}" -S ./dolfinx/cpp

RUN cmake --build build-dir-${DOLFINX_MODE}-${DOLFINX_PRECISION}
RUN cmake --install build-dir-${DOLFINX_MODE}-${DOLFINX_PRECISION}
RUN python3 -m pip -v install --check-build-dependencies --config-settings=build-dir="build-${DOLFINX_CMAKE_BUILD_TYPE}-${DOLFINX_MODE}-${DOLFINX_PRECISION}" --config-settings=install.strip=false --config-settings=cmake.build-type="${DOLFINX_CMAKE_BUILD_TYPE}" --config-settings=cmake.define.CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_NUM_PROCESSES}  --no-build-isolation -e ./dolfinx/python/
jhale commented 1 month ago

The above approaches do not allow for editing of the source on the host and require a complete rebuild on every docker build .. Additionally dev-env has PETSc build in Release mode which is not ideal for development.

Instead I would recommend:

  1. Checking out the FEniCS components into the current working directory on the host.

  2. Running

    docker run -ti -v $(pwd):/shared -w /shared  -e PETSC_ARCH=linux-gnu-real64-32 ghcr.io/fenics/test-env:current-mpich
  3. Inside the container standard pip install -e . for basix, ufl, ffcx.

  4. Inside the container mkdir build/ && cd build/ && cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../ && ninja install for dolfinx/cpp.

  5. Inside the container pip install -r build-requirements.txt and then pip install --check-build-dependencies --no-build-isolation -e . for dolfinx/python.

You can also write a script that does this and put it in the root of /shared.

Note that editable installs are still a bit broken for basix and dolfinx which use scikit-build-core - check its documentation for more information.

RemDelaporteMathurin commented 1 month ago

Aren't we running pip install -e . twice here? (once in 3. and again in 4.)

jorgensd commented 1 month ago

The above approaches do not allow for editing of the source on the host and require a complete rebuild on every docker build .. Additionally dev-env has PETSc build in Release mode which is not ideal for development.

Instead I would recommend:

1. Checking out the FEniCS components into the current working directory on the host.

2. Running
   ```
    docker run -ti -v $(pwd):/shared -w /shared  -e PETSC_ARCH=linux-gnu-real64-32 ghcr.io/fenics/test-env:current-mpich
   ```

3. Inside the container standard `pip install -e .` for `basix`, `ufl`, `ffcx`.

4. Inside the container `mkdir build/ && cd build/ && cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../ && ninja install` for `dolfinx/cpp`.

5. Inside the container `pip install -r build-requirements.txt` and then `pip install --check-build-dependencies --no-build-isolation -e .` for `dolfinx/python`.

You can also write a script that does this and put it in the root of /shared.

Note that editable installs are still a bit broken for basix and dolfinx which use scikit-build-core - check its documentation for more information.

The file above is more for the use-case:

  1. I have a feature in a pull request that I would like someone else to test (maybe because they discovered a bug on a complex use-cases, that has been distilled down to a MWE).
  2. The developer of the PR do not have access to the original MWE (for whatever reason) or do not have bandwidth to test it.
  3. The container above would give them a chance to do a one-time test of that env.

I agree that for a long-term dev env, I wouldn't recommend the approach above, and that there are many different use-cases and ways to develop, and personally I use something closer to what @jhale has suggested (as also shown in the notes)

The following gist by @jorgensd is also helpful:

https://gist.github.com/jorgensd/e1984f6055b0f91197be6e406f0c901f

jorgensd commented 1 month ago

Aren't we running pip install -e . twice here? (once in 3. and again in 4.)

We run it for bsaix, ufl and ffcx first, and then dolfinx.

jhale commented 1 month ago

There is a shortcut to 'build a container with a particular version':

https://github.com/FEniCS/dolfinx/blob/main/docker/Dockerfile.end-user#L33

Feedback on the overall experience would be welcome.