Custom C++ rule with the cc_common API





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I'm trying to write a custom rule to compile C++ code using the cc_common API. Here's my current attempt at an implementation:



load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")   
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME")

def _impl(ctx):
cc_toolchain = find_cpp_toolchain(ctx)
feature_configuration = cc_common.configure_features(
cc_toolchain = cc_toolchain,
unsupported_features = ctx.disabled_features,
)
compiler = cc_common.get_tool_for_action(
feature_configuration=feature_configuration,
action_name=C_COMPILE_ACTION_NAME
)
compile_variables = cc_common.create_compile_variables(
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
)
compiler_options = cc_common.get_memory_inefficient_command_line(
feature_configuration = feature_configuration,
action_name = C_COMPILE_ACTION_NAME,
variables = compile_variables,
)

outfile = ctx.actions.declare_file("test.o")
args = ctx.actions.args()
args.add_all(compiler_options)
ctx.actions.run(
outputs = [outfile],
inputs = ctx.files.srcs,
executable = compiler,
arguments = [args],
)

return [DefaultInfo(files = depset([outfile]))]


However, this fails with the error "execvp(external/local_config_cc/wrapped_clang, ...)": No such file or directory. I assume this is because get_tool_for_action returns a string representing a path, not a File object, so Bazel doesn't add wrapped_clang to the sandbox. Executing the rule with sandboxing disabled seems to confirm this, as it completes successfully.



Is there a way to implement this custom rule without disabling the sandbox?










