Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Solution for creating resource-only DLLs

22 views
Skip to first unread message

Leif Ekblad

unread,
Nov 4, 2011, 4:38:11 PM11/4/11
to
I removed the error "No exports" from wlib, but it seems like this was not
the way to solve this issue. In Borland's IDE, there are no problems with
resource-only DLLs, and without some kind of fix to this issue I'd be forced
to continue to generate resource-only DLLs with Borland instead. Couldn't we
not at least change "No exports" to a warning instead of a fatal error which
seems totally misplaced?

Possible solutions:
1. Change "no exports" to a warning, which would not abort build in IDE
2. Create a new target type "resource DLL" in the IDE, which would neither
require an empty stub, nor would it create the import library. Possibly this
target could be only RDOS, if no other environment needs it.

Suggestions?

Leif Ekblad



Hans-Bernhard Bröker

unread,
Nov 4, 2011, 4:53:58 PM11/4/11
to
On 04.11.2011 21:38, Leif Ekblad wrote:
> I removed the error "No exports" from wlib, but it seems like this was not
> the way to solve this issue. In Borland's IDE, there are no problems with
> resource-only DLLs, and without some kind of fix to this issue I'd be forced
> to continue to generate resource-only DLLs with Borland instead. Couldn't we
> not at least change "No exports" to a warning instead of a fatal error which
> seems totally misplaced?

Seems you just demonstrated yourself that no, we can't, because even
_removing_ that error, by your own observation, didn't make things work.

What's so important about keeping those DLLs resource-only? Why can't
you live with a dummy export?

Leif Ekblad

unread,
Nov 4, 2011, 5:10:36 PM11/4/11
to
Hans-Bernhard Bröker:
> Seems you just demonstrated yourself that no, we can't, because even
> _removing_ that error, by your own observation, didn't make things work.

But it DID work. I built the resource-DLLs yesterday with the OW IDE, and it
worked just fine. What didn't work was that I needed a dummy LibEntry
procedure stub in order to build them, but that was also the case with
Borland. However, with Borland, I could use the same stub for all the
different language DLLs in the same directory, but with OW, I need to create
a custom stub for each of them.

> What's so important about keeping those DLLs resource-only? Why can't you
> live with a dummy export?

I kind of dislike it when I have to live with lesser functionality after
moving from BCC to OW :-)

Leif Ekblad


Paul S. Person

unread,
Nov 5, 2011, 1:47:17 PM11/5/11
to
On Fri, 4 Nov 2011 22:10:36 +0100, "Leif Ekblad" <le...@rdos.net>
wrote:

>Hans-Bernhard Bröker:
>> Seems you just demonstrated yourself that no, we can't, because even
>> _removing_ that error, by your own observation, didn't make things work.
>
>But it DID work. I built the resource-DLLs yesterday with the OW IDE, and it
>worked just fine. What didn't work was that I needed a dummy LibEntry
>procedure stub in order to build them, but that was also the case with
>Borland. However, with Borland, I could use the same stub for all the
>different language DLLs in the same directory, but with OW, I need to create
>a custom stub for each of them.

If I understand this correctly, every Win16 DLL created with OW
includes a LibEntry() defined in ow\rel2\src\startup\win\libentry.asm.
It is used for startup code. I seriously doubt that a special version
is needed for each and every DLL.

Searching online for LibEntry() produces a Microsoft KnowledgeBase
article (http://support.microsoft.com/kb/69894) that applies to
Windows 3.0 and 3.1. It also contains startup code.

And both call LibMain(). Back in the 90's, when I was playing around
with Watcom and C++, I created DLLs containing only two items:

1) A copy of my LibMain(), which was the same for each.
2) The resources.

These were also Win16 DLLs.

>> What's so important about keeping those DLLs resource-only? Why can't you
>> live with a dummy export?
>
>I kind of dislike it when I have to live with lesser functionality after
>moving from BCC to OW :-)

BCC, it appears, required you to have a function in the DLL as well.
Apparently, however, it appearsthat it is satisfied with the library
startup code (code that sets up segmentation and similar arcana),
while OW wants an actual LibMain() function, however trivial it may
be.

Perhaps you should let OW worry about LibEntry(), and focus on
LibMain(). Unless you are implementing a new target that needs its own
LibEntry(), of course, in which case you probably need a LibEntry()
for use with all DLLs and a dummy LibEntry() for the (nearly)
all-resource DLLs.
--
"'If God foreknew that this would happen,
it will happen.'"

Leif Ekblad

unread,
Nov 5, 2011, 5:08:26 PM11/5/11
to
Paul S. Person:
> If I understand this correctly, every Win16 DLL created with OW
> includes a LibEntry() defined in ow\rel2\src\startup\win\libentry.asm.
> It is used for startup code. I seriously doubt that a special version
> is needed for each and every DLL.

