MSBuild

This rule is tailored for MSBuild.exe from the Visual Studio installation. It does not support the dotnet msbuild execution path. MSBuild determines it own compile and linker flags based on the project/solution file configuration. This cannot be fully controlled from bazel like other rules (e.g. cmake). We do our best by generating a msbuild.props file that is used by specifying -p:ForceImportAfterCppTargets=msbuild.props to append bazel flags and override existing flags where possible.

Since MSBuild is closed source project from Microsoft, there is no prebuilt toolchain available and we cannot build it from source. The default is a pre-installed toolchain which assumes MSBuild.exe is installed as a part of Visual Studio and locateable by bazel. If you want to implement your own MSBuild toolchain you will need to define a toolchain that implements the toolchain type @rules_foreign_cc//toolchains:msbuild_toolchain. E.g.

toolchain(
    name = "msbuild_toolchain",
    exec_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    target_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    toolchain = ":_msbuild_toolchain",
    toolchain_type = "@rules_foreign_cc//toolchains:msbuild_toolchain",
)

native_tool_toolchain(
    name = "_msbuild_toolchain",
    path = "<Path to MSBuild.exe inside target>",
    target = "<Label to toolchain target>",
    env = {
        "MSBUILD": "$(execpath <Label for MSBuild.exe>)",
    },
)

native_tool_toolchain should refer to the target where your MSBuild binary/files reside.

When using your own toolchain, it may also be necessary to set the following properties for MSBuild:

# Use env from bazel toolchain, don't override it.
"-p:UseEnv=true",
"-p:SetEnvOverride=false",

# Toolchain config
"-p:PlatformToolset=", # e.g "v143" for Visual Studio 2022
"-p:VCToolsRedistVersion=",
"-p:VCInstallDir=<path to Visual C++ install dir>",
"-p:VCInstallDir_170=<path to Visual C++ install dir for Visual Studios 2022>",

# SDK configuration
"-p:WindowsSdkDir_10=<path to windows sdk>",
"-p:WindowsKitsRoot=<path to windows sdk>",

# Skip the problematic SDK check target
"-p:_CheckWindowsSDKInstalled=",

# Bypass Windows SDK validation checks
"-p:WindowsSDKInstalled=true",
"-p:WindowsSDK_Desktop_Support=true",

The MSBuild Configuration property is controlled by the configuration attribute. When left unset it follows the Bazel compilation mode, defaulting to Debug under -c dbg and Release otherwise (matching the cmake rule).

The MSBuild Platform property is controlled by the platform attribute. It is left unset by default so MSBuild picks the platform declared in the solution or project file. A .sln only builds the Configuration|Platform pairs it declares, so forcing a platform that the solution does not declare fails with MSB4126; set platform only when the project supports it.

MSBuild projects must copy their outputs into $(OutDir) using the layout declared on the rule. For example, with the default include directory and out_static_libs = ["mylib.lib"], the project should produce $(OutDir)mylib.lib and copy public headers under $(OutDir)include.

msbuild

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "msbuild")

msbuild(name, deps, data, additional_inputs, additional_tools, alwayslink, args, build_data,
        configuration, copts, defines, dynamic_deps, env, experimental_validate_outputs_in_action,
        includes, lib_name, lib_source, linkopts, out_bin_dir, out_binaries, out_data_dirs,
        out_data_files, out_dll_dir, out_headers_only, out_include_dir, out_interface_libs,
        out_lib_dir, out_shared_libs, out_static_libs, platform, postfix_script, properties,
        resource_size, set_file_prefix_map, sln_file_path, static_suffix, targets, tool_prefix,
        tools_deps, verbosity)

