The purpose of the work is to reduce the overhead of storing a large number of utilities written in golang.
One of the side effects of the golang static compilation is the relatively large overhead of storing the runtime and all the libraries used within each executable file. For example, a small utility, which only does what accesses the network to the server and executes simple received commands - weighs 5.5 MB.
When such a utility is the only one - it is not scary in the modern conditions. When utilities accumulate and there are already a few dozen or hundreds of them, it becomes humanly pitifully hundreds of megabytes leaking into nowhere.
To solve this problem, I wrote the
multiex library, which I share with the community. With its help, you can combine several programs into one executable file with minimal changes inside the program code and without changing the external behavior. The thought was taken from busybox - all programs are compiled into one file, and the executable code is selected at launch, based on the name of the file being run.
')
To connect programs, you need to call the recorder function, for example, like this:
func f1(){ if os.Args[1] == "asdf" { println("ok") } } multiex.Register(multiex.ExecutorDescribe{Name: "test", Function: f1})
The name of the program is transferred in the structure. If the executable file is called with the name test, the function f1 will be called. Next comes the normal operation of the function without changes, incl. you can sort out the command line arguments passed in the usual way.
./test asdf
./test can be the name of an executable file, hard or symbolic link.
In addition, you can call the f1 function if the first parameter of the executable file is --multiex-command = test. In this case, the --multiex-command = test parameter will be removed and the f1 function will also be able to parse its arguments as usual.
./any --multiex-command = test asdf
The library has already implemented the program of the same name with the name multiex, at the moment it can:
1. Display a brief reference about what kind of file it is and what programs are included in it - if the file was called with an unintended name
2. Create symbolic links to all programs included in the executable file. Links are created in the same folder as the executable file itself.
./any --multiex-command = multiex install
In this case, the link to the multiex itself is not created.
In
github.com/rekby/multiex-example , an example of connecting programs is shown:
1. Registration of functions directly in the main compiled module. With this method, the main assembly module is aware of the specific functions to be included, and when adding a new function, it is necessary to add its transfer to the registration list. In the included programs themselves, there is no need to add dependence on multiex - it is enough to have the exported Main function.
2. In the assembly module, plug-ins are imported, and each module itself registers its functions during the initialization process. Here the assembly module knows only the list of included modules, and not every function. Each module itself determines which functions it will export and to export a new function, it is enough to fix only the module with this function.
3. Naturally, both methods can be combined (in the example, the combined version is shown).
In addition, each program can maintain its independence and, if necessary, compile separately from the others into its own file and run as usual. This is done by adding the subfolder
main to the program source. Moreover, this file can be the same for all projects and just be copied without changes wherever required.
github.com/rekby/multiex