Modern Software Development For JUNO Offline Softw
Modern Software Development For JUNO Offline Softw
1051/epjconf/202429505015
CHEP 2023
Abstract.
The Jiangmen Underground Neutrino Observatory (JUNO), under construction in South
China, primarily aims to determine the neutrino mass hierarchy and to precise measure the
neutrino oscillation parameters. The data-taking is expected to start in 2024 and the detector
plans to run for more than 20 years. The development of the JUNO offline software (JUNOSW)
started in 2012, and it is quite challenging to maintain the JUNOSW for such a long time.
In the last ten years, tools such as Subversion, Trac, and CMT had been adopted for software
development. However, new stringent requirements came out, such as how to reduce the building
time for the whole project, how to deploy offline algorithms to an online environment, and how
to improve the code quality with code review and continuous integration. To meet the further
requirements of software development, modern development tools are evaluated for JUNOSW,
such as Git, GitLab, CMake, Docker, and Kubernetes. This contribution will present the
software development system based on these modern tools for JUNOSW and the functionalities
achieved: CMake macros are developed to simplify the build instructions for users; CMake
generator expressions are used to control the build flags for the online and offline environments;
a tool named git-junoenv is developed to help users partially checkout and build the software;
a script is used to build and deploy the software on the CVMFS server; a Docker image with
CVMFS client installed is created for continuous integration; a GitLab agent is set up to manage
GitLab runners in Kubernetes with all the configurations in a GitLab repository.
© The Authors, published by EDP Sciences. This is an open access article distributed under the terms of the Creative
Commons Attribution License 4.0 (https://creativecommons.org/licenses/by/4.0/).
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
Water pool
Earth magnetic
field compensation
coils
Photo-multiplier
tubes
Acrylic spherical
vessel filled with
liquid scintillator
Acrylic
supporting nodes
happen, such as adding binaries and large files into the SVN repository. One feature of
SVN is its immutable commit history, so the binaries or large files are stored permanently.
This can cause the backup of SVN repository take more disk spaces.
• There is a maintenance issue for the Bitten [10] based continuous integration. Bitten is
built on Trac, which consists of a master and several slaves. XML-based configuration files
need to be set up in the master. When a new commit is pushed to the master, a build task
will be created and dispatched to a slave according to the configurations. The slave invokes
the commands encoded in the XML when it receives a message from the master. The major
issue is that the latest version of Bitten is released in 2011 and only supports Python 2.
3
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
4. Software development
4.1. Migration to CMake
CMake macros and functions have been developed to put all the common functionalities in the
same place. As there are some existing conventions defined in CMT, some of them are used in
the CMake macros. According to the instructions in Modern CMake, the following rules have
been used in the software development with CMake:
• The source code, build directory and installation directory of a project are separated. Even
though CMT adopts a similar rule, CMT puts all the build directories under the package
directories. When moving to CMake, they are all separated to keep the source code clean.
An example is the source code generation for the event data model. When using CMT,
the files are generated in the source code directory, which causes the check-in by mistakes
sometimes. After moving to CMake, these files are generated under build directories.
• A project is organized into packages. A package consists of a header directory for public
interfaces, a source directory for the private headers and detailed implementation, a python
directory for exporting the library in Python, a share directory for the regularly used scripts,
and a test directory for the testing scripts.
• A CMake target is used when building a package. It is used to represent a shared library,
a module library or an executable. Its dependencies on the other different packages are
described by the other CMake targets. The CMake target properties are used to control
how a target is built instead of using global settings.
• CMake generator expression is used to control the flags instead of using the if statement in
CMake. This is useful when the same package is built for online and offline environments.
In this case, the linking libraries could be different. By using the generator expression, the
libraries could be enabled or disabled by checking an option defined in CMake.
• Macros PKG and EDM are developed to build a regular package and a package containing
event data model respectively. The macro EDM generates C++ source code and ROOT
dictionaries at the CMake configuration stage, and builds a shared library at build stage.
The macro PKG creates a shared library by default. If a module library needs to be created,
then an option MODULE is needed. If there is no library or executable created, a custom
target will be created to install the python and share directories.
• Environment variables of packages are collected in the macros PKG and EDM. By adding
package names to a global property in the project, all the information of a package could
be accessed, including the environment variables. A CMake script is used to create both
bash and tcsh scripts before installation. All the environment variables are added at the
end of the scripts.
• When a project is installed, a CMake config will be created automatically, including all the
targets within the same namespace. Another project needs to use the CMake config file to
locate the project and load the exported targets.
• The CMake commands and options are put in the build.sh script.
Below is an example of CMakeLists.txt for the package Geometry:
1 PKG ( Geometry
2 DEPENDS
3 Identifier
4 $ <$ < NOT :$ < BOOL : $ { BUILD_ONLINE } > >: Parameter >
4
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
In this example, the PKG declares the package name. As there are no explicit files to be compiled,
all the files under the source code directory will be used. As there is no option MODULE, a
shared library will be created. When compiling and building this package, it will depend on
several libraries, which are defined after option DEPENDS. As mentioned before, the target
names are used. Both Identifier and Parameter are from JUNOSW, while the others are from
external libraries. The target Parameter is not used if the software is built for online.
Below is another example of the build script, which consists of three steps:
1 function run - build () {
2 local installdir = $ ( install - dir )
3 local blddir = $ ( build - dir )
4 check - build - dir
5 check - install - dir
6 pushd $blddir
7
8 cmake .. $ ( check - var - enabled graphviz ) \
9 $ ( check - var - enabled withoec ) \
10 $ ( check - var - enabled online ) \
11 $ ( check - var - enabled PerformanceCheck ) \
12 - DCMA KE_C XX _STA NDAR D =17 \
13 - DCMAKE_BUILD_TYPE = $ ( cmake - build - type ) \
14 - DC M AKE _ IN ST AL L_ P RE F IX = $installdir \
15 || error : " ERROR Found during cmake stage . "
16 local njobs = - j$ ( nproc )
17 cmake -- build . $njobs || error : " ERROR Found during make stage . "
18 cmake -- install . || error : " ERROR Found during make install stage . "
19
20 popd
21 }
5
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
After both partial checkout and build are working, a shell script called git-junoenv is created.
By prefixing git in the command name, this command could become a sub-command of git.
Below is an example when using it:
1 $ git junoenv init - project junosw && cd junosw # get the junosw without packages
2 $ git junoenv list - pkgs # list all the available packages
3 $ git junoenv add - pkg Reconstruction / OMILREC # add a package
When users need to develop with JUNOSW, the first step is using init-project to clone the
code from the official repository. In order to hide all the packages, both sparse and no-checkout
options are used during the git clone. After cloning, the script will check out the CMake-related
code and initialize the CMake file of users. Then, users could list all the available packages in the
project. The command git ls-files is used to list all the directories containing CMakeLists.txt.
Users could use add-pkg to checkout and enable the package.
5. Software deployment
5.1. junoenv: the installation script
The installation script junoenv is inspired by the ENV project [17], which collects all the
necessary installation scripts in the same repository. There are more than 50 scripts for building
external libraries, and about 30 libraries are deployed in the official release. Modularized bash
functions are used to describe the metadata of the external libraries. When installing a package,
the script junoenv loads the metadata of the package and drives the installation of it. There are
five steps defined during the installation:
• get: download the source code by cURL, wget or git;
• conf: configure the package;
• make: build the package;
• install: install the package;
• setup: create setup scripts for both bash and tcsh.
Five corresponding common bash functions are in charge of these steps. If additional
configuration is needed, the package can define its own functions to override the default functions.
Following is an example:
1 function juno - ext - libs - cmake - conf - {
2 local msg = " ===== $FUNCNAME : "
3 # begin to configure
4 echo $msg ./ bootstrap -- prefix = $ ( juno - ext - libs - cmake - install - dir )
5 ./ bootstrap -- prefix = $ ( juno - ext - libs - cmake - install - dir )
6 }
7 function juno - ext - libs - cmake - conf {
8 juno - ext - libs - PKG - conf cmake
9 }
This is used to configure the package CMake. As the CMake does not use the configure
script by default, an additional function suffixed with a dash is defined to override the
default behavior. So the invoking procedure is: junoenv invokes the conf function of CMake,
named juno-ext-libs-cmake-conf; then this function invokes the common function, named
juno-ext-libs-PKG-conf; the common function then invokes the overridden function.
Reproducible is important during the deployment. For a dedicated release of JUNOSW, the
versions of all external libraries need to be recorded. In order to track all of them, a shell script
is used to collect them. When deploying a release, the corresponding script is loaded. The shell
6
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
script self is created by invoking the vlist command, which prints all the installed packages
and their versions. Below is an example of this script:
1 function juno - ext - libs - git - version - { echo 2.37.3 ; }
2 function juno - ext - libs - cmake - version - { echo 3.24.1 ; }
3 function juno - ext - libs - python - version - { echo 3.9.14 ; }
4 function juno - ext - libs - python - setuptools - version - { echo 58.1.0 ; }
5 function juno - ext - libs - python - pip - version - { echo 22.2.2 ; }
All the software is deployed into CVMFS. When deploying the software, the installation
prefix could be different from the original one when building software. For most packages, it
is not an issue. However, there are still several packages that hardcode the paths, such as
physics generators. Inspired by the package manager spack [18], the paths during building and
deployment are set as the same length, and they are replaced using the tool sed when deployed
into CVMFS.
The benefit is that the Docker image could be reused when upgrading the external libraries.
In the above example, only the JUNOTOP needs to be updated in the YAML file.
7
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023
are set up in a self-hosted Kubernetes cluster. GitLab agents are used to connect Gitlab and
Kubernetes. Then the Gitlab runners are managed by the Gitlab agents. All the configurations
are managed in GitLab repositories.
The GitLab agent is set up as below.
1 gitops :
2 mani fest_p roject s :
3 - id : JUNO / offline / gitlab - agent
4 defa ult_na mespac e : junooffline
5 paths :
6 - glob : ’ manifests /*.{ yaml , json } ’
7 - glob : ’ /**/*.{ yaml , json } ’
8
9 ci_access :
10 groups :
11 - id : JUNO / offline
Then GitLab runners are installed with the cluster management project, which is a Git
repository. The configuration of GitLab runner is enabled first, then the runners will be set up
automatically.
1 repositories :
2 - name : gitlab
3 url : https :// charts . gitlab . io
4
5 releases :
6 - name : runner
7 namespace : gitlab - managed - apps
8 chart : gitlab / gitlab - runner
9 version : 0.44.0
10 installed : true
11 values :
12 - values . yaml . gotmpl
6. Conclusions
The tools used for JUNO software development have been migrated from CMT and SVN to
CMake, Git/GitLab, Docker and Kubernetes. Some additional scripts have been also developed
to help the users. In late 2022, all the migration had been done. More than 160 members are
available in the JUNO GitLab. In the past nine months, more than 300 Merge Requests have
been merged into the official JUNOSW repository, and more than 2,400 pipelines have been
executed with a success ratio of 92.04%.
Acknowledgments
This work is supported by National Natural Science Foundation of China (12375195, 12025502,
11805223), the Strategic Priority Research Program of the Chinese Academy of Sciences (Grant
No. XDA10010900), and Youth Innovation Promotion Association, CAS.
References
[1] Djurcic Z et al. (JUNO) 2015 (Preprint 1508.07166)
[2] An F et al. (JUNO) 2016 J. Phys. G43 030401 (Preprint 1507.05613)
[3] Abusleme A et al. (JUNO) 2022 Prog. Part. Nucl. Phys. 123 103927
[4] Lin T et al. 2023 Eur. Phys. J. C 83 382 [Erratum: Eur.Phys.J.C 83, 660 (2023)] (Preprint 2212.10741)
[5] Zou J H, Huang X T, Li W D, Lin T, Li T, Zhang K, Deng Z Y and Cao G F 2015 J. Phys. Conf. Ser. 664
072053
[6] Barrand G et al. 2001 Comput. Phys. Commun. 140 45–55
[7] Apache Subversion https://subversion.apache.org
8
EPJ Web of Conferences 295, 05015 (2024) https://doi.org/10.1051/epjconf/202429505015
CHEP 2023