What's a good way to manage multiple plugins from one codebase?

Like most devs, I put all my modules into a single plugin. Mainly because it’s easy. But I’m interested in making a second plugin using the same shared code that’s in my one github repo. What’s an easy way to make multiple plugins from one repo? Obviously, they need different plugin.json files, and probably other things.

It could be done by making the common code repo be a submodule to each of the plugins, but that seems like it would be a pain to develop in that environment.

It could be done by putting each plugin on a branch. This would be a bit of a kluge but seems workable.

Anyone out there already solved this problem? Thanks in advance.

1 Like

Actually I work with only one plogin, but planned the layout of my sources to spit my plugin easily. At the end I’m going to build a kernel that can be included and linked to different plugins.

Just take a look at my repo GitHub - Ahornberg/Ahornberg-VCV-Modules: Modules for VCV-Rack

I didn’t try it, but maybe using got submodules?

I think that would be difficult. Wouldn’t that mean that while developing I would need to develop in my master repo, then keep updating the downstream projects to pick up every change? I guess is the main module defines its own “master dev” plugin that has all of them in it it would work. Hmm…

Of course I’m particularly interested in anyone who is doing something now and would like to share experiences.

Sorry, I’m another dev interested but hasn’t actually done it.

I imagine going the three repos + submodules way, two plugins and a common repo, common being a submodule in both plugin repos.

If you’re mainly working on one plugin then you can edit common and that plugin as a single checkout, no push / fetch problems.

It’s a bit of a pain when you need to use recent changes to the common repo in the other plugin, you’d have to push the common changes and fetch them in your other plugin checkout. That seems bearable assuming you’re not switching between different plugins every few minutes.

One repo with both plugins might be nice for developing multiple plugins simultaneously, but I imagine it doesn’t play well with the VCV Rack build system. I don’t know if we can do things like specify a plugin target or a subdirectory to perform the build from.

You mean I edit the common code and the submodule code at the same time, and then later I push them back to their respective repos? I don’t quite understand.

Also, where do the resources go (like svg files)?

Yes, that’s why I mentioned the hack of branches. Each branch would have one plugin in it only. One could have (I think) two different build jobs in the library, one for each branch.

1 Like

Yeah you’d have your plugin checked out with the common submodule checked out inside it. You can modify the submodule code and the plugin code however you want locally. Then you only need to push to github when you want others to see the code, or when you want to work on your other plugin with updated common code.

The svg files would be up to you, store common assets in the common repo, unless they have to be in ./res and I haven’t noticed?

Your branches idea sounds like it would work, it sounds like a good backing plan. I’m just hoping there’s a better way. You’d have to remember to merge your common code between branches, similar to submodules. Submodules can be a pain to work with.

Looks like assets are relative to the top level plugin directory, so you could reference common ones like this:

asset::plugin(pluginInstance, “common/res/panel.svg”)

@cschol - you know a ton about the library build process. What’s a best practice for publishing multiple plugins from the same open-source repo?

In general, the library repository pins plugin versions to a unique SHA. That SHA can point to any branch in a plugin repository. The library repository itself uses git submodules to facilitate this connection.

I think what I am about to say has been mentioned in posts above, but I just want to clarify how these options connect to the library repository.

Two options, that seem feasible to me:

  1. You can have one repository per plugin and manage common code with a git submodule. The build process will clone any submodule referenced in the repository before building the plugin.

  2. You can have your common code in a common branch of a single repository and have plugin branches for each of your plugins in that same repository.

Which of these options works well for you depends on your git skills and your preference, IMO. You either have to deal with handling a separate repository and synch’ing your plugins with the common repository via submodule or deal with merging upstream changes from the common branch into your plugin branches.

Either way, you submit a SHA to the plugin library, which uniquely identifies your plugin and its version.

2 Likes

cool, thanks. Yeah, perhaps most of that has been said, but it’s very helpful to see it all in one place. From a trusted source.

1 Like

Christoph: Will this simple directory structure not work with the Rack build system?

MyRepo
├── CommonCode
├── MyPlugin1
└── MyPlugin2

No, the manifest must be in the root, and there can only be one. Same with resources, although that not a deal breaker. Oh, and only one plugin dll!

I had a look into this at the weekend and it is possible to do.

You have common code located in root directory and then for each plugin a subfolder with according sources for them. Each plugin subfolder contains all required ressources, plugin.json etc. for the specific plugin.

You have a Makefile in the root git project folder where you can define anything you want to build your project with all plugins at once or whatsoever.

The problem is when it comes to publish a specific plugin in the VCV library with the VCV plugin build system. For getting this to work you need again in each plugin subfolder a Makefile with the according definitions to build this plugin.

When the VCV library build system build your code it will checkout the whole repository with all plugins and execute the Makefile in your project root directory. Basically all you have to do is to delegete the called build targets to your plugin subfolder Makefile of the plugin you want them to build and publish.

This means, you need to define all make targets in your root Makefile like dep, install etc. (I don’t know all of them) probably also dist.

For example it should look then like this

...
dep:
	$(MAKE) -C plugin-1 dep
	$(MAKE) -C plugin-2 dep

dist:
	$(MAKE) -C plugin-1 dist
	$(MAKE) -C plugin-2 dist
...

To solve the problem that they can only build and publish 1 plugin at a time you have then to create a release branch of your project and adapt the build targets so it just delegates the build to the plugin subfolder you want them to build. Then you notify them about your update and give them the release branch or tag of the release branch. If you tag the release branch you can then just delete the release branch, because it is basically just for adapting the Makefile for the library build.

I think this is it and I hope it will help.

1 Like

Thanks for this info. very interesting.

@Squinky - I did now an test with a fork of your repository.

You can have a look at the changes here:

I moved all the source code of the plugin itself into a plugin-1 subfolder and used the common source code in the root directory. There is only one problem with this - the plugin subfolder gets now polluted with the built objects artifacts of the common code that is referenced from the root directory. Because it is referenced relative with .. from the plugin subfolder Makefile and the make compile rule does now create the object files into a layout e.g. build/../xyz/xyz.o which means it goes on level up from the build dir. I tried to avoid this by using the absolute path to the source files, but this doesn’t work on Windows, because the build rule contains then the drive letter with the : (e.g. D:User/xyz) and make can’t handle this. See also here for the error - use absolute path for source files · qno/SquinkyVCV@c89e35d · GitHub

But apart from this it works. Maybe somone can find a solution for this problem.

You can check and test if the built plugin works by downloading artifacts from here - CI - don't build with -j · qno/SquinkyVCV@fe192b3 · GitHub

2 Likes