# Small Yet Configurable: Unveiling Null Variability in Software

Xhevahire Tërnava, Georges Aaron Randrianaina, Luc Lesoil, Mathieu Acher

► To cite this version:

Xhevahire Tërnava, Georges Aaron Randrianaina, Luc Lesoil, Mathieu Acher. Small Yet Configurable: Unveiling Null Variability in Software. 2025. hal-05097580

HAL Id: hal-05097580

https://hal.science/hal-05097580v1

Preprint submitted on 4 Jun 2025

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
# Small Yet Configurable: Unveiling Null Variability in Software

Xhevahire Tërnava

LTCI, Télécom Paris, Institut Polytechnique de Paris
Palaiseau, France
xhevahire.ternava@telecom-paris.fr

Luc Lesoil

Univ Rennes, CNRS, Inria, IRISA
UMR 6074, F-35000 Rennes, France
luc.lesoil@irisa.fr

Georges Aaron Randrianaina

Univ Rennes, CNRS, Inria, IRISA
UMR 6074, F-35000 Rennes, France
georges-aaron.randrianaina@irisa.fr

Mathieu Acher

Univ Rennes, CNRS, Inria, IRISA
Institut Universitaire de France (IUF)
UMR 6074, F-35000 Rennes, France
mathieu.acher@irisa.fr

## ABSTRACT

Many small-scale software systems, that is, with limited codebase or binary size, are widely used in everyday tasks, yet their configurability remains largely unexplored. At the same time, studies on modern software systems show a trend toward increasing configurability, alongside growing interest in building immutable, specialized, and reproducible software. In this paper, we present the first empirical study on the extent of configurability in small-scale software systems. By analyzing 108 programs from GNU coreutils, we show that even small programs can exhibit significant compile-time and run-time variability, with up to 76 options per program. Then, there is a high correlation (0.78) between run-time variability and codebase size. Furthermore, an analysis of the 20 smallest programs across 85 releases reveals that variability tends to increase over time, primarily due to the added compile-time variability. This suggests that shifting options between run-time and compile-time, removing unnecessary run-time variability, or resolving compile-time variability early, can help reduce codebase complexity and size. We also introduce, for the first time, the concept of null-variable software system, one with no configurability beyond mandatory features. Our findings show that high configurability is not exclusive to large-scale systems and that reducing unnecessary variability can lead to lightweight, smaller, and more maintainable software. We hope this effort contributes to designing new software by understanding how to balance its configurability with codebase size.

## CCS CONCEPTS

* Software and its engineering → Software product lines; Software configuration management;

## KEYWORDS

software variability, null-variable software, small-scale software

## 1 INTRODUCTION

Since the software crisis in 1968 [33], significant advances have been reached in the development of variability-intensive software systems. Nowadays, software systems are highly configurable and expose to users their abundant configuration options. These options make possible to customize a software system for usage in different contexts [10], without the need to modify its source code. At the code level, most of the options are set at compile-time or run-time [9, 10], for example, as command-line parameters in C-based

systems. Moreover, variability is often recognized as a strength of a software as users have the flexibility to adapt it to their needs.

However, software systems are becoming more and more configurable, such as Linux kernel with more than 20 thousand of options and a configuration space (i.e., possible variants of Linux) of more than atoms in the universe [3, 25, 32, 37]. This ultra-large scale of variability is exceeding the human and even machine limits to deal with it, for example, to test and maintain it [1, 17, 51]. The ultimate and reasonable goal of researchers and developers today is how to address, manage, evolve, and reduce this large and increasing software variability. To our knowledge, the extent of variability and configurability in small-scale software is seldom analyzed, and the notion of a completely invariant system remains undefined.

Actually, motivated by this gap, we asked several questions. What is the extent of variability in small-scale software systems, compared to the extensive configurability of large-scale systems? Is configurability also an important characteristic of small-scale software? Do software systems exist that exhibit little to no noticeable variability? There are studies that have used small-scale software, simplified versions of larger systems, or excerpts from their feature models, for various purposes, such as evaluating variability implementation approaches [6, 31] or debloating software systems [8]. But, in our knowledge, there is no work that explores such questions. In addition, the field of software engineering has traditionally focused on configurability and adaptability, leaving systems with no variability largely unexplored. While terms like "static", "immutable", or "constant" software are occasionally used<fnref n="1" />, there is no formal concept to describe systems designed to lack configurability, representing the antithesis of configurable systems.

Herein, we empirically investigate the extent of variability in small-scale software by analyzing 108 programs from coreutils<fnref n="2" /> and 85 releases across 20 of its programs spanning the years 2003 to 2022, including programs such as `ls`, `cat`, and `mkdir`. Most of these programs have implementation histories dating back to 1979 [18]. Our findings show that even small-scale software programs exhibit significant variability, with up to 76 configuration options and an average configuration space of 2¹⁵. Moreover, we observed that run-time and compile-time variability have distinct roles in the dynamics of software systems. While runtime variability impacts

<footnote n="1">¹https://sonalake.com/latest/the-future-is-minimal-and-immutable-a-new-generation-of-operating-systems/</footnote>

<footnote n="2">²GNU core utilities: https://www.gnu.org/software/coreutils/</footnote>
the size of a program’s codebase at a specific point in time, compile-time variability appears to drive the growth of the codebase over time. Additionally, we identify two strategies for reducing codebase size, both centered on removing unnecessary runtime variability.

The main contributions of this paper are as follows:

* We present the first empirical study on the extent of variability in small-scale software, unlike previous studies that focus on large, complex configurable software systems or explore small-scale software for other purposes.

* To the best of our knowledge, we are the first to explicitly introduce and define the concept of null-variable software.

* All the data and code to replicate our study are available at https://github.com/ternava/zero-variability.

The remainder of this paper is structured as follows. We first provide the background (Section 2) and motivation (Section 3). Then, we present our empirical study (Section 4) with four research questions, examining the size and variability of over 108 programs. We report on the variability, correlation with system size, evolution, and reduction in Section 5, and discuss the results in Section 6. In Section 7 we define null software variability, threats to validity in Section 8, related work in Section 9, and conclude in Section 10.

## 2 BACKGROUND

Variability-intensive software systems. Software systems that are built nowadays require and exhibit variability, commonly understood as the ability of a software system or artifact to be efficiently extended, changed, customized, or configured for use in a particular context [10, 43]. Software variability is often studied in the context of software reuse [33], software factories, software families, software product lines (e.g., [6, 10, 20]), and configurable systems (e.g., [15, 46]). The last two abilities, i.e., customizability and configurability, are typically described in terms of features or variation points with variants incorporated into their respective feature or decision models [13, 20, 48]. Similarly, configuration options are used in configurable software systems, turning them into families of closely related software systems [15]. Moreover, all software artifacts, such as architecture, design, and code, have the potential to vary or to be reused, whether through ad-hoc or systematic reuse. A recent study shows that code artifacts are the most frequently reused ones [11]. Therefore, in this work, we focus on exploring variability of small-scale configurable software at the code level.

Binding time. Although a software system can change over time (a.k.a., variability in time), variability-intensive systems excel in their ability to do and be a dozen different things at a certain point in time (a.k.a., variability in space) [12]. This variability is initially introduced, for example, in the form of options, and then resolved (i.e., concretized) [43], either immediately or later in the development cycle. The point in time at which some variability is resolved is known as the binding time and can range from the requirements phase to runtime [9, 10, 23]. At the code level, all binding times are often boiled down to the programming time, compile time, and runtime. In this work, these are also the binding times of variability in small-scale software systems that we focus on examining.

Implementation: examples of variability types and systems analyzed. Listing 1 shows an excerpt of the implementation of three

