Best practice for multiple apps with common files in one git repo

What do you do when you have 2 (or more) apps with a significant common code/resource base and you want to have them in 1 git repo and be able to develop with VSC?

I already have one project like that, but it has some issues, and I'd like to start another one. So the basic directories are something like:

the common stuff probably in the root or a common/ directory:

resources
resources-eng
...
resources-round-390x390
...
source
source-round-390x390
...

And for the 2 apps: FooApp, FooDF in their own directories, their respective manifest, jungle file and resources, sources which are not common:
FooApp/
- resources
- source
- manifest.xml
- jungle.monkey

jungle.monkey looks something like:
project.manifest = manifest.xml
base.sourcePath = source;../source
base.resourcePath = ../resources;resources

but then we have to add some more lines even for those mappings that we usually "get for free", i.e: translations: resources-eng, display-size, device specific resources that we have to add to the jungle file (which is ok, I can generate it with a script)

But then how do I open the projects in VSC? If I open the git repo's root, then how can I run either FooApp or FooDF?
The only workaround I found so far is to open FooApp/ in VSC and run it from there, but then there are some things that don't work well, because of some confusion with the common files, i.e: ../source/Common.mc

  • I would use git submodules. (This is the solution I see and use in my day job.)

    e.g. You would have the following repos:

    FooApp
    FooDF
    FooCommon (common submodule for the other repos)

    FooApp will look like this on your disk, after the FooCommon submodule is added:

    FooApp/
    |       
    |-------source/
    |       |
    |-------resources/
    |       |
    |-------FooCommon/ (submodule)
    |       |       
    |       |-------source/
    |       |       
    |       |-------resources/
    |       |       
    |       |
    ...

    Pros:

    - well-supported solution that works with VS Code (in contrast, if you just have two unrelated repos and use symlinks to connect one to the other, certain things like built-in source control support may not work properly in VS Code)

    - ability for FooApp and FooDF to use different versions of FooCommon if necessary

    Cons:

    - bit of additional cognitive overhead when dealing with modules (you need to update your workflow to initialize and update any submodules in your repo)

    - if you're just trying out changes to FooCommon without committing them, and you want the changes to apply to both FooApp and FooDF, you'll have to make the changes twice

  • I didn't know git submodules, might try it, but I don't like that there are 3 git repos. I don't even want to have 2. The whole point is that there's a Data Field and an Device App that are the same functionality, same version, if I add a feature to one, then it's added to the second one as well.

  • All right, put everything in one repo, have a common folder at the top level, and use symlinks in each of the Monkey C projects to point back to the common folder. Then you can open each of the projects as a separate "root folder" in VS Code. (This will also work if you open both projects in a multi-root workspace.)

    FooCommon/
    |
    |-------source/
    |       |
    |-------resources/
    |       |
    ...
    FooApp/ (open as project root)
    |
    |-------source/
    |       |
    |-------resources/
    |       |
    |-------common => ../FooCommon
    ...
    FooDF/ (open as project root)
    |
    |-------source/
    |       |
    |-------resources/
    |       |
    |-------common => ../FooCommon

    The downside is that git integration probably won't work properly for the files in the symlinked folders. I'm not sure exactly what problems you're seeing with using "../somefolder" references in your jungles, or whether using symlinks would solve those issues. (I don't doubt that you would see issues though. I think I've tried the same thing as you in the past, and I vaguely recall that there were issues.)

    This is a solution I have used for my own personal Monkey C projects, since I don't want to mess with submodules either. In a professional setting with multiple team members which need to share common code with vastly different projects, submodules are probably the best solution. It may not be worth it for a personal project.

  • Monkey Barrels could be the solution. Do all your devices support this concept? According to "compilerInfo.xml" these are CIQ 1.4.0, 1.5.0 and 2.4.0+.

  • I tried barrels once, but never used, because it more or less has the same issues as the git submodule: it's not user friendly, when I am the only developer working on both parts and I am changing something in the barrel, then I need to compile the barrel and then compile the app (and between them maybe even edit the version somewhere) In short not for a one man show. It's perfect for releasing a library for others to use it.

  • I need to compile the barrel and then compile the app (and between them maybe even edit the version somewhere)

    You don't have to do this.

    You can declare barrel version to be 1.0.0 (or other fixed version you like) once and for all, and select barrel's "monkey.jungle" and not the "MyBarrel.barrel" file when declaring app's dependency. You can even omit barrel version in project's manifest, as this version won't affect anything for jungle-type depencency.

    The workflow will be the following: change code inside barrel, compile and run app, see changes in the simulated app, compile and run datafield, see changes in the simulated datafield (if changes in barrel don't make app/datafield project unbuildable, ofc).

    This is a native way of using common code between projects for any number of developers and it lacks disadvantages of symlinks approach, like weird VS Code's VCS plugin behavior or not reflecting recent code changes in the simulator.

  • One more thing I remembered: I think that my app only saw the code from the barrel but not the resources. I might have doing something wrong, or this might have been fixed since. Can I have resources (strings, fit-contributions.xml, properties, settings, icons) in the barrel and use them in the app? If the answer is yes, then does it also include code in the app (not inside the barrel) being able to access these things from the barrel?

  • I use barrel resources only inside barrel itself, but it should work (and it worked when I tested it recently) if you use "@MyBarrel.Strings.StringFromBarrel" and "$.MyBarrel.Rez.Strings.StringFromBarrel" syntax in the app/datafield.

    EDIT: It is mentioned on the page I posted earlier: search for "@IconLibrary.Drawables.myIcon" and "IconLibrary.Rez.Drawables.myIcon" there.