## Add -il option to inline all libraries **Discussion**: https://github.com/grame-cncm/faust/discussions/832 ### Summary This PR adds a new `-il` (`--inline-libraries`) option that produces a self-contained DSP file with all library code inlined: ```bash faust -il myfile.dsp -o myfile_standalone.dsp ``` The output preserves readable Faust source code, unlike `-e` which exports an unreadable expanded box tree. **Tree-shaking** automatically removes unused definitions to keep output minimal. ### Motivation From issue #832: Users need self-contained DSP files for sharing, archiving, or using in environments without library access. The existing `-e` option exports expanded DSP but produces unreadable output. ### Example **Input (`mytest.dsp`):** ```faust import("mymath.lib"); fx = library("myeffects.lib"); process = _ : half : fx.gain; ``` **mymath.lib:** ```faust half(x) = x * 0.5; double(x) = x * 2; // unused by this program ``` **Output with `-il`:** (note: `double` is removed by tree-shaking) ```faust // Self-contained DSP file generated with -il option // Inlined libraries: 2 // Tree-shaking: enabled (5 definitions used) // ===== Imported: mymath.lib ===== half(x) = x * 0.5; // ===== End of: mymath.lib ===== // Library: mymath.lib __lib_mymath = environment { half(x) = x * 0.5; }; // Library: myeffects.lib __lib_myeffects = environment { gain = *(0.8); }; // ===== Main DSP ===== fx = __lib_myeffects; process = _ : half : fx.gain; ``` ### How It Works 1. **Evaluation phase**: Runs normal Faust evaluation, tracking which definitions are used 2. **Collection phase**: Recursively discovers all `import()` and `library()` dependencies 3. **Output phase**: - `import()` content inlined directly at top level (into global scope) - `library()` content wrapped in `environment { }` as top-level definitions - **Tree-shaking**: Only used definitions are included in output - Files used as both `import()` and `library()` are handled correctly - Circular dependencies detected and reported - Duplicate variable definitions skipped ### Tree-Shaking The `-il` option automatically removes unused definitions by: 1. Evaluating the program first to determine which symbols are actually used 2. Tracking all symbol lookups during evaluation in `gUsedDefinitions` 3. Filtering the output to only include definitions whose names appear in the tracked set This significantly reduces output size when importing large libraries but only using a few functions. ### Implementation As suggested in the original discussion, this reuses infrastructure from the `-i` option: - Uses `gGlobal->gAlreadyIncluded` set for tracking visited files - Uses `fopenSearch()` for resolving library paths - Similar recursive inject pattern **Why new code was needed on top of `-i`:** The `-i` option handles C++ `#include` in architecture files with simple text substitution. The `-il` option needs Faust-specific semantics: | `-i` (architecture) | `-il` (libraries) | |---------------------|-------------------| | Detects `#include ` | Must parse `import("...")` and `library("...")` | | Just copies file content | `import()` → inline directly | | | `library()` → wrap in `environment { }` | | Single use pattern | Files can be used as both import AND library | | | Must track variable definitions to avoid duplicates | | | Tree-shaking removes unused definitions | | File | Changes | |------|---------| | `global.hh` | +2 lines (flags) | | `global.cpp` | +8 lines (option parsing, init, help) | | `libcode.cpp` | +15 lines (integration) | | `sourcereader.hh` | +3 lines (declaration) | | `sourcereader.cpp` | +280 lines (inlining + tree-shaking logic) | | `eval.cpp` | +8 lines (symbol tracking) | ### Testing ```bash # Simple test faust -il test.dsp -o test_inlined.dsp faust -e test_inlined.dsp # Verify it compiles # Tree-shaking in action faust -il uses_one_function.dsp -o small_output.dsp ``` ### Option Naming Follows the pattern of `-it` (`--inline-table`): - `-il` = inline libraries - `-it` = inline table ### Backward Compatibility Fully backward compatible - new option, no changes to existing behavior. ### Branch - **Worktree**: `../faust-inline-libs` - **Branch**: `feature/inline-libraries` - **Base**: `master-dev`