Difference and use of .LIB vs .DLL

,
Tags: #<Tag:0x00007fc0ddbc4e18> #<Tag:0x00007fc0ddbc4c88>

Hi all,

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?

Cheers
Trevor

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).

1 Like

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.

Thanks Jeff, that’s what I thought.

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 ?

Thanks
Trevor

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.

1 Like

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 :slight_smile:

1 Like

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.

1 Like

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

Yes, that was me :slight_smile: 9 years @ JDA, then onto IBM and now Toshiba

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:

  1. Gets the APP files from GitHub
  2. Calls the ClarionCL.exe to generate all the .CLW files etc
  3. Call the MSBuild process to convert the .EXP files to .LIB files
  4. Calls MSBuild to compile the solution
  5. Currently zips up the solution but will call the installer process to create the installer.

Thanks for all your help

2 Likes