Toolchains always try to build for the current platform and x86[_64] architectures

build.gradle

apply plugin: 'cpp'

model {
    toolChains {
        clangA(Clang) {
            path 'clang/a/bin'
            target('a-x86_64')
        }
        clangB(Clang) {
            path 'clang/b/bin'
            target('b-x86_64')
        }                
    }
    platforms {
        'a-x86_64' {
            architecture 'x86_64'
            operatingSystem 'a'
        }
        'b-x86_64' {
            architecture 'x86_64'
            operatingSystem 'b'
        }
    }
    components {
        main(NativeLibrarySpec) {
            targetPlatform 'a-x86_64'
            targetPlatform 'b-x86-64'
        }
    }
}

For the purposes of the example assume a and b are both UNIXes.

When I build, gradle will use clang/a/bin/clang++ to build both the binaries even though I have declared the clangA toolchain does not support targeting platform b-x86_64. Can anyone confirm whether behavior is intended or not?

You can compile in paths to e.g. c++ libraries/headers into clang (this is what Xcode does). But some clangs need these to be specified explicitly (e.g. Android’s ndk clang). So, you should be able to specify exactly which binary to use when [cross-]compiling for a given platform (despite what any compiler may report in terms of which architectures it supports). Some platforms come with their own toolchains and you need to be able to use exactly those binaries. For example, I cannot compile for osx-x86_64 on an osx-x86_64 host if I have another clang toolchain specified that does not have the c++ header paths baked in.

I discovered this is happening because abstractgcccompatibletoolchain adds the x86 and x86_64 architectures implicitly if the os matches. This is, perhaps, a limiting assumption. If b is your current platform, then the first toolchain will match because every toolchain adds an implicit target for the current platform and x86[_64] architectures. I was not expecting this behavior. I expected it to work like the toolchain registry does and only add defaults if nothing is specified. It might be interesting to entertain doing this as a finalizer to the toolchain when no targets have been specified.