# Managing package dependencies with Bazel

**URL:** <https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044>\
**Category:** App Development\
**Created:** [February 4, 2021, 4:47pm UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044 "2021-02-04T16:47:57Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexander\_Bernauer](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/alexander_bernauer/32/1703_2.png) [@Alexander\_Bernauer](https://forum.canton.network/u/Alexander_Bernauer)\
**Post date:** [February 4, 2021, 4:47pm UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/1 "2021-02-04T16:47:57Z")

</div>

Hi

I have a mono-repo with Bazel. There are two components A and B, both a DAML project, where A depends on B.

I can `daml damlc build` components B, no problem. The file `B.dar` is then somewhere in `bazel-out/`.

But how do I make component B available to the build of component A?

The documentation suggests to list `B.dar` in the dependencies section of the `daml.yaml` file of component A. But this means doing something like `../../bazel-out/k8-fastbuild/bin/components/B/B.dar` _ugh_.

I understand I could also just list `B` as an absolute name under A’s dependencies. But then I need to have `B.dar` be included in the package db that the build for component A is using. Am I getting this right?

If so, how do I create a package db that includes `B.dar`? And how would the Bazel build rule look like that accomplishes this?

Or is there another way I am not seeing right now?

Thanks and regard,  
Alex

---

<div class="post-metadata">

**Author:** ![bernhard](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/bernhard/32/356_2.png) [@bernhard](https://forum.canton.network/u/bernhard)\
**Post date:** [February 5, 2021, 9:11am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/2 "2021-02-05T09:11:23Z")

</div>

Since your `B.dar` ends up in `bazel-out`, I assume the `daml build` command (no need for `damlc`) is run inside a Bazel rule. Probably a `Genrule`?  
And I assume the `Genrule` has the `B.dar` as its output as well.

If so, the “right” way of using that dependency in `A` would be to also build `A` using a `Genrule`, which takes the rule of `B` as a dependency.

Say you have

```haskell
genrule(
    name = "B",
    srcs = glob(sourcepathB/**),
    outs = ["B.dar"],
    tools = ["//.../daml"]
    cmd = """
      cd sourcepathB
      $(execpath //.../daml) build -o $@
    """
)

```

Then you can use that dependency in the build rule for `A`.

```haskell
genrule(
    name = "A",
    srcs = glob(sourcepathA/**) + [
    "//pathToB:B"
    ],
    outs = ["A.dar"],
    tools = ["//.../daml"]
    cmd = """
      cd sourcepath
      mkdir -p lib
      cp $(location //pathToB:B) lib
      $(execpath //.../daml) build -o $@
    """
)

```

Now you’d have to have to reference `lib/B.dar` in your `daml.yaml` file.

This doesn’t integrate with the Daml VsCode plugin. You’d have to move the `B.dar` file to the `lib` directory after changing `B`.

If you want an even more solid Bazel solution you can write Daml rules in Skylark. You can find examples of this [in the Daml repo](https://github.com/digital-asset/daml/tree/main/rules_daml).

I think the only way to get bazel rules _and_ a working Daml Studio is probably to do what you suggested (dependency path in bazel\_out) or at best prettifying that via a symlink.

---

<div class="post-metadata">

**Author:** ![Alexander\_Bernauer](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/alexander_bernauer/32/1703_2.png) [@Alexander\_Bernauer](https://forum.canton.network/u/Alexander_Bernauer)\
**Post date:** [February 5, 2021, 10:02am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/3 "2021-02-05T10:02:08Z")

</div>

Thank you very much, @bernhard , for your help.

How does `daml.yaml` need to list the dependency on `B.dar` for damlc to pick it up from the component A’s `lib` folder? Or is this a runtime flag for `damlc`?

For me `damlc` is looking for `B.dar` in `/usr/local/.daml/sdk/1.9.0/daml-libs/` and obviously can’t find it there.

I will check out the Skylark implementation. I was just hoping I could get away with genrules.

Regards,  
Alex

---

<div class="post-metadata">

**Author:** ![bernhard](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/bernhard/32/356_2.png) [@bernhard](https://forum.canton.network/u/bernhard)\
**Post date:** [February 5, 2021, 10:40am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/4 "2021-02-05T10:40:46Z")

</div>

The stanza in the `daml.yaml` of `A` should be something like

```haskell
dependencies:
  - daml-prim
  - daml-stdlib
  - daml-script
  - ./libs/B.dar

```

ie if you give it a relative or absolute path, it’ll look there, not in the `daml-libs` folder of the SDK.

---

<div class="post-metadata">

**Author:** ![Alexander\_Bernauer](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/alexander_bernauer/32/1703_2.png) [@Alexander\_Bernauer](https://forum.canton.network/u/Alexander_Bernauer)\
**Post date:** [February 5, 2021, 10:57am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/5 "2021-02-05T10:57:51Z")

</div>

Thank you, @bernhard, this works.

For the records, this is my `BUILD` file for A:

```
genrule(
    name = "A",
    srcs = glob(["src/**"]) + ["daml.yaml", "//path/to/B:B"],
    outs = ["A.dar"],
    cmd = """
        mkdir -p path/to/A/lib
        cp $(location //path/to/B:B) path/to/A/lib
        daml build --project-root path/to/A -o $@
)

```

and my `daml.yaml` looks just like what you have quoted.

```
dependencies:
  - daml-prim
  - daml-stdlib
  - daml-script
  - ./libs/B.dar

```

Thanks again.  
Alex

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [February 5, 2021, 8:51pm UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/6 "2021-02-05T20:51:38Z")

</div>

This is a common problem when using Bazel with off-the shelf, language-specific build systems (I’d count `daml build` as one in this case). If you hand over control fully to Bazel, things like IDE integrations break which is obviously annoying (this is the approach taken by `rules_daml` @bernhard pointed you to above). If you don’t, then you have to keep things in sync. In your example that means manually updating `libs/B.dar` when it changes (or try to symlink it from the bazel dir but that gets increasingly hard once you take different operating systems, optimization levels, … into account all of which influence the directory bazel uses).

There are a few options to get out of this conundrum that different languages have chosen:

1. Instead of pointing your IDE directly at your underlying tool (`damlc` in this case) you point it at some wrapper script which queries Bazel to build and locate depedencies and then invokes the underlying tool with some extra flags to make it find dependencies. This is the approach taken by Haskell tooling for example and Scala also does something along those lines.  
For Daml, this would mean that you have a `daml.yaml` with an empty list of `data-dependencies`/`dependencies`. You then need your Bazel build setup to produce package databases, e.g., by wrapping `daml damlc init` or maybe even go lower-level and construct them manually (unfortunately no docs on this atm). Finally, your wrapper script would find the location of those package databases and then invoke `daml damlc ide --package-db=… --package-db= … --package=… --package=…` and your IDE should find dependencies. This is probably the approach I’d recommend but it is a fair amount of effort.
2. Another option taken by `rules_nodejs` is to have Bazel step out of its build root and mess around in the actual source tree, e.g., modify `node_modules`. In this case, this could mean modifying `daml.yaml` to point to the location of the dependencies. That requires in some sense less effort since you don’t need the wrapper script but it also gives up on Bazel managing your stuff cleanly and you get back to the good old days where `rm -rf node_modules` solves your problem (or whatever the equivalent of that in Daml is 😉 )
3. Lastly, you could also imagine some kind of native support in the compiler to make the location of source files and dependencies configurable. I’m not really aware of any language that has proper support for this atm that works well with Bazel but it has at least been discussed for Go in the context of [Expose generated Go files to editors and IDEs · Issue #512 · bazelbuild/rules\_go · GitHub](https://github.com/bazelbuild/rules_go/issues/512).

So unfortunately, while I think making 1 work is definitely feasible, the current situation is not great. I’ve opened [Improve UX when compiling Daml code in Bazel or other build systems · Issue #8767 · digital-asset/daml · GitHub](https://github.com/digital-asset/daml/issues/8767) to track this on our side and we’ll see what we can do to make the UX here a bit better.

---

<div class="post-metadata">

**Author:** ![Alexander\_Bernauer](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/alexander_bernauer/32/1703_2.png) [@Alexander\_Bernauer](https://forum.canton.network/u/Alexander_Bernauer)\
**Post date:** [February 8, 2021, 8:22am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/7 "2021-02-08T08:22:59Z")

</div>

Thank you very much, @cocreature, for this extensive response. This is really helpful, since I have been wondering about these things.

From my perspective the native tools should indeed be highly configurable with where they read input from and where they write output to. I guess that would be option 3.

I wonder into which category the Java and C++ toolchains fall. They seem to be rather well supported by Bazel.

Regards,  
Alex

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [February 8, 2021, 8:39am UTC](https://forum.canton.network/t/managing-package-dependencies-with-bazel/2044/8 "2021-02-08T08:39:40Z")

</div>

Java and C++ are a bit special since they are natively supported by Bazel rather than being based on a separate rule set. You still run into the same issue though. Your IDE tooling might expect a Maven project or a CMake project and you have to teach it how to handle Bazel. Not quite sure how that works there.