The problem has to do with the IDE. You cannot include the same
file for more than one target. Therefore, each resource-DLL needs
its own module with its own name, that just contains a dummy
LibMain/LibEntry (don't remember which).

Also, I use 32 bit DLLs, not 16-bit.

> Searching online for LibEntry() produces a Microsoft KnowledgeBase
> article (http://support.microsoft.com/kb/69894) that applies to
> Windows 3.0 and 3.1. It also contains startup code.
>
> And both call LibMain(). Back in the 90's, when I was playing around
> with Watcom and C++, I created DLLs containing only two items:
>
> 1) A copy of my LibMain(), which was the same for each.
> 2) The resources.
>
> These were also Win16 DLLs.

RDOS doesn't need an entry-point or even any code in the code-segment of a
DLL.

> Perhaps you should let OW worry about LibEntry(), and focus on
> LibMain(). Unless you are implementing a new target that needs its own
> LibEntry(), of course, in which case you probably need a LibEntry()
> for use with all DLLs and a dummy LibEntry() for the (nearly)
> all-resource DLLs.

It would be tempting to create target "RDOS resource DLL", and build it
without any code at all. No sense in running unnecesary initialization, and
no
sense in increasing size with unnecesary run-time code.

Alternatively, make some kind of tests in the output-stage of the linker if
there
are any code-modules, and if not, build the DLL for resource-only use. That
doesn't solve the problem with implib though. All DLL-targets have a implib
makefile line which faults when the DLL doesn't export anything. Ideally,
the
make process should depend on number of source-files in the project. When
only
resource-files are present, implib should not be run and the DLL should be
built
as a resource-only DLL.

Leif Ekblad


Frank

unread,
Nov 6, 2011, 3:52:31 AM11/6/11
to
Am 05.11.2011 22:08, schrieb Leif Ekblad:

>
> The problem has to do with the IDE. You cannot include the same
> file for more than one target. Therefore, each resource-DLL needs
> its own module with its own name, that just contains a dummy
> LibMain/LibEntry (don't remember which).

This is not true. The trick is to define a separate subdir for each target:
I create exefiles for OS/2 and NT from the same source:
basedir with sourcefiles
basedir\NT
basedir\OS2

Specify the targets with relative names, i.e. NT\my.exe

CU/2
Frank



Paul S. Person

unread,
Nov 6, 2011, 12:55:47 PM11/6/11
to
On Sat, 5 Nov 2011 22:08:26 +0100, "Leif Ekblad" <le...@rdos.net>
wrote:

>Paul S. Person:
>> If I understand this correctly, every Win16 DLL created with OW
>> includes a LibEntry() defined in ow\rel2\src\startup\win\libentry.asm.
>> It is used for startup code. I seriously doubt that a special version
>> is needed for each and every DLL.
>
>The problem has to do with the IDE. You cannot include the same
>file for more than one target. Therefore, each resource-DLL needs
>its own module with its own name, that just contains a dummy
>LibMain/LibEntry (don't remember which).
>
>Also, I use 32 bit DLLs, not 16-bit.

For which no explicit LibEntry() is defined. But perhaps the startup
code is included in a different manner, or perhaps 32-bit DLLs use the
same startup code as 32-bit EXEs (at least in Windows). I would still
suggest focusing on LibMain(), since that is what users are supposed
to use to set up the DLL.

As for the IDE, Frank has proposed one solution, and it has the
advantage that changes to LibMain() will automatically propagate to
each Target using it. However, it is possible to put the object (OBJ)
file into the DLL Target, along with the resource (RC) file. You will
need another Target, for example, a LIB, to produce the object file.

The theory here is that, since it is only built for one Target (the
LIB), it is possible to include the object file in each DLL Target
without the IDE objecting. IIRC, from over a decade ago, this actually
did work then and should work now. Note that you will have to rebuild
the LIB (and so the object file) every time you change the LibMain()
function. But how often is that likely to happen?

Leif Ekblad

unread,
Nov 7, 2011, 2:04:31 PM11/7/11
to
I've submitted a solution for this to the repository. The solution only
works for target RDOS, but can be extended to other targets if this is
wanted. First, the IDE script is changed so a project with no source files
(c/c++/asm) would output a DLL stub (resstub.obj), and remove the wlib
command. The resstub is in clib/startup, and is compiled for target RDOS. It
contains a dummy LibEntry.

Even if a dummy LibEntry is needed, this is not visible to the programmer
(IDE user), so it is a clear improvement over Borland. :)

Leif Ekblad


0 new messages