share|improve this question





























    1















    I'm trying to write a custom rule to compile C++ code using the cc_common API. Here's my current attempt at an implementation:



    load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")   
    load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME")

    def _impl(ctx):
    cc_toolchain = find_cpp_toolchain(ctx)
    feature_configuration = cc_common.configure_features(
    cc_toolchain = cc_toolchain,
    unsupported_features = ctx.disabled_features,
    )
    compiler = cc_common.get_tool_for_action(
    feature_configuration=feature_configuration,
    action_name=C_COMPILE_ACTION_NAME
    )
    compile_variables = cc_common.create_compile_variables(
    feature_configuration = feature_configuration,
    cc_toolchain = cc_toolchain,
    )
    compiler_options = cc_common.get_memory_inefficient_command_line(
    feature_configuration = feature_configuration,
    action_name = C_COMPILE_ACTION_NAME,
    variables = compile_variables,
    )

    outfile = ctx.actions.declare_file("test.o")
    args = ctx.actions.args()
    args.add_all(compiler_options)
    ctx.actions.run(
    outputs = [outfile],
    inputs = ctx.files.srcs,
    executable = compiler,
    arguments = [args],
    )

    return [DefaultInfo(files = depset([outfile]))]


    However, this fails with the error "execvp(external/local_config_cc/wrapped_clang, ...)": No such file or directory. I assume this is because get_tool_for_action returns a string representing a path, not a File object, so Bazel doesn't add wrapped_clang to the sandbox. Executing the rule with sandboxing disabled seems to confirm this, as it completes successfully.



    Is there a way to implement this custom rule without disabling the sandbox?










    share|improve this question

























      1












      1








      1








      I'm trying to write a custom rule to compile C++ code using the cc_common API. Here's my current attempt at an implementation:



      load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")   
      load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME")

      def _impl(ctx):
      cc_toolchain = find_cpp_toolchain(ctx)
      feature_configuration = cc_common.configure_features(
      cc_toolchain = cc_toolchain,
      unsupported_features = ctx.disabled_features,
      )
      compiler = cc_common.get_tool_for_action(
      feature_configuration=feature_configuration,
      action_name=C_COMPILE_ACTION_NAME
      )
      compile_variables = cc_common.create_compile_variables(
      feature_configuration = feature_configuration,
      cc_toolchain = cc_toolchain,
      )
      compiler_options = cc_common.get_memory_inefficient_command_line(
      feature_configuration = feature_configuration,
      action_name = C_COMPILE_ACTION_NAME,
      variables = compile_variables,
      )

      outfile = ctx.actions.declare_file("test.o")
      args = ctx.actions.args()
      args.add_all(compiler_options)
      ctx.actions.run(
      outputs = [outfile],
      inputs = ctx.files.srcs,
      executable = compiler,
      arguments = [args],
      )

      return [DefaultInfo(files = depset([outfile]))]


      However, this fails with the error "execvp(external/local_config_cc/wrapped_clang, ...)": No such file or directory. I assume this is because get_tool_for_action returns a string representing a path, not a File object, so Bazel doesn't add wrapped_clang to the sandbox. Executing the rule with sandboxing disabled seems to confirm this, as it completes successfully.



      Is there a way to implement this custom rule without disabling the sandbox?










      share|improve this question














      I'm trying to write a custom rule to compile C++ code using the cc_common API. Here's my current attempt at an implementation:



      load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")   
      load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME")

      def _impl(ctx):
      cc_toolchain = find_cpp_toolchain(ctx)
      feature_configuration = cc_common.configure_features(
      cc_toolchain = cc_toolchain,
      unsupported_features = ctx.disabled_features,
      )
      compiler = cc_common.get_tool_for_action(
      feature_configuration=feature_configuration,
      action_name=C_COMPILE_ACTION_NAME
      )
      compile_variables = cc_common.create_compile_variables(
      feature_configuration = feature_configuration,
      cc_toolchain = cc_toolchain,
      )
      compiler_options = cc_common.get_memory_inefficient_command_line(
      feature_configuration = feature_configuration,
      action_name = C_COMPILE_ACTION_NAME,
      variables = compile_variables,
      )

      outfile = ctx.actions.declare_file("test.o")
      args = ctx.actions.args()
      args.add_all(compiler_options)
      ctx.actions.run(
      outputs = [outfile],
      inputs = ctx.files.srcs,
      executable = compiler,
      arguments = [args],
      )

      return [DefaultInfo(files = depset([outfile]))]


      However, this fails with the error "execvp(external/local_config_cc/wrapped_clang, ...)": No such file or directory. I assume this is because get_tool_for_action returns a string representing a path, not a File object, so Bazel doesn't add wrapped_clang to the sandbox. Executing the rule with sandboxing disabled seems to confirm this, as it completes successfully.



      Is there a way to implement this custom rule without disabling the sandbox?







      bazel






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Oct 11 '18 at 22:39









      Kevin K.Kevin K.

      62




      62
























          2 Answers
          2






          active

          oldest

          votes


















          0














          If you use ctx.actions.run_shell you can add the files associated with the toolchain to the input (ctx.attr._cc_toolchain.files). Also, you'll want to add the compiler environment variables. E.g.



          srcs = depset(ctx.files.srcs)
          tools = ctx.attr._cc_toolchain.files
          ...
          compiler_env = cc_common.get_environment_variables(
          feature_configuration = feature_configuration,
          action_name = C_COMPILE_ACTION_NAME,
          variables = compiler_variables,
          )
          ...
          args = ctx.actions.args()
          args.add_all(compiler_options)
          ctx.actions.run_shell(
          outputs = [outfile],
          inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
          command = "{compiler} $*".format(compiler = compiler),
          arguments = [args],
          env = compiler_env,
          )





          share|improve this answer































            0














            Bazel doesn't add files as action inputs automatically, you have to do it explicitly, as you did in your second approach (ctx.attr._cc_toolchain.files). With that, ctx.actions.run should work just fine.






            share|improve this answer
























            • This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

              – Kevin K.
              Nov 30 '18 at 21:48













            • ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

              – hlopko
              Dec 4 '18 at 14:36












            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52769846%2fcustom-c-rule-with-the-cc-common-api%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            If you use ctx.actions.run_shell you can add the files associated with the toolchain to the input (ctx.attr._cc_toolchain.files). Also, you'll want to add the compiler environment variables. E.g.



            srcs = depset(ctx.files.srcs)
            tools = ctx.attr._cc_toolchain.files
            ...
            compiler_env = cc_common.get_environment_variables(
            feature_configuration = feature_configuration,
            action_name = C_COMPILE_ACTION_NAME,
            variables = compiler_variables,
            )
            ...
            args = ctx.actions.args()
            args.add_all(compiler_options)
            ctx.actions.run_shell(
            outputs = [outfile],
            inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
            command = "{compiler} $*".format(compiler = compiler),
            arguments = [args],
            env = compiler_env,
            )





            share|improve this answer




























              0














              If you use ctx.actions.run_shell you can add the files associated with the toolchain to the input (ctx.attr._cc_toolchain.files). Also, you'll want to add the compiler environment variables. E.g.



              srcs = depset(ctx.files.srcs)
              tools = ctx.attr._cc_toolchain.files
              ...
              compiler_env = cc_common.get_environment_variables(
              feature_configuration = feature_configuration,
              action_name = C_COMPILE_ACTION_NAME,
              variables = compiler_variables,
              )
              ...
              args = ctx.actions.args()
              args.add_all(compiler_options)
              ctx.actions.run_shell(
              outputs = [outfile],
              inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
              command = "{compiler} $*".format(compiler = compiler),
              arguments = [args],
              env = compiler_env,
              )





              share|improve this answer


























                0












                0








                0







                If you use ctx.actions.run_shell you can add the files associated with the toolchain to the input (ctx.attr._cc_toolchain.files). Also, you'll want to add the compiler environment variables. E.g.



                srcs = depset(ctx.files.srcs)
                tools = ctx.attr._cc_toolchain.files
                ...
                compiler_env = cc_common.get_environment_variables(
                feature_configuration = feature_configuration,
                action_name = C_COMPILE_ACTION_NAME,
                variables = compiler_variables,
                )
                ...
                args = ctx.actions.args()
                args.add_all(compiler_options)
                ctx.actions.run_shell(
                outputs = [outfile],
                inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
                command = "{compiler} $*".format(compiler = compiler),
                arguments = [args],
                env = compiler_env,
                )





                share|improve this answer













                If you use ctx.actions.run_shell you can add the files associated with the toolchain to the input (ctx.attr._cc_toolchain.files). Also, you'll want to add the compiler environment variables. E.g.



                srcs = depset(ctx.files.srcs)
                tools = ctx.attr._cc_toolchain.files
                ...
                compiler_env = cc_common.get_environment_variables(
                feature_configuration = feature_configuration,
                action_name = C_COMPILE_ACTION_NAME,
                variables = compiler_variables,
                )
                ...
                args = ctx.actions.args()
                args.add_all(compiler_options)
                ctx.actions.run_shell(
                outputs = [outfile],
                inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
                command = "{compiler} $*".format(compiler = compiler),
                arguments = [args],
                env = compiler_env,
                )






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Oct 22 '18 at 18:20









                Kevin K.Kevin K.

                62




                62

























                    0














                    Bazel doesn't add files as action inputs automatically, you have to do it explicitly, as you did in your second approach (ctx.attr._cc_toolchain.files). With that, ctx.actions.run should work just fine.






                    share|improve this answer
























                    • This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                      – Kevin K.
                      Nov 30 '18 at 21:48













                    • ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                      – hlopko
                      Dec 4 '18 at 14:36
















                    0














                    Bazel doesn't add files as action inputs automatically, you have to do it explicitly, as you did in your second approach (ctx.attr._cc_toolchain.files). With that, ctx.actions.run should work just fine.






                    share|improve this answer
























                    • This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                      – Kevin K.
                      Nov 30 '18 at 21:48













                    • ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                      – hlopko
                      Dec 4 '18 at 14:36














                    0












                    0








                    0







                    Bazel doesn't add files as action inputs automatically, you have to do it explicitly, as you did in your second approach (ctx.attr._cc_toolchain.files). With that, ctx.actions.run should work just fine.






                    share|improve this answer













                    Bazel doesn't add files as action inputs automatically, you have to do it explicitly, as you did in your second approach (ctx.attr._cc_toolchain.files). With that, ctx.actions.run should work just fine.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 29 '18 at 6:17









                    hlopkohlopko

                    1,9131322




                    1,9131322













                    • This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                      – Kevin K.
                      Nov 30 '18 at 21:48













                    • ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                      – hlopko
                      Dec 4 '18 at 14:36



















                    • This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                      – Kevin K.
                      Nov 30 '18 at 21:48













                    • ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                      – hlopko
                      Dec 4 '18 at 14:36

















                    This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                    – Kevin K.
                    Nov 30 '18 at 21:48







                    This issue was that I wasn't sure how to get from the string returned by cc_common.get_tool_for_action to the actual files associated with the tool (actually, I'm still not sure how to do that - using ctx.attr._cc_toolchain.files seems like a hack.) I understand that the files aren't added automatically.

                    – Kevin K.
                    Nov 30 '18 at 21:48















                    ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                    – hlopko
                    Dec 4 '18 at 14:36





                    ctx.attr._cc_toolchain.files is the principled way to get FilesToBuildProvider from your implicit dependencies. So no need to fear that. There is (rather unfortunate) separation between files to build from cc_toolchain and paths to those files. Ideally get_tool_for_action would return an Artifact, and a collection of related deps. We're not there now, get_tool_for_action returns a string, and actual action inputs are taken from cc_toolchain.files.

                    – hlopko
                    Dec 4 '18 at 14:36


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52769846%2fcustom-c-rule-with-the-cc-common-api%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

                    Calculate evaluation metrics using cross_val_predict sklearn

                    Insert data from modal to MySQL (multiple modal on website)