```c
#include <getopt.h>
#define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
                      : (ls_mode == LS_MULTI_COL \
                         ? "dir" : "vdir"))
int main (int argc, char **argv) {
    while (true) {
        int c = getopt_long (argc, argv,
                             "abcdefghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",
                             long_options, &oi);
        if (c == -1)
            break;
        switch (c) {
            case 'd':
                immediate_dirs = true;
                break;
            case 'l':
                format_opt = long_format;
                break;
            /* The rest of code and options are omitted */
        }
    }
}
```

<caption>Listing 1: An excerpt of ls.c of ls, dir, and vdir programs</caption>

```
[coreutils9.1]$ ./src/ls --help
>>> Usage: ./src/ls [OPTION]... [FILE]...
>>> -d, --directory list directories themselves,
>>> not their contents
>>> -l
use a long listing format
The rest of 58 options are omitted
```

<caption>Listing 2: Usage and run-time options of the ls program</caption>

well-known C-based command-line software programs: ls, which lists directory contents; dir, which briefly lists directory contents; and vdir, which verbosely lists directory contents<fnref n="3" />. Because of their commonality in the behavior, they are implemented together. Specifically, the compile-time variability in lines 2-4, realized by pre-processor directives, makes it possible to build the three programs with their own executables from the same C files. Whereas, their run-time variability in lines 6-21 is achieved through the getopt.h library<fnref n="4" />, which automates the parsing of Unix command-line options. The program’s usage, as shown in Listing 2 (line 2), and all its available run-time options can be printed in the standard output (lines 3-6) by calling the program with the --help option (line 1).

Although many approaches for addressing variability exist, such as feature-oriented or software design patterns [6, 43, 47], this study focuses on the type of variability found in C-based configurable systems, specifically analysing their compile-time and run-time variability. Moreover, we refer to such systems, characterized by their small executable size, as small-scale systems in this study.

```
[grep-3.10]$ ./configure --disable-largefile
[grep-3.10]$ make && make install
```

<caption>Listing 3: Usage of a compile-time option to build a program</caption>

```
[grep-3.10]$ ./src/grep --ignore-case "novel" books.txt
```

<caption>Listing 4: Usage of a run-time option and input in a program</caption>

<footnote n="3">³Manual: https://www.gnu.org/software/coreutils/manual/coreutils.html</footnote>

<footnote n="4">⁴https://www.gnu.org/software/libc/manual/html_node/Getopt.html</footnote>
Configuration: illustration of compile-time and run-time variability. Often, to customize a C-based software at compile time, users simply use the `./configure` command [16]. For example, `grep`<fnref n="5" /> is a program that is used to search for matching patterns in a file. It has dozens of configuration options that can be used to customize its behavior before installation. For instance, in case that the support for large files is not required, then it is possible to deactivate it by using the `-disable-largefile` option during the grep's build, as in Listing 3 (line 1). After its build, numerous run-time options become available. For example, to search for the word "novel" in a case-insensitive manner in a file, a user can use the command shown in Listing 4. In this case, `./src/grep` is the program, `--ignore-case` is the run-time option that affects program's behavior during a particular execution, and "novel" books.txt is the program's input. This study focuses on this kind of compile-time and run-time variability often found in C-based software systems.

# 3 MOTIVATION

Studies show that software systems are becoming increasingly configurable to meet user needs and cope with the heterogeneity of execution platforms. For example, the Linux kernel, with over 20 000 features and 26 million lines of code, offers a configuration space larger than the number of atoms in the universe [3, 25], a number projected to double within two decades [3]. This immense configuration space poses significant challenges, such as testing a representative subset of configurations [17, 39], identifying bugs caused by feature interactions [1, 2], and performing variability-aware testing [36, 40]. Even basic tasks, such as counting all possible configurations, become very complex [3]. However, there is little empirical evidence on the scale of variability in other typical real-world software systems [19, 28] or how it compares to larger ones like Linux kernel. On the other hand, many small-scale software systems, characterized by their limited codebase or binary size, such as GNU coreutils, are widely used in everyday tasks. However, to the best of our knowledge, their configurability remains largely unexplored. Therefore, we question whether variability is also an important characteristic of small-scale systems, as in large-scale ones, or if their limited configuration spaces would make challenges like counting and testing feature combinations less relevant.

In fact, both real-world and artificially developed small-scale codebases, or snippets of configuration spaces of larger software systems, are often used by researchers, primarily for evaluation purposes, such as assessing new variability implementation techniques [6, 7, 31], variability reverse engineering [34], or debloating approaches [8]. The configuration space of these systems is often perceived as less complex to understand, although there is a lack of empirical evidence that supports this claim. We found no studies that specifically explore the configurability of small-scale systems, both in time and space, and its relationship to codebase size. Exploring the variability and configurability of small-scale systems can provide valuable, empirically grounded insights that we believe that could be effectively applied to larger-scale software systems.

Today, from operating systems to programs like coreutils, there is a clear trend towards specializing, debloating, and minimizing software systems to meet real-world demands for greater

efficiency [5]. Additionally, the push for more reproducible software emphasizes the need for minimal and immutable designs<fnref n="6" />. Despite these efforts, we notice a gap in understanding what defines or characterizes a null-variable software system. Moreover, we believe that understanding the variability of smaller systems can help address challenges in both small- and large-scale contexts.

# 4 EMPIRICAL STUDY

In this section, we present the research questions and the 108 small-scale software systems used as subjects to address them.

## 4.1 Research Questions

To examine the dynamics of variability in small-scale software systems from the user's perspective, we asked:

*   **RQ₁: What is the extent of variability in small-scale software?** The aim of this research question is to analyze and quantify the variability in small to tiny software systems. Specifically, we measure variability by enumerating compile-time and run-time configuration options across 108 programs in the recent version of GNU coreutils.

*   **RQ₂: Is there a relationship between software size and variability?** Building on the results from the previous question, this research question investigates the relationship between software variability and size. To achieve this, we analyzed the binary size and lines of code alongside the amount of variability, calculating the Pearson and Spearman correlations for 108 programs in GNU coreutils to explore the nature of this relationship in small-scale software systems.

*   **RQ₃: How has variability in small-scale software changed over time?** The goal of this research question is to determine whether the earliest versions of small-scale software exhibited lower variability. To investigate this, we selected 20 programs from GNU coreutils that currently have the lowest variability and analyzed how their compile-time and run-time configuration options evolved over time.

*   **RQ₄: What approaches do developers use to reduce or remove variability in small-scale software?** Systems like toybox were created to provide lightweight alternatives to GNU programs, minimizing size and complexity. Our intent is to explore the strategies developers employ to minimize variability. To address this question, we compare alternative implementations of 3 programs in coreutils and toybox. Through this comparison, we aim to uncover some effective approaches for reducing variability in small-scale software.

## 4.2 Subject Systems

To answer the research questions, we analysed the coreutils of GNU operating system. They are the basic file, shell, and text manipulation utilities that are expected to exist on every operating system<fnref n="7" />. Specifically, our software subjects are 108 utilities in the current version 9.1 of coreutils<fnref n="8" />, to which we refer also as programs. Examples of such programs are cat, which makes possible

<footnote n="5">⁵grep: https://www.gnu.org/software/grep/</footnote>

<footnote n="6">⁶https://sonalake.com/latest/the-future-is-minimal-and-immutable-a-new-generation-of-operating-systems/</footnote>

<footnote n="7">⁷GNU core utilities: https://www.gnu.org/software/coreutils/</footnote>

<footnote n="8">⁸The source of analysed release: https://mirror.cyberbits.eu/gnu/coreutils/</footnote>
<figure><img src="image_2.png" /><figcaption>Figure 1: Dependency graph between programs and .c files</figcaption></figure>

to concatenates and writes files; echo, which prints a line of text; ls, which lists directory contents; and mkdir, which makes directories. Their historical relevance makes coreutils a cornerstone of GNU/Linux systems, representative of traditional UNIX-like utilities. The main reasons why we chose to analyze them are the fact that they are quite well-known, used in daily bases (e.g., ls, rm), often used to evaluate different approaches in software engineering, such as debloating techniques [8], and most importantly their relatively small codebase size (e.g., compared to web applications<fnref n="9" />), in terms of lines of code (LoC) or binary size, makes these system suitable to the purpose of our study.

