From 75547f902127f0e769742a26f0a534553ff0c124 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Mon, 18 Dec 2023 14:11:17 -0700 Subject: [PATCH 1/7] Add some debugging tips to the readmes --- .conda/README.md | 47 ++++++++++++++++++++++++++++++++++++- .github/workflows/README.md | 12 ++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/.conda/README.md b/.conda/README.md index dd9f7956e..ec2be7ada 100644 --- a/.conda/README.md +++ b/.conda/README.md @@ -165,4 +165,49 @@ conda activate fierro-dev ``` And then you have all of the dependencies necessary to successfully build Fierro from source. -These packages are `noarch: generic` packages, because they don't contain any architecture/OS specific build artifacts themselves. Whether or not you can install them on your system depends solely on the dependencies being available. \ No newline at end of file +These packages are `noarch: generic` packages, because they don't contain any architecture/OS specific build artifacts themselves. Whether or not you can install them on your system depends solely on the dependencies being available. + + +## Debugging Tips +Anaconda packages are great when they work, but debugging them can be a pain, since it takes so long (relatively) to initailize the build environment. If you find yourself having to debug a conda package, don't waste time and follow these tips: + + +### Inspect the build/host environments. +The intermediate build environments created can be found under `~/anaconda3/conda-bld/`. These are cleaned up if the build is successful, but are left for inspecting if it fails. Your intermediate environemnts might look something like `~/mambaforge/conda-bld/fierro-cpu_1702931506301`, and ones that are still around can be uncovered by running `conda env list`: +``` +# conda environments: +# + ~/anaconda3 +base * ~/mambaforge + ~/mambaforge/conda-bld/cross-apple-test_1699913171912/_build_env + ~/mambaforge/conda-bld/fierro-cpu_1702931083445/_build_env + ~/mambaforge/conda-bld/fierro-cpu_1702931506301/_build_env + ~/mambaforge/conda-bld/fierro-evpfft_1700005728459/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702567877996/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702568248715/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702569485778/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702571726755/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702572653009/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702573356532/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702581207071/_build_env + ~/mambaforge/conda-bld/fierro-heffte-cuda_1702582399999/_build_env + ~/mambaforge/conda-bld/fierro-voxelizer-py_1700001705130/_build_env + ~/mambaforge/conda-bld/fierro-voxelizer-py_1700003960166/_build_env + ~/mambaforge/conda-bld/fierro-voxelizer-py_1700006765747/_build_env +EVPFFT_MATAR ~/mambaforge/envs/EVPFFT_MATAR +... ... + +``` + +Under that build folder you will find 3 relevant things: +1. `_build_env` -- The environment where your "build" dependencies get installed (aka `$BUILD_PREFIX`) +2. `_h_env_placehold_placehold_placehold_placehold_placehold...` -- The environment where your "host" dependencies get installed, and where you install your package (aka `$PREFIX`). +3. `work` -- Where your source files are placed + where `conda_build.sh` (the exact script that is run) can be found. + +You can activate each of these environments or just inspect the installed packages with `conda list -p `. + +### Modify and rebuild under `work` +If you think you identified the issue, don't go back and try the package build again. First modify the intermediate build files and try the rebuild from there. If you think you are missing a host dependency, for example, run `conda install -p ` and rerun `work/conda_build.sh` to see if that fixes it. If you think you need to modify the build script, just change `conda_build.sh` and rerun. Once the package builds successfully, make sure to make you changes to the original `meta.yaml` and/or `build.sh` files and then try the package build again. + +### Targetting Cross Compiling +If you are having issues with the cross-compiling build targets, you can speicfically target just those by adding `--variants "{ target_platform: linux-aarch64 }"`. If you are using the `.conda/build_variants.yaml` file, you will need to comment out the variants you don't want to test. \ No newline at end of file diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 93bffff8f..8b310de57 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -60,3 +60,15 @@ The recipe_dir is the folder containing the conda build `meta.yaml` file as well The second is the package specific action that triggers off of package specific source code changes and invokes `build-conda-package` with the correct package recipe location and additional build variants. In the case of our source-in-repo packages, these trigger of off relevant source code changes. For other dependencies, where the source is not contained in the repo, we configure the actions for manual dispatch. + +# Debugging +Complex github actions can be very annoying to debug for two reasons: +1. The feedback loop is long/slow. Pushing changes to github and waiting for a runner to initialize can easily add ~5 mins to your feedback loop. +2. You don't have easy access to the runtime environment. Github automatically will unmount the docker image and be on its way if an action fails. + +We have some tools to deal with this, though. If you can run docker (not WSL1), you can use [act](https://github.com/nektos/act) to execute github actions locally. This is **much** faster for debugging things like action syntax. We also have a tool to deal with #2 that I have built into the `build-conda-package` action. We have a `debug` option that enables a special workflow step after the package building step. If the debug flag is set, we make use of the [tmate](https://github.com/mxschmitt/action-tmate) github action to create a temporary ssh host and wait for 30 minutes. On the github Actions page you can inspect the log and find something like: +``` +SSH: ssh bJV7VnwDn5NUzBn6fGrkJYQg9@nyc1.tmate.io +``` + +If you are the user that triggered the action, you can ssh into the docker container that was runing your build action. From there you can continue debugging. \ No newline at end of file From 25bc7a4886c5bf5fa0e16a815b8ace705ca600d0 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Mon, 18 Dec 2023 14:50:41 -0700 Subject: [PATCH 2/7] Update to create fierro-cpu github publishing action. --- .conda/fierro/cpu/build.sh | 19 +++++-------------- .conda/fierro/cpu/meta.yaml | 22 +++++++++++++--------- .github/workflows/publish-fierro-cpu.yaml | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/publish-fierro-cpu.yaml diff --git a/.conda/fierro/cpu/build.sh b/.conda/fierro/cpu/build.sh index b2c2cd210..b68615924 100755 --- a/.conda/fierro/cpu/build.sh +++ b/.conda/fierro/cpu/build.sh @@ -1,25 +1,16 @@ -export SRC_DIR=$(pwd) -mkdir -p build -cd build - -export MPI_FLAGS="--allow-run-as-root" - -if [ $(uname) == Linux ]; then - export MPI_FLAGS="$MPI_FLAGS;-mca;plm;isolated" -fi - # These flag variables are set by anaconda. source "$RECIPE_DIR/../../cross-compile-setup.sh" - -cmake -D CMAKE_BUILD_TYPE:STRING=RELEASE \ +mkdir build +cd build +cmake .. \ + -D CMAKE_BUILD_TYPE:STRING=RELEASE \ -D CMAKE_INSTALL_PREFIX:PATH=$PREFIX \ -D CMAKE_CXX_STANDARD:STRING=17 \ -D BUILD_PARALLEL_EXPLICIT_SOLVER=ON \ -D BUILD_IMPLICIT_SOLVER=ON \ -D BUILD_ELEMENTS=OFF \ - -D DISTRIBUTION=True \ + -D DISTRIBUTION=On \ $CMAKE_ARGS \ - $SRC_DIR \ -D CMAKE_CXX_FLAGS="$PATCHED_CXXFLAGS -fopenmp" \ -D MPI_C_COMPILER="$BUILD_PREFIX/bin/mpicc" \ -D MPI_CXX_COMPILER="$BUILD_PREFIX/bin/mpicxx" \ diff --git a/.conda/fierro/cpu/meta.yaml b/.conda/fierro/cpu/meta.yaml index 1a5688b42..cb522d5fb 100644 --- a/.conda/fierro/cpu/meta.yaml +++ b/.conda/fierro/cpu/meta.yaml @@ -1,5 +1,9 @@ {% set version = "1.0.0" %} -{% set compiler_version = "10.4.0" %} +{% set linux_compiler_version = "10.4.0" %} +{% set macos_compiler_version = "12" %} +# We need the same MPI version in build + host. +# So we have to specify it, unfortunately +{% set mpi_version = "4.1" %} package: name: fierro-cpu @@ -10,27 +14,27 @@ source: git_depth: 1 build: - number: 1 + number: 2 script_env: - PLATFORM={{ target_platform }} requirements: build: - cmake >=3.17.0 - - {{ compiler('c') }} ={{ compiler_version }} - - {{ compiler('cxx') }} ={{ compiler_version }} - - openmpi + - {{ compiler('c') }}={{ linux_compiler_version }} # [linux] + - {{ compiler('c') }}={{ macos_compiler_version }} # [osx] + - {{ compiler('cxx') }}={{ linux_compiler_version }} # [linux] + - {{ compiler('cxx') }}={{ macos_compiler_version }} # [osx] + - openmpi={{ mpi_version }} host: - - _openmp_mutex - - openmpi + - openmp + - openmpi={{ mpi_version }} - fierro-trilinos-cpu - elements run: - fierro-trilinos-cpu - mpi -#TODO: Add tests - about: home: https://github.com/lanl/Fierro license: BSD-3-Clause diff --git a/.github/workflows/publish-fierro-cpu.yaml b/.github/workflows/publish-fierro-cpu.yaml new file mode 100644 index 000000000..561447e42 --- /dev/null +++ b/.github/workflows/publish-fierro-cpu.yaml @@ -0,0 +1,15 @@ +name: 'Publish Fierro-CPU' + +on: + push: + paths: + - .conda/fierro/cpu/** + - .github/workflows/publish-fierro-cpu.yaml + workflow_dispatch: + +jobs: + publish: + uses: ./.github/workflows/build-conda-package.yaml + with: + recipe_dir: .conda/fierro/cpu + secrets: inherit From 4271d883777e716be44de4a30584105c74018c61 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Mon, 18 Dec 2023 15:40:08 -0700 Subject: [PATCH 3/7] look for llvm openmp on osx --- .conda/fierro/cpu/meta.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.conda/fierro/cpu/meta.yaml b/.conda/fierro/cpu/meta.yaml index cb522d5fb..99ba1a77b 100644 --- a/.conda/fierro/cpu/meta.yaml +++ b/.conda/fierro/cpu/meta.yaml @@ -27,7 +27,8 @@ requirements: - {{ compiler('cxx') }}={{ macos_compiler_version }} # [osx] - openmpi={{ mpi_version }} host: - - openmp + - openmp # [linux] + - llvm-openmp # [osx] - openmpi={{ mpi_version }} - fierro-trilinos-cpu - elements From 34348173973359a0152155a2eda97ed4e419cdf3 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Mon, 18 Dec 2023 15:46:40 -0700 Subject: [PATCH 4/7] Don't look for `openmp` for all CPU architectures. --- .conda/fierro/cpu/meta.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.conda/fierro/cpu/meta.yaml b/.conda/fierro/cpu/meta.yaml index 99ba1a77b..80e12407c 100644 --- a/.conda/fierro/cpu/meta.yaml +++ b/.conda/fierro/cpu/meta.yaml @@ -27,8 +27,8 @@ requirements: - {{ compiler('cxx') }}={{ macos_compiler_version }} # [osx] - openmpi={{ mpi_version }} host: - - openmp # [linux] - - llvm-openmp # [osx] + - _openmp_mutex # [linux] + - llvm-openmp # [osx] - openmpi={{ mpi_version }} - fierro-trilinos-cpu - elements From 090cf990739de76d6ff3e32cff9a4dcdbc1ab1e6 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Tue, 19 Dec 2023 09:00:51 -0700 Subject: [PATCH 5/7] add _LIBCPP_DISABLE_AVAILABILITY --- .conda/fierro/cpu/build.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.conda/fierro/cpu/build.sh b/.conda/fierro/cpu/build.sh index b68615924..58a902ee3 100755 --- a/.conda/fierro/cpu/build.sh +++ b/.conda/fierro/cpu/build.sh @@ -2,6 +2,11 @@ source "$RECIPE_DIR/../../cross-compile-setup.sh" mkdir build cd build + +# -D _LIBCPP_DISABLE_AVAILABILITY +# is added to the CXXFLAGS for MacOS builds. +# see https://conda-forge.org/docs/maintainer/knowledge_base.html#newer-c-features-with-old-sdk + cmake .. \ -D CMAKE_BUILD_TYPE:STRING=RELEASE \ -D CMAKE_INSTALL_PREFIX:PATH=$PREFIX \ @@ -11,7 +16,7 @@ cmake .. \ -D BUILD_ELEMENTS=OFF \ -D DISTRIBUTION=On \ $CMAKE_ARGS \ - -D CMAKE_CXX_FLAGS="$PATCHED_CXXFLAGS -fopenmp" \ + -D CMAKE_CXX_FLAGS="$PATCHED_CXXFLAGS -fopenmp -D_LIBCPP_DISABLE_AVAILABILITY" \ -D MPI_C_COMPILER="$BUILD_PREFIX/bin/mpicc" \ -D MPI_CXX_COMPILER="$BUILD_PREFIX/bin/mpicxx" \ -D VECTOR_ARCH_FLAGS="$VECTOR_ARCH_FLAGS" \ From 820d30e4078b849f065cad602537ee59ec94f2a3 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Tue, 19 Dec 2023 10:21:43 -0700 Subject: [PATCH 6/7] more sensible shared_ptr construction --- src/CLI/src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CLI/src/main.cpp b/src/CLI/src/main.cpp index a09949015..70cce4ada 100644 --- a/src/CLI/src/main.cpp +++ b/src/CLI/src/main.cpp @@ -11,10 +11,10 @@ #include std::vector> BACKENDS { - std::shared_ptr(new ParallelExplicit()), - std::shared_ptr(new ParallelImplicit()), - std::shared_ptr(new MeshBuilderBackend()), - std::shared_ptr(new VoxelizerBackend()), + std::shared_ptr(), + std::shared_ptr(), + std::shared_ptr(), + std::shared_ptr(), }; std::vector> find_fierro_backends() { From 015a66f06f5a73b3c393a1c4bcfe6317e8925670 Mon Sep 17 00:00:00 2001 From: Kevin Welsh Date: Tue, 19 Dec 2023 10:23:03 -0700 Subject: [PATCH 7/7] Add readme to the CLI just cause. --- src/CLI/README.md | 168 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/CLI/README.md diff --git a/src/CLI/README.md b/src/CLI/README.md new file mode 100644 index 000000000..9fb134b7e --- /dev/null +++ b/src/CLI/README.md @@ -0,0 +1,168 @@ +# Fiero Command Line Interface +This CLI package is a Fierro command line interface that is intended to act as a consolidated front-end for our Fierro backend tools. It provides a consistent interface and framework for exposing tools to the user. + +## Front-End +The front end here is built off of [argparse](https://github.com/p-ranav/argparse), which implements a language agnostic standard for simple command line interface design. It defines a syntax for programs from the command line with suitable helptext/defaults/post-processing. + +The Fierro-CLI implements two things: +1. Output directory -- A directory to run the program in. Outputs of the program will by default be put here if some other backend specific option is not specified. +2. Subcommands -- a list of argparse "subcommands" that each represent an available backend tool. + +Example: +``` +$ fierro -h + +Usage: fierro [--help] [--version] [--output VAR] {mesh-builder,parallel-explicit,parallel-implicit,voxelizer} + +Optional arguments: + -h, --help shows help message and exits + -v, --version prints version information and exits + -o, --output output directory for the program [default: "."] + +Subcommands: + mesh-builder Build rectangular or cylindrical mesh in 2 or 3 dimensions. Useful for setting up test problems. + parallel-explicit Use an explicit solution scheme to step the system. + parallel-implicit Use an implicit solution scheme to step the system. + voxelizer Take a mesh defined by an STL and turn it into a dense voxel grid represented by a VTK structured mesh. The extent of the grid is selected by taking the minimum and maximum extent of the mesh along each dimenison. Note: Only supports binary STL mesh inputs +``` + +## Backends +This Fierro-CLI package is designed to operate decoupled from backends. Each registered backend is an executable that may or may not be present in the system. + +### Registering Backends +To add a new backend, you only need to do a couple of steps. +#### 1. Implementing NewBackend.hpp +You should start by copying one of the existing backend.hpp files and implementing your new backend. We will use `VoxelizerBackend.hpp` as an example. + +You should derive from `FierroBackend` and tell the base class which executable name to look for +```c++ +#include "backend.hpp" +struct VoxelizerBackend: public FierroBackend { + VoxelizerBackend() : FierroBackend("fierro-voxelizer") { + ... + } + ... +}; +``` + +Then, in the constructor, setup your argparse command + +```c++ + +struct VoxelizerBackend: public FierroBackend { + VoxelizerBackend() : FierroBackend("fierro-voxelizer") { + + this->command = std::shared_ptr( + new argparse::ArgumentParser("voxelizer") // <--- This is the name that shows up under "Subcommands:" in the CLI + ); + + // Here you can add your arguments with their helptext. + this->command->add_argument("input-file") + .help("The binary STL file to voxelize.") + .action(absolute_fp); // <-- You can also add a post-processing command. In this case we convert the input filepath to an absolute one. + this->command->add_argument("output-name") + .help("The name of the VTK structured mesh output file."); + this->command->add_argument("x") + .help("The number of voxels along the X direction (int)."); + this->command->add_argument("y") + .help("The number of voxels along the Y direction (int)."); + this->command->add_argument("z") + .help("The number of voxels along the Z direction (int)."); + this->command->add_argument("use-index-space") + .help("Wether or not to output the VTK in index-space coordinates."); + + // Add a description for your subcommand + this->command->add_description( + "Take a mesh defined by an STL and turn it into a dense voxel grid represented by a VTK structured mesh. " + "The extent of the grid is selected by taking the minimum and maximum extent of the mesh along each dimenison. " + "Note: Only supports binary STL mesh inputs." + ); + } + ... +}; +``` + +Lastly you tell the CLI framework how to actually invoke the backend command. This is mostly just building a system command string and invoking it, but I suppose you could do whatever you want. +```c++ + +struct VoxelizerBackend: public FierroBackend { + ... + + /** + * Invoke the backend executable. + * Will throw an ArgumentException if the arguments aren't valid. + * + * @return Return code of the executable. + */ + int invoke() { + if (!exec_path.has_value()) + throw std::runtime_error("Cannot invoke executable without absolute path."); + + auto err = this->validate_arguments(); + if (err.has_value()) throw ArgumentException(err.value()); + + std::string sys_command; + sys_command = this->exec_path.value().string() + + " " + this->command->get("input-file") + + " " + this->command->get("output-name") + + " " + this->command->get("x") + + " " + this->command->get("y") + + " " + this->command->get("z") + + " " + this->command->get("use-index-space"); + + return system(sys_command.c_str()); + } +}; +``` + +You probably also want to add some validation to your input arguments. The voxelizer does this with a serparate function: + +```c++ +struct VoxelizerBackend: public FierroBackend { + ... + + /** + * Check that the arguments of the CLI are valid and make sense. + * + * Checks for explicit/implicit logical consistency. + * Checks that the mesh file is real and readable. + * Does not check that it is correctly formatted. + * + * @return An optional error. If the empty, the arguments are valid. + * + */ + std::optional validate_arguments() { + std::string msg = ""; + auto parser = this->command; + + // Here we just check if the input file is an actual file. + if (!file_exists(parser->get("input-file"))) { + msg = "Unable to find input file: " + parser->get("input-file"); + } + + if (msg.length() > 0) { + return std::optional(msg); + } + return {}; + } + ... +}; +``` + +Now you have a well defined backend. + + +#### 2. Plug it into the CLI framework +Head over to main.cpp and add your backend to the list of backends: +```c++ +std::vector> BACKENDS { + std::shared_ptr(), + std::shared_ptr(), + std::shared_ptr(), + std::shared_ptr(), + //std::shared_ptr() <-- Add yours here +}; + +``` + +Now you have everything set up, and it will automatically be picked up if its compiled and in the system. \ No newline at end of file