tools/build_defs/framework.bzl
def cc_external_rule_impl(ctx, attrs):
    """ Framework function for performing external C/C++ building.

     To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
     and use results in Bazel.
     It is possible to use it to build a group of external libraries, that depend on each other or on
     Bazel library, and pass nessesary tools.

     Accepts the actual commands for build configuration/execution in attrs.

     Creates and runs a shell script, which:

     1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
      of the execroot directory. Adds tools into PATH.
     2) defines the correct absolute paths in tools with the script paths, see 7
     3) defines the following environment variables:
        EXT_BUILD_ROOT: execroot directory
        EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:

          For cmake_external built dependencies:
            symlinked install directories of the dependencies

          for Bazel built/imported dependencies:

            include - here the include directories are symlinked
            lib - here the library files are symlinked
            lib/pkgconfig - here the pkgconfig files are symlinked
            bin - here the tools are copied
        INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
        will be installed

        These variables should be used by the calling rule to refer to the created directory structure.
     4) calls 'attrs.create_configure_script'
     5) calls 'attrs.make_commands'
     6) calls 'attrs.postfix_script'
     7) replaces absolute paths in possibly created scripts with a placeholder value

     Please see cmake.bzl for example usage.

     Args:
       ctx: calling rule context
       attrs: attributes struct, created by create_attrs function above.
         Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there),
         two mandatory fields:
         -  configure_name: name of the configuration tool, to be used in action mnemonic,
         -  create_configure_script(ConfigureParameters): function that creates configuration
            script, accepts ConfigureParameters
         and some other fields provided by the rule, which have been passed to create_attrs.
    """
    lib_name = attrs.lib_name or ctx.attr.name

    inputs = _define_inputs(attrs)
    outputs = _define_outputs(ctx, attrs, lib_name)
    out_cc_info = _define_out_cc_info(ctx, attrs, inputs, outputs)

    cc_env = _correct_path_variable(get_env_vars(ctx))
    set_cc_envs = ""
    execution_os_name = os_name(ctx)
    if execution_os_name != "osx":
        set_cc_envs = "\n".join(["export {}=\"{}\"".format(key, cc_env[key]) for key in cc_env])

    version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'\\n".format(VERSION, lib_name)

    # We can not declare outputs of the action, which are in parent-child relashion,
    # so we need to have a (symlinked) copy of the output directory to provide
    # both the C/C++ artifacts - libraries, headers, and binaries,
    # and the install directory as a whole (which is mostly nessesary for chained external builds).
    #
    # We want the install directory output of this rule to have the same name as the library,
    # so symlink it under the same name but in a subdirectory
    installdir_copy = copy_directory(ctx.actions, "$$INSTALLDIR$$", "copy_{}/{}".format(lib_name, lib_name))

    # we need this fictive file in the root to get the path of the root in the script
    empty = fictive_file_in_genroot(ctx.actions, ctx.label.name)

    define_variables = [
        set_cc_envs,
        "export EXT_BUILD_ROOT=##pwd##",
        "export BUILD_TMPDIR=##tmpdir##",
        "export EXT_BUILD_DEPS=$$EXT_BUILD_ROOT$$/bazel_foreign_cc_deps_" + lib_name,
        "export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty.file.dirname + "/" + lib_name,
    ]

    script_lines = [
        "##echo## \"\"",
        "##echo## \"{}\"".format(version_and_lib),
        "##echo## \"\"",
        "##script_prelude##",
        "\n".join(define_variables),
        "##path## $$EXT_BUILD_ROOT$$",
        "##mkdirs## $$EXT_BUILD_DEPS$$",
        "##mkdirs## $$INSTALLDIR$$",
        _print_env(),
        "\n".join(_copy_deps_and_tools(inputs)),
        # replace placeholder with the dependencies root
        "##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$",
        "cd $$BUILD_TMPDIR$$",
        attrs.create_configure_script(ConfigureParameters(ctx = ctx, attrs = attrs, inputs = inputs)),
        "\n".join(attrs.make_commands),
        attrs.postfix_script or "",
        # replace references to the root directory when building ($BUILD_TMPDIR)
        # and the root where the dependencies were installed ($EXT_BUILD_DEPS)
        # for the results which are in $INSTALLDIR (with placeholder)
        "##replace_absolute_paths## $$INSTALLDIR$$ $$BUILD_TMPDIR$$",
        "##replace_absolute_paths## $$INSTALLDIR$$ $$EXT_BUILD_DEPS$$",
        installdir_copy.script,
        empty.script,
        "cd $$EXT_BUILD_ROOT$$",
    ]

    script_text = convert_shell_script(ctx, script_lines)
    wrapped_outputs = wrap_outputs(ctx, lib_name, attrs.configure_name, script_text)

    rule_outputs = outputs.declared_outputs + [installdir_copy.file]

    ctx.actions.run_shell(
        mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
        inputs = depset(inputs.declared_inputs, transitive = [ctx.attr._cc_toolchain.files]),
        outputs = rule_outputs + [
            empty.file,
            wrapped_outputs.log_file,
        ],
        tools = [wrapped_outputs.script_file],
        # We should take the default PATH passed by Bazel, not that from cc_toolchain
        # for Windows, because the PATH under msys2 is different and that is which we need
        # for shell commands
        use_default_shell_env = execution_os_name != "osx",
        command = wrapped_outputs.wrapper_script,
        execution_requirements = {"block-network": ""},
        # this is ignored if use_default_shell_env = True
        env = cc_env,
    )

    externally_built = ForeignCcArtifact(
        gen_dir = installdir_copy.file,
        bin_dir_name = attrs.out_bin_dir,
        lib_dir_name = attrs.out_lib_dir,
        include_dir_name = attrs.out_include_dir,
    )
    output_groups = _declare_output_groups(installdir_copy.file, outputs.out_binary_files)
    wrapped_files = [
        wrapped_outputs.script_file,
        wrapped_outputs.log_file,
        wrapped_outputs.wrapper_script_file,
    ]
    output_groups[attrs.configure_name + "_logs"] = wrapped_files
    return [
        DefaultInfo(files = depset(direct = rule_outputs + wrapped_files)),
        OutputGroupInfo(**output_groups),
        ForeignCcDeps(artifacts = depset(
            [externally_built],
            transitive = _get_transitive_artifacts(attrs.deps),
        )),
        CcInfo(
            compilation_context = out_cc_info.compilation_context,
            linking_context = out_cc_info.linking_context,
        ),
    ]
 Framework function for performing external C/C++ building.

     To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
     and use results in Bazel.
     It is possible to use it to build a group of external libraries, that depend on each other or on
     Bazel library, and pass nessesary tools.

     Accepts the actual commands for build configuration/execution in attrs.

     Creates and runs a shell script, which:

     1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
      of the execroot directory. Adds tools into PATH.
     2) defines the correct absolute paths in tools with the script paths, see 7
     3) defines the following environment variables:
        EXT_BUILD_ROOT: execroot directory
        EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:

          For cmake_external built dependencies:
            symlinked install directories of the dependencies

          for Bazel built/imported dependencies:

            include - here the include directories are symlinked
            lib - here the library files are symlinked
            lib/pkgconfig - here the pkgconfig files are symlinked
            bin - here the tools are copied
        INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
        will be installed

        These variables should be used by the calling rule to refer to the created directory structure.
     4) calls 'attrs.create_configure_script'
     5) calls 'attrs.make_commands'
     6) calls 'attrs.postfix_script'
     7) replaces absolute paths in possibly created scripts with a placeholder value

     Please see cmake.bzl for example usage.

     Args:
       ctx: calling rule context
       attrs: attributes struct, created by create_attrs function above.
         Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there),
         two mandatory fields:
         -  configure_name: name of the configuration tool, to be used in action mnemonic,
         -  create_configure_script(ConfigureParameters): function that creates configuration
            script, accepts ConfigureParameters
         and some other fields provided by the rule, which have been passed to create_attrs.
    
