To illustrate better how the functionality works, we are going to use an example application. You can find the sample application under: C:\Program Files\Micro Focus\Studio Enterprise Edition 6.0\Examples\OPEN-PLI\Dynamic Subroutines.
The main program is A and it is calling a subroutine called B which in turn calls a subroutine C.
To build this application, you need to understand the CALL statements present in each routine and build them from the lowest calling level to the highest. Once the application has been built, you can rebuild individual shared objects without having to relink all shared objects.
To build the example application where A is calling B and B is calling C, you need to execute the commands below in the following order:
mfpli -o C.o C.PLI
ld -shared --warn-unresolved-symbols -o C.so C.o -melf_i386 -rpath . $MFPLI_PRODUCT_DIR/lib/libmf.so
mfpli -o B.o B.PLI
ld -shared --warn-unresolved-symbols -o B.so B.o C.so -melf_i386 -rpath . $MFPLI_PRODUCT_DIR/lib/libmf.so
mfpli -o A.o A.PLI
ld -shared --warn-unresolved-symbols -o A.so A.o B.so -melf_i386 -rpath . B.so $MFPLI_PRODUCT_DIR/lib/dllmain.o $MFPLI_PRODUCT_DIR/lib/nojw.o $MFPLI_PRODUCT_DIR/lib/noofm.o $MFPLI_PRODUCT_DIR/lib/libmf.so *.so $HOME/staff/opli/DMFTEST/debug/
As you can see, only the main program A is linked with dllmain.o.
All subroutines are linked with the PLI RTS (libmf.so) and the shared objects for any routines that they call.
In the three ld commands there is --warn-unresolved-symbols which allows you to catch any unexpected missing bits. It is not required but can be useful.
You need the -melf_i386 option only if building on a 64-bit Red Hat or SUSE Linux.