## 4.3 Data Extraction and Processing Protocol

**The build of programs.** To analyse the programs of coreutils, we had first to understand the way how they are implemented and can be build. In the considered release, the project of coreutils has 763,637 LoC<fnref n="10" />. One characteristic of coreutils is that each program can be build as a separate binary (i.e., executable), which is the default way, or the whole coreutils can be build as a single binary containing the chosen programs. In this work, we built all the default programs offered by the project separately, meaning each has its own distinct binary. Note that two programs (arch and hostname) were not built by default, but we added them to the configuration. Despite that, we kept unchanged the default compile-time options during the build. The entire coreutils resembles an SPL with the basic programs for an operating system. Thus, each of these programs can be seen as a product variant of coreutils.

**Measuring the size of programs.** Because of the product line nature of coreutils, finding all used lines of code (LoC) to implement each program was challenging. Therefore, as the LoC of a given program we considered only the source code that explicitly contributes to the implementation of its functionalities. Specifically, for each program, we identify its main .c file, which is typically named after the program. Additionally, we include the LoC of files that implement features specific to the program. This analysis gives us a dependency graph as depicted in Figure 1. It shows that each program has often only one associated .c file (bottom part), but there are also programs with more complex dependencies (top part). For example, for the cat program we counted LoC that are in its corresponding cat.c file, for arch we counted LoC in uname-arch.c and uname.c, and so on. We did not count the LoC used to implement some functionalities which are imported as external files into the respective files of a program. Moreover, to increase the

precision of our experiments and crosscheck the results, we also measured each program's executable size (in bytes).