Framework function for performing external C/C++ building.
To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
and use results in Bazel.
It is possible to use it to build a group of external libraries, that depend on each other or on
Bazel library, and pass nessesary tools.

Accepts the actual commands for build configuration/execution in attrs.

Creates and runs a shell script, which.

1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
of the execroot directory. Adds tools into PATH.
2) defines the correct absolute paths in tools with the script paths, see 7
3) defines the following environment variables:
EXT_BUILD_ROOT: execroot directory
EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories.

For cmake_external built dependencies:
symlinked install directories of the dependencies

for Bazel built/imported dependencies.

here the include directories are symlinked
lib - here the library files are symlinked
lib/pkgconfig - here the pkgconfig files are symlinked
bin - here the tools are copied
INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
will be installed

These variables should be used by the calling rule to refer to the created directory structure.

Please see cmake.bzl for example usage.
Framework function for performing external C / C ++ building . To be used to build external libraries or / and binaries with CMake configure / make autotools etc . and use results in Bazel . It is possible to use it to build a group of external libraries that depend on each other or on Bazel library and pass nessesary tools . Accepts the actual commands for build configuration / execution in attrs . Creates and runs a shell script which . 1 ) prepares directory structure with sources dependencies and tools symlinked into subdirectories of the execroot directory . Adds tools into PATH . 2 ) defines the correct absolute paths in tools with the script paths see 7 3 ) defines the following environment variables : EXT_BUILD_ROOT : execroot directory EXT_BUILD_DEPS : subdirectory of execroot which contains the following subdirectories . For cmake_external built dependencies : symlinked install directories of the dependencies for Bazel built / imported dependencies . here the include directories are symlinked lib - here the library files are symlinked lib / pkgconfig - here the pkgconfig files are symlinked bin - here the tools are copied INSTALLDIR : subdirectory of the execroot ( named by the lib_name ) where the library / binary will be installed These variables should be used by the calling rule to refer to the created directory structure . Please see cmake . bzl for example usage .
def cc_external_rule_impl(ctx, attrs):
    lib_name = attrs.lib_name or ctx.attr.name
    inputs = _define_inputs(attrs)
    outputs = _define_outputs(ctx, attrs, lib_name)
    out_cc_info = _define_out_cc_info(ctx, attrs, inputs, outputs)
    cc_env = _correct_path_variable(get_env_vars(ctx))
    set_cc_envs = ""
    execution_os_name = os_name(ctx)
    if execution_os_name != "osx":
        set_cc_envs = "\n".join(["export {}=\"{}\"".format(key, cc_env[key]) for key in cc_env])
    version_and_lib = "Bazel external C/C++ Rules {}. Building library '{}'\\n".format(VERSION, lib_name)
     We want the install directory output of this rule to have the same name as the library,
     so symlink it under the same name but in a subdirectory
    installdir_copy = copy_directory(ctx.actions, "$$INSTALLDIR$$", "copy_{}/{}".format(lib_name, lib_name))
     we need this fictive file in the root to get the path of the root in the script
    empty = fictive_file_in_genroot(ctx.actions, ctx.label.name)
    define_variables = [
        set_cc_envs,
        "export EXT_BUILD_ROOT=pwd",
        "export BUILD_TMPDIR=tmpdir",
        "export EXT_BUILD_DEPS=$$EXT_BUILD_ROOT$$/bazel_foreign_cc_deps_" + lib_name,
        "export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty.file.dirname + "/" + lib_name,
    ]
    script_lines = [
        "echo \"\"",
        "echo \"{}\"".format(version_and_lib),
        "echo \"\"",
        "script_prelude",
        "\n".join(define_variables),
        "path $$EXT_BUILD_ROOT$$",
        "mkdirs $$EXT_BUILD_DEPS$$",
        "mkdirs $$INSTALLDIR$$",
        _print_env(),
        "\n".join(_copy_deps_and_tools(inputs)),
         replace placeholder with the dependencies root
        "define_absolute_paths $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$",
        "cd $$BUILD_TMPDIR$$",
        attrs.create_configure_script(ConfigureParameters(ctx = ctx, attrs = attrs, inputs = inputs)),
        "\n".join(attrs.make_commands),
        attrs.postfix_script or "",
         replace references to the root directory when building ($BUILD_TMPDIR)
         and the root where the dependencies were installed ($EXT_BUILD_DEPS)
         for the results which are in $INSTALLDIR (with placeholder)
        "replace_absolute_paths $$INSTALLDIR$$ $$BUILD_TMPDIR$$",
        "replace_absolute_paths $$INSTALLDIR$$ $$EXT_BUILD_DEPS$$",
        installdir_copy.script,
        empty.script,
        "cd $$EXT_BUILD_ROOT$$",
    ]
    script_text = convert_shell_script(ctx, script_lines)
    wrapped_outputs = wrap_outputs(ctx, lib_name, attrs.configure_name, script_text)
    rule_outputs = outputs.declared_outputs + [installdir_copy.file]
    ctx.actions.run_shell(
        mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
        inputs = depset(inputs.declared_inputs, transitive = [ctx.attr._cc_toolchain.files]),
        outputs = rule_outputs + [
            empty.file,
            wrapped_outputs.log_file,
        ],
        tools = [wrapped_outputs.script_file],
         We should take the default PATH passed by Bazel, not that from cc_toolchain
         for Windows, because the PATH under msys2 is different and that is which we need
         for shell commands
        use_default_shell_env = execution_os_name != "osx",
        command = wrapped_outputs.wrapper_script,
        execution_requirements = {"block-network": ""},
         this is ignored if use_default_shell_env = True
        env = cc_env,
    )
    externally_built = ForeignCcArtifact(
        gen_dir = installdir_copy.file,
        bin_dir_name = attrs.out_bin_dir,
        lib_dir_name = attrs.out_lib_dir,
        include_dir_name = attrs.out_include_dir,
    )
    output_groups = _declare_output_groups(installdir_copy.file, outputs.out_binary_files)
    wrapped_files = [
        wrapped_outputs.script_file,
        wrapped_outputs.log_file,
        wrapped_outputs.wrapper_script_file,
    ]
    output_groups[attrs.configure_name + "_logs"] = wrapped_files
    return [
        DefaultInfo(files = depset(direct = rule_outputs + wrapped_files)),
        OutputGroupInfo(**output_groups),
        ForeignCcDeps(artifacts = depset(
            [externally_built],
            transitive = _get_transitive_artifacts(attrs.deps),
        )),
        CcInfo(
            compilation_context = out_cc_info.compilation_context,
            linking_context = out_cc_info.linking_context,
        ),
    ]
