It is not very straightforward, but a possible way is to use separate compilation units. For example, say that you are inside the body of a package named Pkg, and want some code that should do different things based on some scenario variable (this is a GNAT GPRBuild term, but the method can also be used with other build systems). You move that code into some subroutine, let's say, Do_Something, and declare it as separate:
package body Pkg is -- ... procedure Do_Something is separate; -- ... end Pkg;
This tells the compiler that this procedure is defined as separate compilation unit. Now, you put your two (or any number of) implementations in two separate files like this:
separate (Pkg) procedure Do_Something is -- ... begin -- ... end Do_Something;
This tells the compiler that this is the definition of a separate compilation unit from within Pkg. And yes, this means that for each bunch of code, you would need to write two (or n with n = number of differing implementations) additional files.
A good method for managing those files would be to put all debug implementations in a debug directory and likewise for release implementations. You then instruct your build system to load sources from one or the other directory. For example with GPRBuild:
project My_Project is -- define legal modes type Mode_Type is ("debug", "release"); -- load mode from environment variable `Mode`, defaulting to "debug" Mode : Mode_Type = external ("Mode", "debug"); -- add directory with appropriate separate implementations case Mode is when "debug" => My_Sources := My_Sources & "src/debug"; when "release" => My_Sources := My_Sources & "src/release"; end case; -- define where the compiler should load sources from for Source_Dirs use My_Sources; -- ... end My_Project;
Your src folder would have a layout like this:
src debug pkg-do_something.adb release pkg-do_something.adb pkg.adb pkg.ads
This approach works well with multiple, orthogonal scenario values. It also forces you to separate scenario-specific code from general code, which may be seen as good thing, but ymmv.