In your case I would let SCons build the different binaries in their respective folder, and then use the Install builder to copy the binary files to the bin/
directory.
You would get something like:
env = Environment()
Export('env')
common = env.SConscript("source/common/SConscript_object", variant_dir="object/common", duplicate=0)
Export('common')
prog1 = env.SConscript("source/prog1/SConscript_bin", variant_dir="object/prog1", duplicate=0)
prog2 = env.SConscript("source/prog2/SConscript_bin", variant_dir="object/prog2", duplicate=0)
env.Install('bin', prog1)
env.Install('bin', prog2)
With the SConscript of the subprograms being something like
Import('env')
Import('common')
prog1 = env.Program('prog1', [ env.Glob(*.cpp), common ])
Return('prog1')
I think SCons refuses to build different targets into a unique variant directory because variants are designed to build a given target with different build settings, like debug and release mode.