Is it good or bad practice to set the CMAKE_TOOLCHAIN_FILE from within CMakeLists.txt?

…as opposed to passing it on the CMake command line or in CMakePresets.json?

I moved from a computer which had VCPKG_ROOT set to one that did not (although I have vcpkg on here). My CMAKE_TOOLCHAIN_FILE from my CMakePresets.json was no longer valid since I had it defined as "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake".

I found a suggestion on the vcpkg Github discussions to use vcpkg from a submodule so that a local path could be used and to set CMAKE_TOOLCHAIN_FILE in the CMakeLists.txt:

From experimentation I think it can work, but it has to appear before the project directive (I think that’s what made the difference), or else it doesn’t work. However I’m wondering if this suggestion squares with CMake good practice. I’m trying to balance “batteries included / works out of the box” with not over-constraining how my projects can be built.

In general, a project shouldn’t be setting CMAKE_TOOLCHAIN_FILE itself. That is normally something that the user should be in control of. They would normally set it either on the cmake command line or with a CMake preset. There are occasionally some scenarios where the project setting it can be justified, but those are typically restricted to tightly controlled company projects where the project must be built in a very specific way. Even then, presets are usually a better choice for such cases.