def cc_external_rule_impl ( ctx , attrs ) : lib_name = attrs . lib_name or ctx . attr . name inputs = _define_inputs ( attrs ) outputs = _define_outputs ( ctx , attrs , lib_name ) out_cc_info = _define_out_cc_info ( ctx , attrs , inputs , outputs ) cc_env = _correct_path_variable ( get_env_vars ( ctx ) ) set_cc_envs = "" execution_os_name = os_name ( ctx ) if execution_os_name != "osx" : set_cc_envs = "\n" . join ( [ "export {}=\"{}\"" . format ( key , cc_env [ key ] ) for key in cc_env ] ) version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'\\n" . format ( VERSION , lib_name ) installdir_copy = copy_directory ( ctx . actions , "$$INSTALLDIR$$" , "copy_{}/{}" . format ( lib_name , lib_name ) ) empty = fictive_file_in_genroot ( ctx . actions , ctx . label . name ) define_variables = [ set_cc_envs , "export EXT_BUILD_ROOT=##pwd##" , "export BUILD_TMPDIR=##tmpdir##" , "export EXT_BUILD_DEPS=$$EXT_BUILD_ROOT$$/bazel_foreign_cc_deps_" + lib_name , "export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty . file . dirname + "/" + lib_name , ] script_lines = [ "##echo## \"\"" , "##echo## \"{}\"" . format ( version_and_lib ) , "##echo## \"\"" , "##script_prelude##" , "\n" . join ( define_variables ) , "##path## $$EXT_BUILD_ROOT$$" , "##mkdirs## $$EXT_BUILD_DEPS$$" , "##mkdirs## $$INSTALLDIR$$" , _print_env ( ) , "\n" . join ( _copy_deps_and_tools ( inputs ) ) , "##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$" , "cd $$BUILD_TMPDIR$$" , attrs . create_configure_script ( ConfigureParameters ( ctx = ctx , attrs = attrs , inputs = inputs ) ) , "\n" . join ( attrs . make_commands ) , attrs . postfix_script or "" , "##replace_absolute_paths## $$INSTALLDIR$$ $$BUILD_TMPDIR$$" , "##replace_absolute_paths## $$INSTALLDIR$$ $$EXT_BUILD_DEPS$$" , installdir_copy . script , empty . script , "cd $$EXT_BUILD_ROOT$$" , ] script_text = convert_shell_script ( ctx , script_lines ) wrapped_outputs = wrap_outputs ( ctx , lib_name , attrs . configure_name , script_text ) rule_outputs = outputs . declared_outputs + [ installdir_copy . file ] ctx . actions . run_shell ( mnemonic = "Cc" + attrs . configure_name . capitalize ( ) + "MakeRule" , inputs = depset ( inputs . declared_inputs , transitive = [ ctx . attr . _cc_toolchain . files ] ) , outputs = rule_outputs + [ empty . file , wrapped_outputs . log_file , ] , tools = [ wrapped_outputs . script_file ] , use_default_shell_env = execution_os_name != "osx" , command = wrapped_outputs . wrapper_script , execution_requirements = { "block-network" : "" } , env = cc_env , ) externally_built = ForeignCcArtifact ( gen_dir = installdir_copy . file , bin_dir_name = attrs . out_bin_dir , lib_dir_name = attrs . out_lib_dir , include_dir_name = attrs . out_include_dir , ) output_groups = _declare_output_groups ( installdir_copy . file , outputs . out_binary_files ) wrapped_files = [ wrapped_outputs . script_file , wrapped_outputs . log_file , wrapped_outputs . wrapper_script_file , ] output_groups [ attrs . configure_name + "_logs" ] = wrapped_files return [ DefaultInfo ( files = depset ( direct = rule_outputs + wrapped_files ) ) , OutputGroupInfo ( ** output_groups ) , ForeignCcDeps ( artifacts = depset ( [ externally_built ] , transitive = _get_transitive_artifacts ( attrs . deps ) , ) ) , CcInfo ( compilation_context = out_cc_info . compilation_context , linking_context = out_cc_info . linking_context , ) , ]
Framework function for performing external C/C++ building.
Framework function for performing external C / C ++ building .
""" Framework function for performing external C/C++ building.

     To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
     and use results in Bazel.
     It is possible to use it to build a group of external libraries, that depend on each other or on
     Bazel library, and pass nessesary tools.

     Accepts the actual commands for build configuration/execution in attrs.

     Creates and runs a shell script, which:

     1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
      of the execroot directory. Adds tools into PATH.
     2) defines the correct absolute paths in tools with the script paths, see 7
     3) defines the following environment variables:
        EXT_BUILD_ROOT: execroot directory
        EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:

          For cmake_external built dependencies:
            symlinked install directories of the dependencies

          for Bazel built/imported dependencies:

            include - here the include directories are symlinked
            lib - here the library files are symlinked
            lib/pkgconfig - here the pkgconfig files are symlinked
            bin - here the tools are copied
        INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
        will be installed

        These variables should be used by the calling rule to refer to the created directory structure.
     4) calls 'attrs.create_configure_script'
     5) calls 'attrs.make_commands'
     6) calls 'attrs.postfix_script'
     7) replaces absolute paths in possibly created scripts with a placeholder value

     Please see cmake.bzl for example usage.

     Args:
       ctx: calling rule context
       attrs: attributes struct, created by create_attrs function above.
         Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there),
         two mandatory fields:
         -  configure_name: name of the configuration tool, to be used in action mnemonic,
         -  create_configure_script(ConfigureParameters): function that creates configuration
            script, accepts ConfigureParameters
         and some other fields provided by the rule, which have been passed to create_attrs.
    """ # We can not declare outputs of the action, which are in parent-child relashion, # so we need to have a (symlinked) copy of the output directory to provide # both the C/C++ artifacts - libraries, headers, and binaries, # and the install directory as a whole (which is mostly nessesary for chained external builds). # # We want the install directory output of this rule to have the same name as the library, # so symlink it under the same name but in a subdirectory # we need this fictive file in the root to get the path of the root in the script # replace placeholder with the dependencies root # replace references to the root directory when building ($BUILD_TMPDIR) # and the root where the dependencies were installed ($EXT_BUILD_DEPS) # for the results which are in $INSTALLDIR (with placeholder) # We should take the default PATH passed by Bazel, not that from cc_toolchain # for Windows, because the PATH under msys2 is different and that is which we need # for shell commands # this is ignored if use_default_shell_env = True
ctx
calling rule context
calling rule context
attrs
attributes struct, created by create_attrs function above.
Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES ,
two mandatory fields:
configure_name: name of the configuration tool, to be used in action mnemonic,
create_configure_script(ConfigureParameters): function that creates configuration
script, accepts ConfigureParameters
and some other fields provided by the rule, which have been passed to create_attrs.
attributes struct created by create_attrs function above . Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES two mandatory fields : configure_name : name of the configuration tool to be used in action mnemonic create_configure_script ( ConfigureParameters ) : function that creates configuration script accepts ConfigureParameters and some other fields provided by the rule which have been passed to create_attrs .