Rule for building external library with MSBuild.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOptional dependencies to be copied into the directory structure. Typically those directly required for the external building of the library/binaries. (i.e. those that the external build system will be looking for and paths to which are provided by the calling rule)List of labelsoptional[]
dataFiles needed by this rule at runtime. May list file or rule targets. Generally allows any target.List of labelsoptional[]
additional_inputsdeprecated: Please use the build_data attribute.List of labelsoptional[]
additional_toolsdeprecated: Please use the build_data attribute.List of labelsoptional[]
alwayslinkOptional. if true, link all the object files from the static library, even if they are not used.BooleanoptionalFalse
argsArgs for MSBuild.exe. e.g. '-p:PlatformToolset=v143'List of stringsoptional[]
build_dataFiles needed by this rule only during build/compile time. May list file or rule targets. Generally allows any target.List of labelsoptional[]
configurationMSBuild Configuration to build. When unset, defaults to Debug in -c dbg compilation mode and Release otherwise, mirroring the cmake rule. Usually either Debug or Release.Stringoptional""
coptsOptional. Add these options to the compile flags passed to the foreign build system. The flags only take affect for compiling this target, not its dependencies.List of stringsoptional[]
definesOptional compilation definitions to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
dynamic_depsSame as deps but for cc_shared_library.List of labelsoptional[]
envEnvironment variables to set during the build. $(execpath) macros may be used to point at files which are listed as data, deps, or build_data, but unlike with other rules, these will be replaced with absolute paths to those files, because the build does not run in the exec root. This attribute is subject to make variable substitution. No other macros are supported.Variables containing PATH (e.g. PATH, LD_LIBRARY_PATH, CPATH) entries will be prepended to the existing variable.Dictionary: String -> Stringoptional{}
experimental_validate_outputs_in_actionValidate expected installed outputs inside the main foreign build action before it exits.BooleanoptionalTrue
includesOptional list of include dirs to be passed to the dependencies of this library. They are NOT passed to the compiler, you should duplicate them in the configuration options.List of stringsoptional[]
lib_nameLibrary name. Defines the name of the install directory and the name of the static library, if no output files parameters are defined (any of static_libraries, shared_libraries, interface_libraries, binaries_names) Optional. If not defined, defaults to the target's name.Stringoptional""
lib_sourceLabel with source code to build. Typically a filegroup for the source of remote repository. Mandatory.Labelrequired
linkoptsOptional link options to be passed up to the dependencies of this libraryList of stringsoptional[]
out_bin_dirOptional name of the output subdirectory with the binary files, defaults to 'bin'.Stringoptional"bin"
out_binariesOptional names of the resulting binaries.List of stringsoptional[]
out_data_dirsOptional names of additional directories created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_data_filesOptional names of additional files created by the build that should be declared as bazel action outputsList of stringsoptional[]
out_dll_dirOptional name of the output subdirectory with the dll files, defaults to 'bin'.Stringoptional"bin"
out_headers_onlyFlag variable to indicate that the library produces only headersBooleanoptionalFalse
out_include_dirOptional name of the output subdirectory with the header files, defaults to 'include'.Stringoptional"include"
out_interface_libsOptional names of the resulting interface libraries.List of stringsoptional[]
out_lib_dirOptional name of the output subdirectory with the library files, defaults to 'lib'.Stringoptional"lib"
out_shared_libsOptional names of the resulting shared libraries.List of stringsoptional[]
out_static_libsOptional names of the resulting static libraries. Note that if out_headers_only, out_static_libs, out_shared_libs, and out_binaries are not set, default lib_name.a/lib_name.lib static library is assumedList of stringsoptional[]
platformMSBuild Platform to build (e.g. x64, Win32, ARM64). When unset, the -p:Platform flag is omitted and MSBuild selects the platform from the solution or project file. This is deliberately not derived from the target CPU: a .sln only builds Configuration|Platform pairs it declares, so forcing a mismatched platform fails with MSB4126. Set this explicitly when the project supports it.Stringoptional""
postfix_scriptOptional part of the shell script to be added after the make commandsStringoptional""
propertiesA map of properties (-p:) for MSBuild. Do not set Configuration or Platform; use the dedicated attributes instead.Dictionary: String -> Stringoptional{}
resource_sizeSet the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once. 2. The parallelism passed to the underlying build system via environment variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small overcommit (default +2, matching ninja's ncpus+2 convention). This hides I/O latency and lets configure_make targets — whose configure phase is always serial — make better use of their allocation during the parallel make phase. The overcommit can be tuned with @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run bazel run @rules_foreign_cc//foreign_cc/settings to print all settings in bazelrc format.

The serial size is special: it fixes cpu=1 with no overcommit, for packages that are known-broken under parallel builds.
Stringoptional"default"
set_file_prefix_mapIf True, pass -ffile-prefix-map=$EXT_BUILD_ROOT=. to strip the sandbox path from compiled outputs. If False (the default), inherit from //foreign_cc/settings:set_file_prefix_map_default. Has no effect on MSVC.BooleanoptionalFalse
sln_file_pathSolution or project file path, relative to the detected lib_source root.Stringrequired
static_suffixOptional suffix used by static libs.Ensures correct association of static and shared libs.Stringoptional""
targetsList of MSBuild targets in the projectList of stringsoptional[]
tool_prefixA prefix for build commandsStringoptional""
tools_depsdeprecated: Please use the build_data attribute.List of labelsoptional[]
verbosityVerbosityLevel of msbuild logs. One of 'quiet', 'minimal', 'normal', 'detailed', 'diagnostic'.Stringoptional"normal"

export_for_test.msbuild_dep_paths

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.msbuild_dep_paths(deps, inputs)

PARAMETERS

NameDescriptionDefault Value
deps

-

none
inputs

-

none

export_for_test.msbuild_properties

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.msbuild_properties(user_properties, configuration, platform)

PARAMETERS

NameDescriptionDefault Value
user_properties

-

none
configuration

-

none
platform

-

none

export_for_test.sln_file_path

load("@rules_foreign_cc//foreign_cc:msbuild.bzl", "export_for_test")

export_for_test.sln_file_path(sln_file_path, lib_source_files, root)

PARAMETERS

NameDescriptionDefault Value
sln_file_path

-

none
lib_source_files

-

none
root

-

none