• Welcome to Dark Bit Factory & Gravity.
 

Unresolved externals with NODEFAULTLIB flag

Started by Raizor, November 22, 2011

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Raizor

Hi guys,

As you're probably aware, I use IQ's 64k C++ framework as a base. This uses the NODEFAULTLIB linker flag to keep the size down.

There are ASM replacements for a lot of standard functions, all prefixed with "msys_" i.e. msys_memset etc.  My issue is that VC is being smart and identifying certain blocks of code as doing something specific (like memset) and replacing the code block with a call to memset during compilation.

This results in things such as:

Error   3   error LNK2019: unresolved external symbol _memset referenced in function "int __fastcall build_huffman(struct huffman *,int *)" (?build_huffman@@YIHPAUhuffman@@PAH@Z)   stb_image.obj   phenomenaEclipse

Is there an easy way to avoid this happening without mashing up the code so the compiler cannot recognise it that will not impact badly on overall performance?

I'm adding some image handling stuff using stbi (stb Image), which is the source of these headaches.

Any advice gratefully appreciated :)

EDIT: I found a similar post where Hellfire suggest adding the /QIfist compiler flag. This flag is already present and doesn't resolve the issue.
raizor

Challenge Trophies Won:

Raizor

I've found some info that helped: http://stackoverflow.com/questions/2938966/how-to-use-vc-intrinsic-functions-w-o-run-time-library.

Adding this:

#pragma function(memset)
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
    char *p = reinterpret_cast<char *>(pTarget);
    while (cbTarget-- > 0) {
        *p++ = static_cast<char>(value);
    }
    return pTarget;
}


has got round the problem. Not an ideal solution, but it will do for now :)
raizor

Challenge Trophies Won:

LittleWhite

Well you redefined the function, in a non optimised way of doing it (I guess the libc is better than yours).
But, it will do the job and the compiler will stop complain ...

The point is that, the libc(++) is certainly missing from your project définition. I guess that adding it will make your executable so much bigger (or maybe not, if only the symbol (I mean, the function address) is registered in your exe). You should try, or define your own function loader (with getProcAdress() stuff? )
The demoscene will never die, never!

Jim

There's no point getting rid of the C runtime (CRT) libraries and then using another big binary library like stb image if the aim is to achieve small exes.  Nearly all these external libs will also have a dependency on CRT.

Windows can load bmp files with a few lines of code (LoadImage), or with a bit more ingenuity you can use Direct3DX or GDI+ to do the loading for other formats.

<edit>
FYI, the compiler will generate memset for things like this

void apple(void)
{
   int banana[200]={0};
}

and many other scenarios where a stack-based variable must be cleared to 0.

If you want to avoid that, make banana a global.

int banana[200];

But watch if you're not using CRT, as it is that guy that guarantees that the BSS segment - uninitialised global variables - is cleared to 0 at exe startup.  Not initialising CRT e.g. by bypassing WinMain and using WinMainCRTStartup will also break any lib that depends on that behaviour.

Jim
Challenge Trophies Won:

Raizor

Thanks LittleWhite and Jim.

Jim, I'm not overly worried about size at the moment, just wanted to keep things as lean as possible for a 64k intro. Some useful information you provided there, thanks.
raizor

Challenge Trophies Won:

hellfire

Quote from: Raizor on November 22, 2011
Adding this:

#pragma function(memset)
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
    char *p = reinterpret_cast<char *>(pTarget);
    while (cbTarget-- > 0) {
        *p++ = static_cast<char>(value);
    }
    return pTarget;
}


has got round the problem. Not an ideal solution, but it will do for now :)
I guess this is about size, so you can link against the runtime dlls - all functions are already in there. Just add msvcrt.lib to your libs.
This requires that the vcredist-package is installed, though - which one exactly depends on your vs version (2005, 2008, 2010).
Or you link the msvcrt.lib which comes with vs6 (from 1998), its' runtime dlls are already shipped with windows since 2000.
Challenge Trophies Won:

Raizor

Quote from: hellfire on November 23, 2011
Or you link the msvcrt.lib which comes with vs6 (from 1998), its' runtime dlls are already shipped with windows since 2000.

That sounds like a good plan Hellfire, thanks.
raizor

Challenge Trophies Won:

Rbz

Quote from: hellfire on November 23, 2011
Or you link the msvcrt.lib which comes with vs6 (from 1998), its' runtime dlls are already shipped with windows since 2000.

@Raizor: This is how I do it all the time :), and if I remember correctly this lib version is included with "tinyptc_ext" on this forum.
Challenge Trophies Won:

Raizor

Cool rbz! Does it bump the exe size much?
raizor

Challenge Trophies Won:

Rbz

Challenge Trophies Won:

Jim

It only links in the functions you use (and any internal ones it needs) and the code is pretty optimal - the source code for the CRT is included with visual studio so you can check it out and see.
e.g.
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src

Jim
Challenge Trophies Won:

Raizor

raizor

Challenge Trophies Won:

Raizor

Does anyone have a copy of msvcrt.lib from VC6 handy? I checked the Tiny_PTC archive RBZ, but it doesn't seem to be included.

Thanks
raizor

Challenge Trophies Won:

Rbz

Sorry, I thought it was there.

I've attached it here for you  8)


Challenge Trophies Won:

Raizor

raizor

Challenge Trophies Won: