Scoped enable_language

I have a project in language A with most toolchain files also in A.
If built with unittests then there is one or two subdirectories in language B included.
One single toolchain is also in language B.
Depending on an option set there might also be some files in language C included which require a locally scoped enabling of language C…

How do I set enable_language so that A is enabled everywhere whereas B is only enabled in the unittest subdirectory and/or for the particular toolchain (preferably without having an ugly if(unittests OR my_special_toolchain) clause)?
I particularly want to avoid having to specify language B compilers for toolchains that do not use it which seems to be the case when all three are defined on the project command.
I have tried a bit with only setting A on the project command and adding the others as need arise but I’d love some guidance on best practices/pitfalls to avoid.

Thanks.

I have no experience with toolchain files, so I can’t comment on that part, but I can share a few caveats I’ve learned when working with enable_language().

First off, the command may only be called once for each language in the entire CMake run. So if you e.g. have two sibling directories which need language B enabled, you have to call enable_language() in a parent of those two directories.

Second, the command must be called at file scope, not in a function, because it sets many variables for the language in its current scope.

However, there is no problem with having enable_language() controlled by an if(). Based on your description, I would probably structure the flow like this:

In the top-level CMakeList, do:

project(whatever LANGUAGES A)

if(the_one_toolchain_file)
  enable_language(B)
  set(enabled_B TRUE)
endif()

In parent directory of all unit tests:

if(not enabled_B)
  enable_language(B)
  set(enabled_B TRUE)
endif()

In a directory above all C language sources:

if(the_option)
  enable_language(C)
endif()

Thanks, this is helpful! So to get some sort of scope you need to do a bit more file separation.

An alternative that could be of interest is if there is a convenient way to turn off the requirement to include a compiler for a certain langague that’s enabled above.
Eg cmake complains loudly when crosscompiling if I don’t do a set compiler for the enabled language B that I don’t (normally) use in that case.