**Quantifying variability in programs.** To determine the run-time variability of a program, we first built the program and enumerated the number of individual options, being them long or short, shown by its --help command. Duplicate and alias options (e.g., -a and --archive in the cp program, which provide the same functionality to the users) were counted as a single option. Similarly, variants of an option (e.g., the basename program's --suffix=SUFFIX option) were counted as a single option because their possible values, such as different SUFFIX-es, are often unlimited and rarely a finite set. Additionally, we disregarded logical relationships between options, such as alternative or optional dependencies, and all other kinds of dependencies between options. In other words, we counted the number of distinct available run-time options in a program, not its configuration space (i.e., the possible combinations of options, or system variants). As for compile-time variability, we used the graph in Figure 1 to parse the source code of each program and automatically searched for preprocessor directives with Tree-sitter [35]<fnref n="11" />. We extracted each preprocessor directive and counted the distinct ones to determine the compile-time options available in each program.

**Categorizing programs based on their usage.** To give some perspective on the most and least used programs in coreutils, we extracted all the bash files used in the Linux kernel<fnref n="12" /> and counted the occurrences of each of the 108 subject programs within these files. We then classified the usage into three categories: High for more than 1 000 occurrences, Medium for 50 to 1 000 occurrences, and Low for fewer than 50 occurrences of each program.

# 5 RESULTS

This section presents results, insights, and discusses the findings related to our four research questions.

## 5.1 Extent of Variability in Small Software

To answer the first two research questions (RQ₁ and RQ₂), we first measured the size of the 108 programs using two metrics: the number of lines of code (LoC) and their binary size in kibibytes (KiB). We then quantified their variability by enumerating the number of compile-time and run-time options, a common and immediate indicator of variability in C-based systems [14] like coreutils.

In Figure 2, the size of each bubble represents the obtained size of the corresponding program, measured in lines of code (LoC). It resulted that three programs, namely dir, ls, and vdir, have the highest number of LoC (4 095 LoC), whereas the smallest ones are hostid and true with only 50 LoC. Thus, on average, a program has 712 LoC. As for the binary size, all programs fall within the range of 185 [KiB] (for true and false) to 806 [KiB] (for dir). This is shown on the horizontal axis in Figure 2. On average, the size of the executable of a program is 308 [KiB]. To put this in perspective, these sizes are small compared to many modern applications, e.g.,

<footnote n="9">⁹The website obesity crisis: https://idlewords.com/talks/website_obesity.htm</footnote>

<footnote n="10">¹⁰We used cloc to count them: https://github.com/AlDanial/cloc</footnote>

<footnote n="11">¹¹Tree-sitter parser: https://tree-sitter.github.io/</footnote>

<footnote n="12">¹²https://github.com/torvalds/linux/commit/a185a0995518a3355c8623c95c36aaae489de10</footnote>
<figure><img src="image_3.png" /><figcaption>Figure 2: The variability, binary size, LoC and usage of 108 programs, as subjects, from the GNU coreutils, version 9.1</figcaption></figure>

<table><caption>Table 1: Correlation between variability, LoC, and binary size</caption><thead><tr><th>Correlation</th><th>Pearson</th><th>Spearman</th><th>Resolution</th></tr></thead><tbody><tr><td>Binary size × Run-time</td><td>0,78</td><td>0,70</td><td>Strong [0,6→0,8]</td></tr><tr><td>LoC × Run-time</td><td>0,78</td><td>0,62</td><td>Strong [0,6→0,8]</td></tr><tr><td>Binary Size × LoC</td><td>0,72</td><td>0,70</td><td>Strong [0,6→0,8]</td></tr><tr><td>Binary Size × Compile-time</td><td>0,38</td><td>0,38</td><td>Low [0,2→0,4]</td></tr><tr><td>LoC × Compile-time</td><td>0,64</td><td>0,61</td><td>Strong [0,6→0,8]</td></tr><tr><td>Run-time × Compile-time</td><td>0,35</td><td>0,23</td><td>Low [0,2→0,4]</td></tr></tbody></table>

web applications, which often exceed several mebibytes (MiB)$^{13}$. Hence, our subjects are indeed lightweight or small-scale software.

The vertical axis in Figure 2 also shows the amount of variability observed in the 108 analysed programs in coreutils. To facilitate comparison in the chart, we categorized all programs based on their usage in the bash files of Linux kernel, as explained in Section 4.3. It resulted that approximately 16% are highly used (●, in red), 33% are moderately used (●, in orange), and 51% are less used (●, in blue).

In terms of variability, all programs were found to have a range of 4 to 76 compile-time and run-time options. Indeed, we found out that 3 programs, namely dir, ls, and vdir, have the largest amount of variability, with 76 compile-time and run-time options each. Whereas, 12 programs have only 4 compile-time and run-time options, among which are sleep, true, and link. Although less significant, each program, on average, has 15 options. If each of these options is Boolean (as is often the case), the configuration space for a program with 15 options would be 2$^{15}$, or 32768 possible configurations, assuming that there are no dependencies between the

options. Thus, under these assumptions, even small programs offer substantial configurability, ranging from 2$^4$ to 2$^{76}$ possible configurations. This means that although small in binary size and LoC, still these systems can pose considerable challenges in testing and maintenance due to their large consiguration spaces. When compared to larger systems, this variability becomes even more striking. Studies on 26 larger software systems, such as x264, FreeBSD, and Ubuntu, report feature counts ranging from 9 to 31 012, with an average of 2 370 features per system [19]. While these studies do not claim to provide exact counts of features [25], they reveal the immense configurability in real-world software systems. Our findings highlight that the configurability in smaller software like coreutils is lower but significant and represents an important aspect that should not be overlooked when building, using, or maintaining them.

**RQ1 insights:** Small to tiny software programs (up to 4 095 LoC and 806 KiB in executable size) exhibit significant variability, with configuration options ranging from 4 to 76. Variability remains a key characteristic of these programs, enabling substantial configurability despite their modest size.

## 5.2 Software Size and Variability Relationship

Looking in Figure 2, the majority of programs are concentrated in one area. Specifically, most of them have fewer than 20 run-time options (91%), fewer than 10 compile-time options (91%), an executable size of less than 500 [KiB] (90%), and fewer than 1,500 LoC (91%, as shown by the small bubbles). To verify if there is a relationship between these three measurements, we calculated their linear correlation using the Pearson and Spearman coefficients interpreted

<footnote>$^{13}$The website obesity crisis: https://idlewords.com/talks/website_obesity.htm</footnote>
<figure><img src="image_4.png" /><figcaption>Figure 3: Changes in LoC over time for the 20 smallest programs, from 2003 (v 4.5.1) to 2022 (v 9.1)</figcaption></figure>

with the Evans rule [22]. The obtained results in Table 1 show that a high and positive (≈ 0.72, that is, the average of the first two rows) correlation exists between the size (i.e., binary size and #LoC) and number of run-time options in programs. Whereas, a lower and positive (≈ 0, 50, that is, the average of the fourth and fifth rows) correlation is between size and compile-time options. The highest correlation of 0.78 is between binary size and run-time options. This suggests that a high and positive relationship exists between them, indicating that larger programs tend to have more run-time options. However, while the correlation is high, it is not perfect. This implies that the amount of variability in programs has an impact on their codebase size, or vice versa, alongside other factors. These results show how design choices and system architecture affect the balance between run-time and compile-time variability. This balance, in turn, affects the software's size and configurability.

**RQ₂ insights:** The results provide an interesting perspective on balancing software size and configurability: while run-time options correlate strongly with size (0.78), compile-time options show a weaker correlation (0.50). This suggests an opportunity to strategically decide when to implement options at compile-time or run-time. Understanding this balance is key to optimizing configurability in systems of all sizes.

## 5.3 Variability Over Time in Small Software

As results in RQ₂ show, none of the programs are without variability. Then, there is a high correlation between their size and run-time

variability (on average 0.78 for Pearson and 0.66 for Spearman). Therefore, for our third research question (*RQ₃*), we sought to determine whether earlier versions of these programs exhibited more or fewer variability. This is particularly relevant because it is possible that more lines of code were added to the programs over time, which may or may not be linked to new added options in the programs. To find out, we analysed the evolution of 20 programs (from 22 in total<fnref n="14" />) that are with 2 run-time options. These programs have the lowest amount of variability in the current *coreutils*. As such, we thought that they were ideal for closely examining, and even manually if needed, the relationship between variability and program size. These programs are listed in the legend of Figure 3. Specifically, we analysed their run-time variability and size (LoC) in all 85 releases of *coreutils*, from 2003 (v 4.5.1) to 2022 (v 9.1).

```
$ ./src/true /*returns true as exit status*/
$ ./src/true --help /*displays its help and exits*/
$ ./src/true --version /*outputs its version*/
```

### Listing 5: The three variants of the true program

After a thorough examination of the variability in these 20 programs, we observed that all of them share the same 2 options in the latest release, namely --help and --version. These two options seem that do not alter the functionality of these programs and are not particular to them, as pretty much all other programs also have them. We thus raised the question of whether they should be regarded as program variability at all. For instance, Listing 5 shows

<footnote n="14">¹⁴Two of them have operands, another form of variability, besides options.</footnote>
that both options make 3 possible ways to run true, and thus the 3 different outputs. Since they introduce a form of variability in the output, we considered them part of the program's variability.

Figure 3 shows the evolution of the number of lines of code (`# LoC`) for the 20 smallest programs in `coreutils`. It can be noticed that their size (`# LoC`) decreased on average up to the version 5.0 in 2003. From this version onward, up to the current version 9.1, their size has increased by up to 99.89% compared to the first version.

Regarding the evolution of their variability, we noticed the following.

* Programs `arch`, `false`, `groups`, and `nohup` were introduced in latter versions. For instance, the command `false` existed from the beginning as part of the built sources, but as a program in its own source file and executable, it was introduced only in version 5.90.

* Programs `expr` and `factor` have an increase in variability only in version 7.0, with 2 and 1 run-time options added, respectively. Then, their variability was decreased (i.e., removed) by the same amount.

* For the 13 other programs, their run-time variability remained the same across all releases (i.e., with 2 options).

```c
#include <stdio.h>
#include "system.h" /* ... */

/* some of the code is omitted */

#if EXIT_STATUS == EXIT_SUCCESS   /* true 9.1 */
# define PROGRAM_NAME "true"     /* true 5.0 */
#else
# define PROGRAM_NAME "false"   /* true 9.1 */
#endif

int main (int argc, char **argv)
{
    /* ... */
    if (argc == 2)
    {
        /* ... */
        if (STREQ (argv[1], "--help"))
            usage (EXIT_STATUS);

        if (STREQ (argv[1], "--version"))
            version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME,
                        Version, AUTHORS, (char *) NULL);
    }
    return EXIT_STATUS;
}
```

<caption>Listing 6: An excerpt of true, comparing its v 9.1 and v 5.0</caption>

```c
int main ()
{
    exit (0);
}
```

<caption>Listing 7: An excerpt of the true 1999, with no variability</caption>

This is the case only for their run-time variability. But, as their size in `LoC` has changed among the versions, we decided to investigate in depth the source code of the two smallest programs, `true` and `false`, to understand the nature of these size changes and check for any differences in their compile-time options. In one of the earliest `coreutils` releases, version 5.0 (2003)<fnref n="15" />, `true` had 43 `LoC`, whereas `false` did not yet have a source file. Listing 6 shows an excerpt of `true`'s implementation. In version 5.0, it had

only line 6 from lines 5-9. The program name `"true"`, which will be bound at compile-time, but its value remained the same, that is, it did not vary. From version 5.90 onward, when `false` had its own source file for the first time, developers added a few more `LoC` to `true`, among which also lines 5 and 7-9. Thus, in addition to the existing run-time variability (cf. lines 13-20), some compile-time variability was added. Currently, the latest versions of `true` and `false` have twice as much variability, with 2 compile-time options and 2 run-time options each. Out of curiosity, we went further back in time and noticed that the implementation of `true` in 1999 has had only 4 `LoC` and no variability, that is, neither run-time nor compile-time options. Listing 7 shows its entire implementation.

```bash
$ ls -l /bin/true /bin/false
```

*   `› -rwxr-xr-x 1 root root 0 Jan 10 1979 /bin/true`
*   `› -rwxr-xr-x 1 root root 7 Jan 10 1979 /bin/false`

Listing 8: true and false in Unix, 1979 (from: [18])

Listing 8 shows the respective binary size of `true` and `false` in their very first version (adopted from [18]). Basically, `true` was an empty file. The way how it worked is that the shell would open the empty file, do nothing, and exit with a `true` status code 0. Whereas, `false` was a file with 7 characters, that is, `exit 1` (including the line-feed at the end). It would return 1, which signifies failure [38]. Thus, the initial versions of `true` and `false` had little to no lines of code (`LoC`), no variability, and yet retained the same exact functionality as their current version (9.1).

These results show that while the run-time variability of most programs remained unchanged across releases, compile-time variability evolved notably, particularly in the smallest programs like `true` and `false`. Interestingly, these programs began with little to no variability (a.k.a., null variability), yet over time, both compile-time options and lines of code increased, reflecting the incorporation of broader configurability for the same exact functionality. While $RQ_2$ highlighted a strong relationship between run-time variability and program size when analyzing their variability in space, the analyzed variability in time (i.e., $RQ_3$) underscores a relationship between compile-time variability and size, as observed through the evolution of two small programs. Extending this analysis to other subject programs could uncover broader trends, but this requires developing tools to automate compile-time variability identification in all program releases, which we leave for future work.

**$RQ_3$ insights:** Early versions of some small-scale software exhibited minimal variability, often with no configuration options. Over time, variability increased, mostly due to the addition of compile-time options. Moreover, while run-time variability was correlated to program size in space, compile-time variability seems to be linked with size in time. These results highlight the importance of further exploring compile-time options and their impact on software growth over time.

## 5.4 Used Approaches for Reducing Variability

To answer our fourth research question ($RQ_4$), we analyzed `toybox` [27], an alternative and lightweight implementation of `coreutils`.

The `toybox`'s main objective is to provide the most common Linux programs into a single executable, which would be simple,

<footnote n="15">¹⁵The source of analysed release: https://mirror.cyberbits.eu/gnu/coreutils/</footnote>
<table><caption>Table 2: cat's size and variability in coreutils and toybox</caption><thead><tr><th>cat</th><th>LoC</th><th>Size</th><th>Compile-time</th><th>Run-time</th></tr></thead><tbody><tr><td>coreutils</td><td>526</td><td>219,02 [KiB]</td><td>4</td><td>12</td></tr><tr><td>toybox</td><td>40</td><td>18,14 [KiB]</td><td>0</td><td>4 + 2</td></tr></tbody></table>

small, and fast to turn resource constraint devices, such as Android, into a development environment [27]. To answer $RQ_4$, we explored how much smaller the toybox programs are compared to coreutils and what developers did to achieve this reduction. While these programs are expected to be smaller in size, the question is: what happens to their variability? Is it preserved or reduced?

To begin with, the recent release of toybox<fnref n="16" /> includes 227 programs and has 72 300 LoC, or 90, 53% less than coreutils. Then, 85 of 108 programs in coreutils are also in toybox. Indeed, comparing their individual size showed that each of them have less LoC and smaller executable than their equivalent program in coreutils. Due to space constraints, detailed data are provided in the shared repository. Regarding their run-time variability, we noticed that:

* 6 programs have one or two more options than in coreutils.

* 19 programs have the same number of options.

* 60 programs exhibit less variability in toybox.

Based only on run-time variability, these data suggest that programs in toybox have become smaller by mainly reducing their variability (71% of them). But, the question is how did they achieve that goal?

### 5.4.1 Removing Variability.
In order to get a glimpse of understanding which variability is reduced and how, we chose to compare the implementation of cat program in coreutils and toybox. It is one of the most used programs<fnref n="17" />, which copies (concatenates) files to standard output. Table 2 shows that its implementation in toybox has 92.40% less LoC, a 91.72% smaller executable, and 62.50% less compile-time and run-time options (i.e., variability).

Basically, there is no visible compile-time variability in the implementation of cat in toybox, that is, the built cat in toybox is always the same or is of null variability at compile-time. Then, Listings 9 and 10 show that cat has also 6 less run-time options in toybox than in coreutils. As it can be noticed, this is achieved by removing the unnecessary variability. First, the long options are removed, that is, only their abbreviations are kept. For example, --show-nonprinting is removed and -v is kept (cf. lines 14-15 in Listing 9 and lines 6-8 in Listing 10). Secondly, duplicated options are removed, such as -b and -n (cf. lines 4-5, 8 in Listing 9). Plus, no -s option exists in toybox. It is the only one that is completely removed. Thirdly, the equivalent options are removed too, namely -A, -e, and -t (cf. lines 3, 6, 11 in Listing 9). They are equivalent with the combination of other options, hence they are completely removed in toybox. Lastly, although the --help and --version are understood by cat in toybox (also by most of its other programs), they are invisible here but contribute to its variability (cf. Table 2).

In Listings 9 and 10 also can be visually distinguished the implemented (■), removed (□), unimplemented (■), and invisible (□)

<figure><img src="image_5.png" /><figcaption>Listing 9: The run-time option of cat in coreutils 9.1</figcaption></figure>

<figure><img src="image_6.png" /><figcaption>Listing 10: The run-time option of cat in toybox 0.8.8</figcaption></figure>

options in toybox. Although other and different reasons for keeping or removing some variability may exist, the illustrative example of cat shows one way to reducing, and in some cases nullifying, the variability of a software program. By nullifying we mean that the program's variability is reduced, sometimes entirely, while still delivering the same essencial value to users. Additionally, we identified various examples of programs in toybox where variability has been completely removed (i.e., nullified), such as sync, true, false, and sleep (though sleep still accepts different times as inputs).

```c
#include "toys.h"
void true_main(void)
{
    return;
}
```

<caption>Listing 11: true in toybox</caption>

<caption>Listing 12: false in toybox</caption>

### 5.4.2 Resolving Variability.
Looking into the implementation of toybox, we also noticed that some of its programs have less variability because it is resolved earlier. Concretely, true and false programs in toybox have only 5 LoC each and no compile-time or run-time variability. Semantically, these programs are opposites, which may explain why their implementation in coreutils has undergone several changes, as discussed in Section 5.3. Listings 11 and 12 show their current and respective implementation in toybox. By comparing the two implementations of true it can be noticed that the compile-time variability in lines 5-9 in Listing 6 is resolved

<footnote n="16">¹⁶The analysed release of toybox: https://github.com/landley/toybox/tree/0.8.8</footnote>

<footnote n="17">¹⁷Based on UNIX user data set: http://archive.ics.uci.edu/ml/datasets/unix+user+data</footnote>
in Listings 11 and 12. As a result of this, now each of two programs are into their own source files, true.c and false.c, without the implemented logic by preprocessor directives to build them from a common implementation. Despite this, both programs in toybox together have less LoC and binary size than in coreutils.

Moreover, we observed that while run-time variability in toybox is reduced, and in some cases nullified by removing unnecessary and duplicate options, compile-time variability is primarily reduced, or even nullified, by resolving it during programming-time.

**RQ4 insights:** Based on small-scale software, software systems can become even smaller or lightweight by removing redundant and unnecessary run-time variability, consolidating functionalities, and resolving compile-time variability early.

# 6 DISCUSSION

These results highlight the extensive configuration space in small-scale software, despite their size, and the strong correlation between their run-time variability and size. Over time, variability in these software seems to grow mostly due to the added compile-time variability. The observed results suggest that changing certain options from run-time to compile-time could lead to notable reductions in binary size or LoC. In fact, the broader impact of altering the binding time of configuration options on binary size seems to be an important area for further investigation. Such a study could help developers to achieve a better balance between variability and software size, while also identifying and eliminating unused features that contribute to unnecessary bloat. Moreover, this strategy could pave the way for creating more specialized software systems, as opposed to those bloated with redundant or rarely used features.

It is important to note that we do not rule out the possibility that additional methods for reducing variability could exist. For instance, the disparity in the number of programs between toybox (227) and coreutils (108) is important to investigate. It raises the question of whether some programs in coreutils have been split into multiple, more specialized programs in toybox. Still, the overall codebase of toybox remains significantly smaller than that of coreutils. This observation suggests potential differences in the underlying used algorithms or programming methodologies, with coreutils potentially favoring a more verbose approach.

As opposed to the SPL variants that might be used independently of one another, the coreutils programs are frequently used together, to perform sequential tasks, in scripting and command-line workflows, such as ls and cd. Identifying common combinations of these programs and evaluating the variability contributed by each could help to simplify workflows by removing unnecessary options in some typical use cases. Moreover, we believe that similar findings based on small-scale software offer valuable insights that could be applied to larger software with more extensive codebases.

# 7 UNVEILING NULL VARIABILITY

Building on the findings from our research questions, we introduce null-variable software systems, providing a definition and outlining five observed properties of null variability. We deliberately use the term "null" instead of "zero" or "no" variability since a configurable software is often described by the set of features or configuration

options that it contains. Hence, we use null for variability similar to the null set (i.e., {} ) in the set theory.

## 7.1 Notations

To begin, we present the necessary notations to formally define our concept. Let S be a set of all existing software systems and s ∈ S be a given software system. If s is a software system with variability, then let F_s be the set of all its features or configuration options. Each of those options can be on/off or have multiple values. When combined, the set of options used by a user constitutes a system configuration, which yields a unique instance (variant) of the system. Furthermore, an option's value is set at a specific point in time, known as its binding time. Therefore, let T = {... , t_p, t_c, t_r, ...} be the set of possible binding times of the option f ∈ F_s, where t_p is the binding at programming-time, t_c is the binding at compile-time, and t_r is the binding at run-time. In this work, we consider that all mandatory features are bound or resolved before compile-time, i.e., at t_p. Conversely, varying features (i.e., configuration options) are resolved at one of two subsequent binding times, namely, t_c or t_r.

## 7.2 Properties

Based on the obtained results in this study, we derived the following five properties of software systems of null variability.

**P_1:** Existing software. A software system of null variability, denoted as s null , is an existing, complete, and functional piece of software. It is different from no software at all. Then, just like all other kinds of working or complete software, an unvarying program (i.e., of null variability) delivers values to the end-users. This means that it is not a running but featureless software, in the sense that it does nothing. This may appear to be a paradoxical statement, but all features in a null-variable software are mandatory, in the sense that they cannot be selectively enabled or disabled after implementation. As F_s is the set of all features in a software system s, then formally

$$s_{\text{null}} \in S \\ F_{s_{\text{null}}} \neq \emptyset, F_{s_{\text{null}}} = \{f_x \mid \text{bound}(f_x) \leq t_p, x \in \mathbb{N}\} \quad (1)$$

**P_2:** Multiplicity across domains. Null variability is not limited to a single software system or domain. Multiple systems can be of null variability, regardless of the programming paradigm or application domain. Formally,

$$s_{\text{null}} \in S_{\text{null}}, \text{ where } S_{\text{null}} \subset S \text{ and } |S_{\text{null}}| \geq 0 \quad (2)$$

**P_3:** Behavioral consistency. A null-variable software system behaves as a constant system. For any input I it produces a consistent, though not necessarily identical, output U. This property ensures predictable, unchanging behavior across all contexts. Formally,

$$s_{\text{null}}(I) = U \quad (3)$$

**P_4:** Distinction from the core part in an SPL. In variability-intensive software systems or SPLs, the core (or base) part is often distinguished from the commonalities (C_s) and variabilities (V_s). While the core part is often understood as the constant part among the possible software products that can be derived from a codebase, it may still include some variability. Additionally, core features may
represent a basis (e.g., classes or interfaces) that is extended later and, therefore, not yet a complete, running software. In contrast, a null-variabile software ($s_{null}$) is a complete, unvarying software where all features ($F_{s_{null}}$) are compulsory and bound before or at programming time ($t_p$). This distinction is formalized as:

$$ 
\begin{array}{l}
F_s = C_s \cup V_s, C_s \cap V_s = \emptyset \\
\forall c \in C_s, \ bound(c) \le t_p \text{ and } \forall v \in V_s, \ bound(v) \in \{t_c, t_r\} \\
F_{s_{null}} = \{f_x | \ bound(f_x) \le t_p, x \in \mathbb{N}\} \\
F_{s_{null}} \ne \emptyset, C_s \subset F_{s_{null}}, \text{ where } C_s \ne \emptyset
\end{array}
\quad (4) $$

**P5: Binding time constraints.** The concept of null variability can be used also to denote the absence of variability at a particular binding time. For instance, a software with no run-time configuration options is null-varying at run-time. Similarly, a null-varying software at compile-time has no variability in compile time.

## 7.3 Definition

Hence, we define null software variability as the exact opposite of software variability, as described by Capilla et al. [10].

**Definition 1.** Null variability in software is the deliberate absence of the ability to customize or configure the software at or after a certain binding time. A software with null variability delivers consistent and unchanging behavior regardless of its context or environment. Formally, if $t_b$ is the fixed binding time, then

$$ s_{null} \Leftrightarrow F_s \neq \emptyset \text{ and } \forall f \in F_s, \ bound(f) \leq t_b \quad (5) $$

## 8 THREATS TO VALIDITY

*Internal threats.* A first internal threat stems from the identification of compile-time and run-time options of programs. Their variability can be different in case that somebody else uses a slightly different definition of what an options is, compared to our given explanation in Section 4.3. As for the compile-time options, we plan to use the state-of-the-art approaches for identifying the implemented variability by preprocessors in C (e.g., [25]). Still, as we studied in depth most of the programs, we manually crosschecked their amount of variability. In addition, other variation points may exist in code, which may have other binding times. Moreover, we do not consider the variability of external libraries used by a program or in build scripts. But, this does not present a direct threat to our study. Another threat is related with the counting of LoC, because of the SPL nature of coreutils and toybox. To increase its precision we used the complementary and alternative metric of binary size. Importantly, in both cases we got the same results in our research questions. To mitigate these threats, all the data are extracted by two authors and crosschecked by two other authors.

*External threats.* While we believe that analysing 108 programs of coreutils, and 85 programs of toybox that intersect with them, are strong evidence for our obtained results, still we considered only the C-based and small programs. While our study showed that the empty file version of the true program is the smallest null-variable software program we encountered, it is important to note that we cannot determine the upper limit of the size of a null-variable software program based solely on these findings. Still, whatever the size of a software system, we believe that the

concept of null variability remains valid for them too, and also similar approaches can be employed to reduce their variability.

## 9 RELATED WORK

Most research on software variability focuses on large-scale systems, such as the Linux kernel [19, 25]. Then, many studies also highlight the increasing variability in software systems [4, 44, 50], often adding complexity through numerous configuration options. In contrast, our work examines the variability of small-sized software systems, that is, those with few lines of code or small executables. These systems are intentionally kept simple yet effective, delivering real, everyday value to users. Still, to the best of our knowledge, the extent of their variability and how it is linked with their size has not been explicitly explored in prior research.

However, numerous subdomains related to SPL engineering are linked to this work. For instance, El-Sharkawy et al. [14] conducted a systematic literature review and presented a catalog of over 140 variability-aware implementation metrics for software product lines, including "# of configuration options" and "# of features" in an SPL. In this work, we quantified the variability of 108 small to tiny programs using existing metrics and introcude a new metric, that of null variability at compile-time or run-time. While El-Sharkawy et al. focused on identifying relevant variability metrics in the literature, our objective was to apply these metrics to analyze and characterize the variability of real-world, small-sized programs, including how their variability evolves over time.

There are different works that explore how the variability in C-based systems is addressed, managed, or extracted. Our work examines how much variability is included in small-sized systems, showing that it can still be significant. We also highlight that, despite their size, there are real scenarios where this variability needs further reduction, and introduce the notion and characteristics of systems with null variability. On the other hand, Krüger et al. [24] conducted a study that, while not directly related, parallels ours in exploring an unconventional aspect of software systems. They focused on the commonality of software systems instead of variability, whereas we study the variability of small-size software systems.

Furthermore, several other topics in software engineering may appear related, including the low code/no code [41] or the KISS [49] philosophies, which emphasize keeping the codebase as small and simple as possible during development. Other related areas include software debloating [26, 45], which involves removing superfluous features, options, or libraries at the code level to reduce the binary size and surface attack of systems; optimisation or restructuring [29, 30], aimed at removing rarely or never used features to decrease the complexity of systems; and dependency reduction [42], which focuses on minimizing unnecessary dependencies.

Some less related works, but close to the protocol of our experiments, are those on the growing complexity of software systems [4], extracting compile-time variability out of preprocessor directives [21, 25, 52], and analysing the evolution of variability [53].

## 10 CONCLUSION

While the extent, implementation, management, and testing of software variability are well-recognized challenges in modern (ultra
large-scale software systems, little attention has been given by researchers to the extent of variability in small-scale software. We conducted an empirical investigation into the extent of variability in small-scale software and introduced the concept of null variability. By analyzing 108 programs from GNU coreutils, we revealed that even small-scale software, averaging 308 [KiB], exhibits notable configurability, with an average configuration space of $2^{15}$ and offering up to 76 options per program. This shows that despite their modest size, such software presents similar challenges in testing and maintenance as large-scale software systems. Our findings also showed a high correlation (0.78) between run-time variability and software size. Then, an analysis of 84 releases of 20 coreutils programs showed that early versions of programs exhibited little to no variability, while a focused study in smallest programs highlighted that compile-time variability have an effect in the codebase size of small-scale software over time. These results highlight how design decisions and the binding time of variability influence the codebase size both at specific points in time and over its development. Additionally, we show that software can be made more lightweight by removing redundant run-time variability or resolving some of the compile-time variability early in the development process.

Finally, we introduced null variability as a formal concept to describe software systems with no configurability beyond mandatory features. This concept provides a new way on describing and designing immutable, minimal, specialized, or lightweight software systems. We hope these insights encourage further exploration of variability reduction in both small and large-scale systems, for improving software maintainability and usability.

## REFERENCES

[1] Iago Abal, Claus Brabrand, and Andrzej Wasowski. 2014. 42 variability bugs in the Linux Kernel: A qualitative analysis (ASE '14). Association for Computing Machinery, New York, NY, USA, 421–432. https://doi.org/10.1145/2642937.3542990

[2] Iago Abal, Jean Melo, Ştefan Stănciuulescu, Claus Brabrand, Márcio Ribeiro, and Andrzej Wasowski. 2018. Variability bugs in highly configurable systems: A qualitative analysis. 26, 3, Article 10 (jan 2018), 34 pages. https://doi.org/10.1145/3149119

[3] Mathieu Acher, Hugo Martin, Luc Lesoil, Arnaud Blouin, Jean-Marc Jézéquel, Djamel Eddine Khelladi, Olivier Barais, and Juliana Alves Pereira. 2022. Feature subset selection for learning huge configuration spaces: The case of Linux Kernel size. In *Proceedings of the 26th ACM International Systems and Software Product Line Conference - Volume A* (Graz, Austria) (SPLC '22). Association for Computing Machinery, New York, NY, USA, 85–96. https://doi.org/10.1145/3546932.3546997

[4] Mamdouh Alenezi and Khaled Almustafa. 2015. Empirical analysis of the complexity evolution in open-source software systems. *International Journal of Hybrid Information Technology* 8, 2 (2015), 257–266.

[5] Mohannad Alhanahnah, Yazan Boshmaf, and Ashish Gehani. 2024. SoK: Software debloating landscape and future directions (FEAST '24). Association for Computing Machinery, New York, NY, USA, 11–18. https://doi.org/10.1145/3689937.3695792

[6] Sven Apel, Don Batory, Christian Kästner, and Gunter Saake. 2016. Feature-oriented software product lines. Springer. https://doi.org/10.1007/978-3-642-37521-7

[7] Don Batory. 2005. Feature models, grammars, and propositional formulas. In *Software Product Lines*, Henk Obbink and Klaus Pohl (Eds.). Springer Berlin Heidelberg, Berlin, Heidelberg, 7–20.

[8] Michael D. Brown, Adam Meily, Brian Fairservice, Akshay Sood, Jonathan Dorn, Eric Kilmer, and Ronald Eytchison. 2024. A broad comparative evaluation of software debloating tools. In *33rd USENIX Security Symposium (USENIX Security 24)*. USENIX Association, Philadelphia, PA, 3927–3943. https://www.usenix.org/conference/usenixsecurity24/presentation/brown

[9] Carl Burch. 2012. Binding time. http://www.cburch.com/books/bind/. Accessed: 2025-04-24.

[10] Rafael Capilla, Jan Bosch, Kyo-Chul Kang, et al. 2013. Systems and software variability management. *Concepts Tools and Experiences* 10 (2013), 2517766.

[11] Rafael Capilla, Barbara Gallina, Carlos Cetina, and John Favaro. 2019. Opportunities for software reuse in an uncertain world: From past to emerging trends. *Journal of software: Evolution and process* 31, 8 (2019), e2217.

https://doi.org/10.1002/smr.2217

[12] Paul Clements. 2019. Managing variation: An industrial perspective on product line engineering. In *2019 IEEE/ACM 41st International Conference on Software Engineering: Companion Proceedings (ICSE-Companion)*. IEEE, 1–1. https://doi.org/10.1109/ICSE-Companion.2019.00020

[13] Krzysztof Czarnecki, Paul Grünbacher, Rick Rabiser, Klaus Schmid, and Andrzej Wasowski. 2012. Cool features and tough decisions: A comparison of variability modeling approaches. In *Proceedings of the sixth international workshop on variability modeling of software-intensive systems*. 173–182. https://doi.org/10.1145/2110147.2110167

[14] Sascha El-Sharkawy, Nozomi Yamagishi-Eichler, and Klaus Schmid. 2019. Metrics for analyzing variability and its implementation in software product lines: A systematic literature review. *Information and Software Technology* 106 (2019), 1–30. https://doi.org/10.1016/j.infsoft.2018.08.015

[15] Paul Gazzillo and Myra B Cohen. 2022. Bringing together configuration research: Towards a common ground. (2022). https://doi.org/10.1145/3563835.3568737

[16] GNU. [n. d.]. Autoconf - GNU Project. https://www.gnu.org/software/autoconf/

[17] Axel Halin, Alexandre Nuttinck, Mathieu Acher, Xavier Devroey, Gilles Perrouin, and Benoit Baudry. 2019. Test them all, is it worth it? Assessing configuration sampling on the JHipster web development stack. *Empirical Softw. Engg.* 24, 2 (apr 2019), 674–717. https://doi.org/10.1007/s10664-018-9635-4

[18] G. J. Holzmann. 2015. Code Inflation. *IEEE Software* 32, 02 (2015), 10–13. https://doi.org/10.1109/MS.2015.40

[19] Seiede Reyhane Kamali, Shirin Kasaei, and Roberto E. Lopez-Herrejon. 2019. Answering the call of the wild? Thoughts on the elusive quest for ecological validity in variability modeling (SPLC '19). Association for Computing Machinery, New York, NY, USA, 143–150. https://doi.org/10.1145/3307630.3342400

[20] Kyo C Kang, Sholom G Cohen, James A Hess, William E Novak, and A Spencer Peterson. 1990. Feature-oriented domain analysis (FODA) feasibility study. Technical Report. Carnegie-Mellon Univ Pittsburgh Pa Software Engineering Inst.

[21] Christian Kästner, Paolo G. Giarrusso, Tillmann Rendel, Sebastian Erdweg, Klaus Ostermann, and Thorsten Berger. 2011. Variability-aware parsing in the presence of lexical macros and conditional compilation. 46, 10 (oct 2011), 805–824. https://doi.org/10.1145/2076021.2048128

[22] Maurice George Kendall. 1948. *Rank correlation methods*. Harvard Book, Harvard.

[23] Michael Krisper and Christian Kreiner. 2016. Describing binding time in software design patterns. In *Proceedings of the 21st European Conference on Pattern Languages of Programs*. 1–15. https://doi.org/10.1145/3011784.3011811

[24] Jacob Krüger, Wanzi Gu, Hui Shen, Mukelabai, Mukelabai, Regina Hebig, and Thorsten Berger. 2018. Towards a better understanding of software features and their characteristics: A case study of Marlin (VAMOS 2018). Association for Computing Machinery, New York, NY, USA, 105–112. https://doi.org/10.1145/3168365.3168371

[25] Elias Kuiter, Chico Sundermann, Thomas Thüm, Tobias Hess, Sebastian Krieter, and Gunter Saake. 2025. How configurable is the Linux Kernel? Analyzing two decades of feature-model history. *ACM Trans. Softw. Eng. Methodol.* (April 2025). https://doi.org/10.1145/3729423 Just Accepted.

[26] Hsuan-Chi Kuo, Jianyan Chen, Sibin Mohan, and Tianyin Xu. 2020. Set the configuration for the heart of the OS: On the practicality of operating system kernel debloating. 4, 1, Article 03 (may 2020), 27 pages. https://doi.org/10.1145/3379469

[27] Rob Landley. 2006. Toybox. http://landley.net/toybox/#12-08-2022.

[28] Jörg Liebig, Sven Apel, Christian Lengauer, Christian Kästner, and Michael Schulze. 2010. An analysis of the variability in forty preprocessor-based software product lines (ICSE '10). Association for Computing Machinery, New York, NY, USA, 105–114. https://doi.org/10.1145/1806799.1806819

[29] Felix Loesch and Erhard Ploedereder. 2007. Optimization of variability in software product lines. In *11th International Software Product Line Conference (SPLC 2007)*. 151–162. https://doi.org/10.1109/SPLINE.2007.31

[30] Felix Loesch and Erhard Ploedereder. 2007. Restructuring variability in software product lines using concept analysis of product configurations. In *11th European Conference on Software Maintenance and Reengineering (CSMR'07)*. 159–170. https://doi.org/10.1109/CSMR.2007.40

[31] Roberto E. Lopez-Herrejon and Don Batory. 2001. A standard problem for evaluating product-line methodologies. In *Generative and Component-Based Software Engineering*, Jan Bosch (Ed.). Springer Berlin Heidelberg, Berlin, Heidelberg, 10–24.

[32] Hugo Martin, Mathieu Acher, Juliana Alves Pereira, Luc Lesoil, Jean-Marc Jézéquel, and Djamel Eddine Khelladi. 2021. Transfer learning across variants and versions: The case of linux kernel size. *IEEE Transactions on Software Engineering* 48, 11 (2021), 4274–4290. https://doi.org/10.1109/TSE.2021.3116768

[33] M Douglas McIlroy, J Buxton, Peter Naur, and Brian Randell. 1968. Mass-produced software components. In *Proceedings of the 1st international conference on software engineering (NATO), Garmisch, Germany*. 88–98.

[34] Johann Mortara, Xhevhahire Tërnava, and Philippe Collet. 2020. Mapping features to automatically identified object-oriented variability implementations: the case of ArgoUML-SPL (VaMoS '20). Association for Computing Machinery, New York,
NY, USA, Article 20, 9 pages. https://doi.org/10.1145/3377024.3377037

[35] Iulian Neamtiu, Jeffrey S Foster, and Michael Hicks. 2005. Understanding source code evolution using abstract syntax tree matching. In *Proceedings of the 2005 international workshop on Mining software repositories*. ACM, NY, USA, 1–5.

[36] Hung Viet Nguyen, Christian Kästner, and Tien N. Nguyen. 2014. Exploring variability-aware execution for testing plugin-based web applications. In *Proceedings of the 36th International Conference on Software Engineering* (Hyderabad, India) (ICSE 2014). Association for Computing Machinery, New York, NY, USA, 907–918. https://doi.org/10.1145/2568225.2568300

[37] Leonardo Passos, Leopoldo Teixeira, Nicolas Dintzner, Sven Apel, Andrzej Wąsowski, Krzysztof Czarnecki, Paulo Borba, and Jianmei Guo. 2016. Coevolution of variability models and related software artifacts. *Empirical Software Engineering* 21, 4 (2016), 1744–1793. https://doi.org/10.1007/s10664-015-9364-x

[38] Rob Pike. 2018. /bin/true used to be an empty file. The shell would open it, do nothing, and exit with a true status code. https://threadreaderapp.com/thread/966896123548872705.html. Accessed: 2025-04-24.

[39] Quentin Plazar, Mathieu Acher, Gilles Perrouin, Xavier Devroey, and Maxime Cordy. 2019. Uniform sampling of SAT solutions for configurable systems: Are we there yet? 240–251. https://doi.org/10.1109/ICST.2019.00032

[40] Alexander von Rhein, Jörg Liebig, Andreas Janker, Christian Kästner, and Sven Apel. 2018. Variability-aware static analysis at scale: An empirical study. 27, 4, Article 18 (nov 2018), 33 pages. https://doi.org/10.1145/3280986

[41] Karlis Rokis and Marite Kirikova. 2022. Challenges of low-code/no-code software development: A literature review. In *International Conference on Business Informatics Research*. Springer, 3–17.

[42] Marco Sinnema, Sybren Deelstra, Jos Nijhuis, and Jan Bosch. 2004. Covamof: A framework for modeling variability in software product families. In *International Conference on Software Product Lines*. Springer, 197–213.

[43] Mikael Svahnberg, Jilles Van Gurp, and Jan Bosch. 2005. A taxonomy of variability realization techniques. *Software: Practice and experience* 35, 8 (2005), 705–754. https://doi.org/10.1002/spe.652

[44] Reinhard Tartler, Daniel Lohmann, Julio Sincero, and Wolfgang Schröder-Preikschat. 2011. Feature Consistency in Compile-Time-Configurable System Software: Facing the Linux 10,000 Feature Problem. In *Proceedings of the Sixth Conference on Computer Systems* (Salzburg, Austria) (EuroSys '11). Association for Computing Machinery, New York, NY, USA, 47–60. https://doi.org/10.1145/1966445.1966451

[45] Xhevahire Tërnava, Mathieu Acher, and Benoit Combemale. 2023. Specialization of run-time configuration space at compile-time: An exploratory study (SAC '23). Association for Computing Machinery, New York, NY, USA, 1459–1468. https://doi.org/10.1145/3555776.3578613

[46] Xhevahire Tërnava, Mathieu Acher, Luc Lesoil, Arnaud Blouin, and Jean-Marc Jézéquel. 2022. Scratching the surface of ./configure: Learning the effects of compile-time options on binary size and gadgets. In *Reuse and Software Quality: 20th International Conference on Software and Systems Reuse, ICSR 2022, Montpellier, France, June 15–17, 2022, Proceedings*. Springer, 41–58. https://doi.org/10.1007/978-3-031-08129-3_3

[47] Xhevahire Tërnava and Philippe Collet. 2017. On the diversity of capturing variability at the implementation level. In *Proceedings of the 21st International Systems and Software Product Line Conference-Volume B*. 81–88. https://doi.org/10.1145/3109729.3109733

[48] Xhevahire Tërnava, Johann Mortara, Philippe Collet, and Daniel Le Berre. 2022. Identification and visualization of variability implementations in object-oriented variability-rich systems: a symmetry-based approach. *Automated Software Engineering* 29, 1 (2022), 1–51. https://doi.org/10.1007/s10515-022-00329-x

[49] Vincent Vidal. 2011. YAHSP2: Keep it simple, stupid. *Proceedings of the 7th International Planning Competition (IPC-2011)* (2011), 83–90.

[50] Tianyin Xu, Long Jin, Xuepeng Fan, Yuanyuan Zhou, Shankar Pasupathy, and Rukma Talwader. 2015. Hey, you have given me too many knobs!: Understanding and dealing with over-designed configuration in system software. In *Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering*. 307–319. https://doi.org/10.1145/2786805.2786852

[51] Zuoning Yin, Xiao Ma, Jing Zheng, Yuanyuan Zhou, Lakshmi N Bairavasundaram, and Shankar Pasupathy. 2011. An empirical study on configuration errors in commercial and open source systems. In *Proceedings of the Twenty-Third ACM Symposium on Operating Systems Principles*. 159–172. https://doi.org/10.1145/2043556.2043572

[52] Bo Zhang and Martin Becker. 2012. Code-based variability model extraction for software product line improvement (SPLC '12). Association for Computing Machinery, New York, NY, USA, 91–98. https://doi.org/10.1145/2364412.2364428

[53] Bo Zhang, Martin Becker, Thomas Patzke, Krzysztof Sierszecki, and Juha Erik Savolainen. 2013. Variability evolution and erosion in industrial product lines: A case study (SPLC '13). Association for Computing Machinery, New York, NY, USA, 168–177. https://doi.org/10.1145/2491627.2491645