FASTBuild Generator

First of all, thank you very much for supporting the FASTBuild generator. I would like to use cmake and FASTBuild to build our own project, but I have found that the i18nNum code in the FASTBuild generator is currently written dead. There may be issues with the VS support for non English versions. Additionally, when generating BFF files, the PlatformToolset parameter was not set in the VCXProject type target to specify the current version of the toolset being used. I am not sure if there are any plans to optimize this in future versions.

Cc: @Eduard_Voronkin

Context: i18nNum code is the generator is used in order to figure out names of some of the DLLs that cl.exe needs to be run in isolated environment on remote host.

i18nNum code in the FASTBuild generator is currently written dead. There may be issues with the VS support for non English versions.

This code has never been tested on non-English systems, it’s just a default that I found working fine on my machine. However, you can use CMAKE_FASTBUILD_COMPILER_EXTRA_FILES variable to specify arbitrary files as compiler’s dependencies. I agree that more general defines would be nice, but for this we need to have more concrete bug report (e.g. which particular system it doesn’t work on)

PlatformToolset parameter was not set in the VCXProject type target to specify the current version of the toolset being used

There are a lot of variables we can set in the .bff files in order to improve quality of the VS Solution / Xcode projects generated by FASTBuild. I’m not sure there are equivalents for some of them in CMake, so we might need to introduce separate variables.

Going back to the original question - PlatformToolset seems to correspond to CMAKE_VS_PLATFORM_TOOLSET.

First of all, thank you very much for your reply. I am using Visual Studio in Chinese. I have set this variable CMAKE_SASTBUILD_COMPILER_EXTRA_FILES, but there is an error when compiling the test program during the configuration phase. It seems that this variable does not take effect during the configuration phase, so I am temporarily using this method to handle it. However, this method is not very perfect.

  // Calculate the i18n number.
  std::string i18nNum = "1033";

  // Add the language to the compiler's name
  FastbuildCompiler compilerDef;
  std::string const compilerRoot = cmSystemTools::GetFilenamePath(compilerLocation);
  compilerDef.ExtraVariables["Root"] = compilerRoot;
#ifdef WIN32
  if (!cmSystemTools::PathExists(compilerRoot + "/" + i18nNum)) {
    LCID lcid = GetUserDefaultLCID();
    i18nNum = std::to_string(lcid);
  }
#endif // WIN32

Regarding the PlatformToolset setting, I use cmake to generate the fbuild.bff file, and then fbuild.bff to generate the solution as the development environment. When generating the VS solution in the fbuild.bff file, PlatformToolset needs to be set in the VSXProject in the bff file so that vsxproj can be generated using the correct PlatformToolset for code editing. I am currently using this method for simple processing, which is convenient for generating solutions that can correctly correspond to PlatformToolset.

void cmGlobalFastbuildGenerator::AddCompiler(std::string const& language,
                                             cmMakefile* mf)
    //............

    // Visual Studio 16 (19.20 to 19.29)
    if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                      compilerDef.CmakeCompilerVersion,
                                      "19.20")) {
      //............
      MSVCToolsetVersion = "v142";
    }
    // Visual Studio 15 (19.10 to 19.19)
    else if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                           compilerDef.CmakeCompilerVersion,
                                           "19.10")) {
      //............
      MSVCToolsetVersion = "v141";
    }
}

void cmGlobalFastbuildGenerator::WriteIDEProjectCommon(
  IDEProjectCommon const& project)
{
  //............
  if (!this->MSVCToolsetVersion.empty()) {
    WriteVariable("PlatformToolset", Quote(this->MSVCToolsetVersion), 1);
  }
  //............
}

In addition, I also found that during the post-build step, the generated bat script fastbuild cannot detect whether the script has terminated when called, resulting in fastbuild waiting for it to end. It seems that the following code needs to be added to the call where the bat script is called

void cmFastbuildNormalTargetGenerator::CollapseAllExecsIntoOneScriptfile(
  std::string const& scriptFileName,
  std::vector<FastbuildExecNode> const& execs) const
{
        //……
    } else {
#if defined(_WIN32)
      WriteScriptProlog(scriptFile);
      WriteCmdsToFile(
        scriptFile,
        { "call " +
          cmSystemTools::ConvertToWindowsOutputPath(exec.ScriptFile) });
      WriteScriptEpilog(scriptFile);
#else
        //……
#endif
    }
  }
}

I’ve created the issue: https://gitlab.kitware.com/cmake/cmake/-/issues/27481 and the fix.

For the PlatformToolset issue. I think we can use the MSVC_TOOLSET_VERSION variable for this. Let me know if it works for you.

For the

there is an error when compiling the test program during the configuration phase

Could you provide a minimal example how I can reproduce the issue? Thanks!

I tried this and it can set PlatformToolset correctly.

https://gitlab.kitware.com/cmake/cmake/-/issues/27481
    // This line is incorrect and needs to be corrected
    if (platformToolset.empty()) {

I submitted a testing project.There are error messages in the README.md file of the project, as well as instructions for the Visual Studio environment I am using.

https://gitlab.kitware.com/TimeLooper/fastbuild-demo.git

How does the compiler node in the generated fbuild.bff file look like on your end?

I’ve tried your sample projects and here’s what I’ve got (it doesn’t mention the 1033 directory anywhere…):

Compiler('Compiler_CXX')
{
  .Root = 'C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.44.35207/bin/Hostx64/x64'
  .Executable = 'C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.44.35207/bin/Hostx64/x64/cl.exe'
  .CompilerFamily = 'msvc'
  .Environment = .LocalEnv
  .ExtraFiles =
  {
    '$Root$/c1.dll',
    '$Root$/c1xx.dll',
    '$Root$/c2.dll',
    '$Root$/atlprov.dll',
    '$Root$/msobj140.dll',
    '$Root$/mspdb140.dll',
    '$Root$/mspdbcore.dll',
    '$Root$/mspdbsrv.exe',
    '$Root$/mspft140.dll',
    '$Root$/msvcp140.dll',
    '$Root$/msvcp140_atomic_wait.dll',
    '$Root$/tbbmalloc.dll',
    '$Root$/vcruntime140.dll',
    '$Root$/vcruntime140_1.dll',
    '$Root$/2052/clui.dll',
    '$Root$/2052/mspft140ui.dll'
  }
}

Also, in the source code it seems like as long as the CMAKE_FASTBUILD_COMPILER_EXTRA_FILES variable is set, we should only use files specified by that variable (source link).

In your case - I’m not sure where does this error

3> Error: opening file 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\1033\clui.dll' in Compiler ToolManifest. File not found.

come from…

Ahh, I think I know what’s happening - probably the CMAKE_FASTBUILD_COMPILER_EXTRA_FILES is not set during the configuration stage… Could you check if this MR helps in your case?

This code modification works fine in my tests. However, I’m wondering if it’s possible to make CMake automatically recognize i18nNum in the future. Using this variable doesn’t seem to be very user-friendly for Visual Studio versions with different languages.

Also, the vcruntime140_1.dll file in Visual Studio 2019 varies between versions; I’ve found that some versions don’t have it. Therefore, in our current project development, I first check if this file exists in the code, and only add it to the ExtraFiles list if it does.