Have a look at this answer it explains how the configurations are passed from project to Project through the MSBuild Task and Using the MetaData of the configuration to pass the desired configuration for the target project
here
UPDATE
I created a Solution with a class library(Sample.Domain) and ConsoleApplication(SampleApp.Console). I added two more configurations to the SamplApp.Console: prod-us;prod-eu, Sample.Domain remained with debug;release.
I then Changed the csproj file of the ConsoleApplication, like so:
ProjectReferences
<!--<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj">
<Project>{73e8a7fd-0a24-47c5-a527-7601550d4b92}</Project>
<Name>Sample.Domain</Name>
</ProjectReference>
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj" >
<Targets>Build</Targets>
</ProjectReference>
</ItemGroup>
Added a switch case on the configuration passed to MSBuild, to configure some properties for Outputfiles and reference files:
<Choose>
<When Condition="'$(Configuration)' != 'Debug'">
<PropertyGroup>
<OutputProperty>$(OutputPath)\$(Configuration)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<OutputProperty>$(OutputPath)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</Otherwise>
</Choose>
Created a Target to switch the Configuration passed to MSBuild, so that Debug will pass Debug to Sample.Domain, everything else it will pass Release
<Target Name="MultiConfiguration" >
<CreateProperty Value="Debug">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' == 'Debug'"/>
</CreateProperty>
<CreateProperty Value="Release">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' != 'Debug' "/>
</CreateProperty>
</Target>
The Build Target uses the Properties we have added so the Output and Copy of references files will have the right values according to Configuration value
<!--Build Process-->
<Target Name="Build" DependsOnTargets="Clean;MultiConfiguration;ComputeProjectReference" >
<Csc Sources="@(Compile)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(OutputProperty)\$(AssemblyName).exe"/>
</Target>
<Target Name="ComputeProjectReference" Inputs="@(ProjectReference)" Outputs="%(ProjectReference.Identity)__Forced">
<MSBuild Projects="@(ProjectReference)" Targets="%(ProjectReference.Targets)" Properties="Configuration=$(LibConfiguration);Platform=AnyCPU;OutputPath=bin\$(LibConfiguration)">
<Output TaskParameter="TargetOutputs" ItemName="ResolvedProjectReferences"/>
</MSBuild>
</Target>
<Target Name="AfterProjectReference" AfterTargets="ComputeProjectReference">
<CreateItem Include="@(ResolvedProjectReferences)">
<Output TaskParameter="Include" ItemName="CopyFiles" />
</CreateItem>
<Copy SourceFiles="@(CopyFiles)" DestinationFolder="$(FileCopy)" SkipUnchangedFiles="false" />
<ItemGroup>
<NewAssemblies Include="$(OutputProperty)\%(CopyFiles.FileName)%(CopyFiles.Extension)" />
</ItemGroup>
</Target>
To call the Debug configuration is done like this
msbuild SampleApp.Console.csproj
To call (Release;prod-us;prod-eu;...) is done like this
msbuild SampleApp.Console.csproj /p:Configuration="prod-us" /p:OutputPath="bin"
I'm sure it can be optimized, and might be some way easier, but it works.