I know that a .LIB is a static library which is linked into an .exe at compile type whereas a .DLL is a dynamic library that is loaded at runtime. So if my project is setup to use .DLLs why does the compiler need to reference the .LIB files during compile time? And does it actually make use of the .LIB file in any way? ie: What would happen if the .LIB and .DLL were out of sync with each other?
When you use âDLLâ link mode, corresponding LIB file doesnât contain a code, it contains only a list of exported from the dll functions which you can call from your code directly (without LoadLibrary api).
If your exports use mangled prototypes (which is the usual way when linking Clarion DLL â Clarion DLL) then you could get unresolved for export types of errors on link if the mangle doesnât match the prototypeâŚ
If you use the NAME() attribute (or C or PASCAL conventions), then mangling isnât used, and you can link OK, but you can still get into trouble at run-time if the prototypes donât match.
If you use a LIB that doesnât match its DLLâs prototypes, youâll get a run-time error.
If you use a LIB whose exports donât match the caller, youâll get an unresolved external error when you link the caller.
Here is my situation: Keen on anyoneâs views (there is of course one obvious one, but thatâs challenging to do):
I am helping an organisation (who shall remain anonymous for now) who have a large(ish) system with the generation of 20 .DLLs and one .EXE (so 21 .APP files). However, in their wisdom over the years they have just referenced different .DLLs and so the whole system is one large circular-dependancy â seriously - the DLL with the least references to other DLLs still references more than half of all other modules and those modules reference back to it anyway).
if you delete all .LIB and .DLL files you cannot re-compile the system as the compilation process wants to reference the various .LIB files which have not been built yet and so there is a compilation ERROR (not warning).
The reason they have been OK for a long time is they always work in the same folder and never delete anything. Iâm trying to clean things up, automate build processes, automate deployment, allow multiple developers (with care) etc and am a believer in ensuring a clean compilation process.
So, any thoughts form anyone other than fixing all the circular references ?
If it were me, Iâd definitely use Rick Martinâs Version Control add-in. It would simplify moving procedures around, but it still takes some getting used to. Search for Upper Park on Clarionshop.com. Itâs the âUpper Park Solutions Version Control Interfaceâ.
Hopefully, you can figure out an arrangement strategy that works for you.
Well⌠If you have the EE version of Clarion, You can actually compile it all, but you might have to compile 2 or 3 times one after another to create the appropriate bits. you get a little further each time.
Itâs still a bit messy however. My personal preference is fix the circles. It might up your app count a little but itâs the cleaner option.
The LIB files are made from the EXP files. You can make all the LIB files with a project that uses #implib as described in the below link. You need to generate APPs to make the EXP files which I do with a BAT file running ClarionCL.exe which is also covered in this topic
This post is also good putting LIB with DLL files in the Project folder. Clarionâs default setup puts the LIB in OBJ which tends to cause problems.
Technically the LIB file is not for the Compiler its there for the Linker to verify a procedure name you entered exists in that library. If the Linker cannot find a matching name you get an Unresolved External error.
In Windows procedure names are case sensitive but not in Clarion. The LIB has the exact case sensitive name for the Linker to lookup and place in the EXE / DLL PE Import Table. That is another purpose of the EXP file to provide case sensesitive names for the LIB and DLL PE Export Table. App generation makes names all UPPER in the EXP but they donât have to be.
Remove the circular dependencies is the right answer here.
Depending on how complicated the dependencies are you can probably build the full product the way it is, but itâd take several iterative passes of building everything over and over again before itâll link properly.
To answer your specific question, the .LIB is just used at compile time so that the linker can resolve any procedure calls in the .EXE to the right .DLL. Without the .LIB the linker wonât build your .EXE file.
From the linkerâs perspective having a .LIB out of sync with itâs DLL is effectively the same as not having a LIB file in the first place, it when the app is calling procedure foo() the linker wonât know what DLL the EXE needs to run.
I worked on a product 15+ years ago that was built of 160 apps, if we could handle this then Iâm sure you can do it now
Microsoft calls these Mutual Imports. There is no problem beyond trying to do a clean build with no LIB files:
The problem with mutually importing executable files (usually DLLs) is that neither can be built without building the other first. Each build process requires, as input, an import library produced by the other build process
The solution described on MSDN similar to what I describe for Clarion, a Project performing #ImpLib commands makes the LIB before compiling and linking the APP projects so they build in one pass.
The solution is to use the LIB utility with the /DEF option, which produces an import library without building the executable file. Using this utility, you can build all the import libraries you need, no matter how many DLLs are involved or how complicated the dependencies are.
In the long run itâs nice to have your Projects and DLLs as a nicely organized tree versus a big bush where everything calls everything. But it can be a lot of work. the #ImpLib Project lets you deal with it. On my GutHub I do have a tool named App Splitter that I have used for breaking up Apps.
Not quite so⌠There are (rare) cases where they can cause a GPF. Usually with an âobject freed twiceâ message. Seems the DLLs can get confused when disposing.
I have heard of problems during destruction but never run into it myself. Every multi-DLL system I work on now, and in the past, has many mutual imports and I have not had errors or crashes.
The OP reported no errors or crashes just build problems that can be solved with #implib. Iâm not sure it can build using an SLN, I use BAT files with ClarionCL and MsBuild. I think on that link I posted I have an example with DLL Tutor.
I have, Itâs rare I must admit. I had instability issues solved on one project once the cyclic calls were dealt with. While I canât say for sure what it was, the coincidence is compelling. Iâve also read of others with a similar experience
Thanks Paul, your name seems familiar, I have a feeling we worked on the same software at the same time? Would it have been WinDSS @ JDA Software (I was in the UK office)
Thanks all for your thoughts and comments. Much appreciated. I will do the #IMP change in the short term and longer term resolve the circular dependancies. Cheers
Thanks to everyone for their responses and help. While I cannot easily correct the circular dependancies (although would like to over time) I used the method outlined by @CarlBarnes in his post Msbuild example for Clarion which works really well.
I now have a multi-stage TeamCity build process which:
Gets the APP files from GitHub
Calls the ClarionCL.exe to generate all the .CLW files etc
Call the MSBuild process to convert the .EXP files to .LIB files
Calls MSBuild to compile the solution
Currently zips up the solution but will call the installer process to create the installer.