Yes, the products of the package need to dynamic and despite this, with SPM, framework dependancies of a product are statically linked/embedded in the product. The only way around this I found was to generate an .xcodeproj using Xcode 13 and xcodebuild using that.
When you build PackageDepA, that script rewrites PackageDepA to be a dynamic library. But you don't rewrite PackageDepRoot to dynamic, so it will be statically linked.
You can't archive it without the other module is because you are not using @_implementationOnly imports (or internal imports: swift-evolution/proposals/0409-access-level-on-imports.md at main · swiftlang/swift-evolution · GitHub ).
So either rewrite both Package.swift to dynamic when building PackageDepA or use the proper imports in PackageDepA, so it doesn't expose PackageDepRoot as a required dependency.
Building on this point, if you have another dependency (B) that also depends on Root, if you build A as an xcframework with version x.y.z of Root and pull that in as a dependency, the version that B uses won't necessarily be the same version that's compiled into A, which could lead to a whole host of issues.
I have been using tuist, and think it's perfect for generate a .xcodeproj for this purpose of building for .xcframework from a Swift package. I built this example MyPrivateLib that uses tuist to generate .xcodeproj, builds .xcframework, and pushes it as a Swift package MyPrivateLibRelease, which will be distributed, either as a public repo or a private repo.
You might want to look at this script which I wrote while looking into the possibility of binary frameworks for swift-syntax. YMMV but it you should be able to adapt it to create a binary framework for another package.