Define x86 preset on Windows x64 host using Ninja generator

I have a basic CMakePresets.json as follows:

{
    "version": 3,
    "configurePresets": [
        {
            "name": "windows-base",
            "hidden": true,
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/out/build/${presetName}",
            "installDir": "${sourceDir}/out/install/${presetName}",
            "cacheVariables": {
                "CMAKE_C_COMPILER": "clang-cl.exe",
                "CMAKE_CXX_COMPILER": "clang-cl.exe"
            },
            "condition": {
                "type": "equals",
                "lhs": "${hostSystemName}",
                "rhs": "Windows"
            }
        },
        {
            "name": "x64-debug",
            "inherits": "windows-base",
            "architecture": {
                "value": "x64",
                "strategy": "external"
            },
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug"
            }
        },
        {
            "name": "x86-debug",
            "inherits": "windows-base",
            "architecture": {
                "value": "x86",
                "strategy": "external"
            },
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "x64-debug",
            "configurePreset": "x64-debug"
        },
        {
            "name": "x86-debug",
            "configurePreset": "x86-debug"
        }
    ]
}

With the following CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project ("CMakeProject1")

# Include sub-projects.
add_subdirectory ("CMakeProject1")

When building the x86-debug build preset using Visual Studio 2022 (v17.25), I get the following error:

Detecting C compiler ABI info failed to compile with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-tjf4db

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_c4ed9 && [1/2] Building C object CMakeFiles\cmTC_c4ed9.dir\CMakeCCompilerABI.c.obj

[2/2] Linking C executable cmTC_c4ed9.exe

FAILED: cmTC_c4ed9.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_c4ed9.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_c4ed9.dir\CMakeCCompilerABI.c.obj  /out:cmTC_c4ed9.exe /implib:cmTC_c4ed9.lib /pdb:cmTC_c4ed9.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console   && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_c4ed9.dir\CMakeCCompilerABI.c.obj /out:cmTC_c4ed9.exe /implib:cmTC_c4ed9.lib /pdb:cmTC_c4ed9.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_c4ed9.dir/intermediate.manifest CMakeFiles\cmTC_c4ed9.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.





Determining if the C compiler works failed with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-wg8j9p

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_58966 && [1/2] Building C object CMakeFiles\cmTC_58966.dir\testCCompiler.c.obj

[2/2] Linking C executable cmTC_58966.exe

FAILED: cmTC_58966.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_58966.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_58966.dir\testCCompiler.c.obj  /out:cmTC_58966.exe /implib:cmTC_58966.lib /pdb:cmTC_58966.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_58966.dir\testCCompiler.c.obj /out:cmTC_58966.exe /implib:cmTC_58966.lib /pdb:cmTC_58966.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_58966.dir/intermediate.manifest CMakeFiles\cmTC_58966.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.




Detecting C compiler ABI info failed to compile with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-p73hjz

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_ef6c6 && [1/2] Building C object CMakeFiles\cmTC_ef6c6.dir\CMakeCCompilerABI.c.obj

[2/2] Linking C executable cmTC_ef6c6.exe

FAILED: cmTC_ef6c6.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_ef6c6.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_ef6c6.dir\CMakeCCompilerABI.c.obj  /out:cmTC_ef6c6.exe /implib:cmTC_ef6c6.lib /pdb:cmTC_ef6c6.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console   && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_ef6c6.dir\CMakeCCompilerABI.c.obj /out:cmTC_ef6c6.exe /implib:cmTC_ef6c6.lib /pdb:cmTC_ef6c6.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_ef6c6.dir/intermediate.manifest CMakeFiles\cmTC_ef6c6.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.





Determining if the C compiler works failed with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-utz58l

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_77ca1 && [1/2] Building C object CMakeFiles\cmTC_77ca1.dir\testCCompiler.c.obj

[2/2] Linking C executable cmTC_77ca1.exe

