Bouncing on Simon's answer
Many purists reject the idea of preprocessing
And a purist's answer would be: use GPR project files, they offer the "scenario variables" feature that should do exactly what you want, without having to rename files or rely on some preprocessing step.
I guess Secondary_File.ads
is unique (interface/contract), so you put each Secondary_File.adb
in its own folder (distinct implementations).
Then its easy to adapt the GPR source_dir/source_files list according to a scenario variable. The variable can be set in the GnatStudio IDE, in an env var, and in a command line flag.
So you could have this folder tree:
src
|-- main.adb
|-- Secondary_File.ads
|-- implA
|-- Secondary_File.adb
|-- implB
|-- Secondary_File.adb
|-- implC
|-- Secondary_File.adb
Then use this GPR file my_project.gpr
:
project my_project is
-- enum value shall match folders
type Secondary_Impl is ("implA", "implB", "implC");
the_secondary_impl_val : Secondary_Impl := external("secondary_impl_env_var", "implA"); -- gprbuild will look for env var if any, otherwise defaults to implA
for Source_Dirs use ("src", "src/" & the_secondary_impl_val );
-- other useful settings : obj dir, compiler/linker switches etc.
-- ...
end my_project;
All you have to do is then build using gpr build:
# build with impl A
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implA
# build with impl C
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implC
or even :
# bash commands, syntax to set env var depends on the OS/shell
secondary_impl_env_var=implB
gprbuild -Pmy_project.gpr
Depending on your specific software, you may also consider object oriented design patterns that can help achieve a similar result in some cases.