@@ -49,12 +49,12 @@ which will open a new
4949webpage from GitHub from which you can select where you would like to create the project. You can also get to this
5050page through the GitHub interface:
5151
52- <p align =" center " ><img src =" img/GitHubTemplate.png " alt =" EESSI filesystem layer " width =" 600px " /></p >
52+ <p align =" center " ><img src =" img/GitHubTemplate.png " alt =" EESSI CI/CD demo template repository " width =" 600px " /></p >
5353
5454Once GitHub has created a project for you from the template, you can _ clone_ the project to the local resource that
5555you wish to use (your laptop, a cluster,...) by copying the relevant command from the GitHub interface:
5656
57- <p align =" center " ><img src =" img/GitHubRepo.png " alt =" EESSI filesystem layer " width =" 600px " /></p >
57+ <p align =" center " ><img src =" img/GitHubRepo.png " alt =" Cloning our GitHub repository " width =" 600px " /></p >
5858
5959For example, for the repository shown in the image, the full command is
6060``` { .bash .no-copy}
@@ -104,7 +104,7 @@ Some characteristics of the project are
104104 - The project uses a build tool called [ ` CMake ` ] ( https://cmake.org/ ) for building. Many software projects use this tool to help with
105105 the logistical challenge of building complex software.
106106 - This introduces another dependency on ` CMake ` itself which we only require during the building of the project.
107- Such dependencies are often called _ buildtime dependencies_ .
107+ Such dependencies are often called _ build-time dependencies_ .
108108- Testing
109109 - ` CMake ` has some features that allow for the running of tests that are included in our software project. This
110110 gives us an easy way to check both that our software runs, and that it gives correct results, without us needing
@@ -175,7 +175,7 @@ Currently Loaded Modules:
175175That's now a long of packages which make up the _ runtime dependency tree_ of ` HDF5 ` . That dependency tree includes
176176` OpenMPI/5.0.8-GCC-14.3.0 ` which means the list already satisfies the runtime requirements for our software package.
177177
178- However, we are still missing our _ build time dependency_ ` CMake ` . Can EESSI also provide that? Let's check with
178+ However, we are still missing our _ build- time dependency_ ` CMake ` . Can EESSI also provide that? Let's check with
179179``` { .bash .copy}
180180module spider cmake
181181```
@@ -217,7 +217,7 @@ We don't have any reason to choose one over the other, so let's go with the most
217217module load CMake/4.0.3-GCCcore-14.3.0
218218```
219219
220- With this module loaded, we now have all both our buildtime and runtime dependencies satisfied, and can proceed to
220+ With this module loaded, we now have all both our build-time and runtime dependencies satisfied, and can proceed to
221221build our project.
222222
223223### First attempt at building and testing our project
@@ -352,12 +352,82 @@ Our output is full of errors like
352352```
353353What went wrong?
354354
355- ### Why did our build fail the tests?
355+ ## Why did our build fail the tests when using EESSI ?
356356
357357To understand where the failure is coming from, we first need to understand what actually happens when we try to run a
358- program on a computer.
358+ program on a computer. Our applications that we want to run take up space in memory, but many of them share parts of
359+ their dependency tree. For example, every application built with the ` GCC ` compiler, require the ` GCC ` compiler runtime
360+ libraries. Have every executable we run have a copy of that library built in is a waste of space in memory, since all
361+ programs need exactly the same library.
362+
363+ To save space (and to allow us to upgrade the libraries), dynamically linked
364+ programs used _ shared libraries_ . A runtime loader in Linux (often called the dynamic linker/loader) is
365+ responsible for loading shared libraries required by a program when it starts.
366+ It resolves symbols and links the program to the correct library functions and variables at runtime.
367+ This allows multiple programs to share the same libraries in memory and enables libraries to be updated independently
368+ of applications.
369+
370+ <p align =" center " ><img src =" img/runtime-loader.png " alt =" Runtime loader " width =" 600px " /></p >
371+
372+ The runtime loader is perhaps the most critical part of any operating system, as it controls the behaviour of most
373+ applications on any system
374+
375+ ### What affects the behaviour of the runtime loader?
376+
377+ There are a few things that can impact the behaviour of the runtime loader:
378+
379+ * Hints in the environment about where to look for our shared libraries. ` LD_LIBRARY_PATH ` in particular is typically
380+ used to influence the behaviour of the runtime loader.
381+ * Information can be stoed directly in the library/application that you are trying to load. At compile time, we can
382+ store information about the paths to search when looking for libraries. This can be done in such a way that it can
383+ be overridden by ` LD_LIBRARY_PATH ` (` RUNPATH ` linking), or in a way where ` LD_LIBRARY_PATH ` has no influence
384+ (` RPATH ` linking).
385+ * The runtime loader also has default locations it searchs for libraries. These are used as a last resort.
386+
387+ For a given application or library, we can inspect what the runtime loader will resolve the the shared libraries to
388+ using the command ` ldd ` . For our failed build, we can do this on the binary ` hello_mpi_hdf5 ` , which was created by our
389+ build (and mentioned in some of our errors):
390+ ``` { .bash .no-copy}
391+ {EESSI/2025.06} $ ldd hello_mpi_hdf5
392+ linux-vdso.so.1 (0x0000f1bedad95000)
393+ libmpi.so.40 => /cvmfs/software.eessi.io/versions/2025.06/software/linux/aarch64/neoverse_n1/software/OpenMPI/5.0.8-GCC-14.3.0/lib/libmpi.so.40 (0x0000f1bedaa10000)
394+ libhdf5_cpp.so.310 => not found
395+ libhdf5.so.310 => not found
396+ ...
397+ ```
398+ While a lot of libraries are listed, we note that only two of them are not found: the ones related to ` HDF5 ` ! Why not
399+ though? Why couldn't the runtime loader find them? For that we need to think again about how EESSI works.
400+
401+ ### EESSI ships its own runtime loader
402+
403+ The reason EESSI is like a container is because when it builds and ships applications and libraries, it tells them to
404+ use the runtime loader from the EESSI compatibility layer, not from the local operating system. This is what gives us
405+ independence from the underlying operating system.
406+
407+ However, because EESSI needs to live side-by-side with the underlying operating system,
408+ we cannot use ` LD_LIBRARY_PATH ` to find libraries (as setting this also affects the behaviour of the host runtime
409+ loader, which may break things). EESSI therefore must use ` RPATH ` -linking for all of the programs it ships in the
410+ software layer.
411+
412+ We can inspect the RPATH information encoded in a libary using a tool called ` patchelf ` (which is
413+ shipped in EESSI):
414+ ``` { .bash .no-copy }
415+ {EESSI/2025.06} ocaisa@~/EESSI/cicd-demo/build(main)$ patchelf --print-rpath hello_mpi_hdf5
416+ /cvmfs/software.eessi.io/versions/2025.06/software/linux/aarch64/neoverse_n1/software/OpenMPI/5.0.8-GCC-14.3.0/lib
417+ ```
418+ So there is some information in the RPATH header of our executable that tells it where to find the MPI libraries
419+ (and it _ does_ find them as we saw in our ` ldd ` output), but there is nothing there to tell it where to find the
420+ ` HDF5 ` libraries.
421+
422+ To inject this information we need to give hints to the compiler that this information is required _ inside_ the binary.
423+ This is very tedious though if we are building lots of applications with lots of different dependencies, so instead we
424+ use _ compiler wrappers_ to automatically inject this information based on the modules we have loaded at the time we
425+ do the compilation.
426+
427+ This is done by default for everything that EESSI itself ships, but when building software manually with EESSI, we
428+ need to activate these wrappers.
359429
360- ### Using the ` buildenv ` module
430+ ## Using the ` buildenv ` module
361431
362- ### Building our project
432+ ## Building our software project (Part 2)
363433
0 commit comments