FAILED: cmTC_77ca1.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_77ca1.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_77ca1.dir\testCCompiler.c.obj  /out:cmTC_77ca1.exe /implib:cmTC_77ca1.lib /pdb:cmTC_77ca1.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_77ca1.dir\testCCompiler.c.obj /out:cmTC_77ca1.exe /implib:cmTC_77ca1.lib /pdb:cmTC_77ca1.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_77ca1.dir/intermediate.manifest CMakeFiles\cmTC_77ca1.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.




Detecting C compiler ABI info failed to compile with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-9s7onn

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_7ce67 && [1/2] Building C object CMakeFiles\cmTC_7ce67.dir\CMakeCCompilerABI.c.obj

[2/2] Linking C executable cmTC_7ce67.exe

FAILED: cmTC_7ce67.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_7ce67.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_7ce67.dir\CMakeCCompilerABI.c.obj  /out:cmTC_7ce67.exe /implib:cmTC_7ce67.lib /pdb:cmTC_7ce67.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console   && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_7ce67.dir\CMakeCCompilerABI.c.obj /out:cmTC_7ce67.exe /implib:cmTC_7ce67.lib /pdb:cmTC_7ce67.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_7ce67.dir/intermediate.manifest CMakeFiles\cmTC_7ce67.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.





Determining if the C compiler works failed with the following output:
Change Dir: C:/Users/user/source/repos/CMakeProject1/out/build/x86-debug/CMakeFiles/CMakeScratch/TryCompile-1i4isf

Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_a291e && [1/2] Building C object CMakeFiles\cmTC_a291e.dir\testCCompiler.c.obj

[2/2] Linking C executable cmTC_a291e.exe

FAILED: cmTC_a291e.exe 

cmd.exe /C "cd . && "C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_a291e.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_a291e.dir\testCCompiler.c.obj  /out:cmTC_a291e.exe /implib:cmTC_a291e.lib /pdb:cmTC_a291e.pdb /version:0.0 /machine:x64  /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~1\MICROS~1\2022\PROFES~1\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\cmTC_a291e.dir\testCCompiler.c.obj /out:cmTC_a291e.exe /implib:cmTC_a291e.lib /pdb:cmTC_a291e.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_a291e.dir/intermediate.manifest CMakeFiles\cmTC_a291e.dir/manifest.res" failed (exit code 1) with the following output:

lld-link: error: <root>: undefined symbol: mainCRTStartup


ninja: build stopped: subcommand failed.

The target builds fine if I run cmake on the Visual Studio Developer Command Prompt command-line after running vcvarsall x86.

I could be wrong, but my recollection is that you need to set both architecture and toolset, not just the former, for VS to apply its auto-detection logic that causes it to set up the environment for you automatically when using the external strategy.

1 Like

The solution was to add toolset:

{
    "name": "x86-debug",
    "inherits": "windows-base",
    "architecture": {
        "value": "x86",
        "strategy": "external"
    },
    "toolset": {
        "value": "host=x86",
        "strategy": "external"
    },
    "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
    }
}

In VS2022 17.4, this works for me without toolset defined. This actually limits the user of this preset to the x86 32 bit compiler executable. Not specifying host correctly uses x64_x86 for me when run from within Visual Studio.

Yes, it does limit the preset to the x86, but the preset is specifically x86-debug.

By specifying the toolset with "strategy": "external", Visual Studio automatically configures the Visual C++ environment correctly for the Ninja generator (I’m not aware of how it does this, and I don’t know how to debug it). To do the same on the command line, run the vcvarsall.bat script and specify the correct arch.

Note that on the command line, it can be confusing if you run vcvarsall.bat x64 and then run the cmake --preset x86-debug, expecting the configure preset to configure the build for x86. After that, the result of cmake --build --preset x86-debug will be a 64-bit binary.

As you suggested, I tried removing toolset from the preset, but I still get the error! Can you share your CMakePresets.json and CMakeLists.txt?