Daml upgrade and duplicate modules during codegen

Hello !
I’ve got a question regarding upgrading daml models and associated codegen. I have the following structure:

├── v0
│   ├── TestContract.daml
│   ├── Utils.daml
│   └── daml.yaml
└── v1
    ├── TestContract.daml
    └── daml.yaml

v0/TestContract.daml and v0/Utils.daml both contain a dummy contract
In v1 I want to make changes to TestContract (but not Utils, it stays the same)
v1/TestContract.daml looks like this

module TestContract where

import Utils
import qualified Test010.TestContract as TestContract010

template TestContract with
        issuer: Party
        owner: Party
    where
    signatory issuer

    choice Dummy: ContractId TestContract with
            previous: TestContract010.TestContract
        controller issuer
        do
            create TestContract with
                issuer = previous.issuer
                owner = previous.issuer

v1/daml.yaml looks like this

sdk-version: 2.2.1
name: test
source: .
version: 0.2.0
start-navigator: false
dependencies:
  - daml-prim
  - daml-stdlib
  - daml-script
data-dependencies:
  - ../v0/.daml/dist/test-0.1.0.dar
build-options:
  - '--package'
  - 'test-0.1.0 with (TestContract as Test010.TestContract)'
codegen:
  java:
    package-prefix: com.daml.generated.test
    output-directory: ../java
    verbosity: 2

I can daml build this without errors. I have access both to the old and new TestContract in v1/TestContract.daml
But for the codegen, I get a

Duplicate module com.daml.generated.test.TestContract found in multiple packages 27ada4468b6b04a1fecaddfca3cdf29759353fa264670aba7101ca7872e8ffb1, 8bc2d90ec167649013cd62dbb41d63af41797a6d48a12086c5904309186b80f4. To resolve the conflict rename the modules in one of the packages via module-prefixes.

Adding

module-prefixes:
  test-0.1.0: prefix010

does make it work, but it means that all modules of v1 are now generated under a java package prefix101 . This makes sense for TestContract (since there are 2 versions of it now), but not really for Utils which hasn’t changed, but all references to it in the code now need to be updated. If there were other modules in v 0.1.0 that would be the case for all of them.
So my question is what is the recommended way to approach this type of model update. My first thought was expecting

build-options:
  - '--package'
  - 'test-0.1.0 with (TestContract as Test010.TestContract)'

to be picked up by the codegen and generate the TestContract class (and only that one) for 0.1.0 in a test010 java package for instance.

Any thoughts? :slight_smile:

1 Like

I suggest introducing a unique module-prefix for v1 and each future version. This is stable with respect to current references to v0, and defines a path that will remain stable for v1 immediately as you introduce it, and with each future version as well.

The problem with placing unchanging modules in the same package as changing modules is that, fundamentally, they all change. In the topology you’ve described, Utils all get new package IDs to go along. That makes them distinct with respect to the ledger API, which is more-or-less the primary target of codegen, and means that dealing with that distinction is something you cannot avoid. Having two generated copies of Utils is the most straightforward way of being able to deal with that distinction.

If you want Utils to “not change”, then it genuinely needs to be in a separate Daml package, not just a separate module. We split up the standard library for a similar reason:

For the same reason, we recommend putting triggers, scripts, and such in separate packages, so that they can be altered with reckless abandon without having any on-ledger implications.

2 Likes

Hi Stephen!

Thanks a lot for your answer, that clarifies it for me :slight_smile:

2 Likes