Pelles C has some inconsistencies in its CRT libraries:
all libraries except pocrt64.lib depend on kernel32.lib (any reason for this difference, BTW?), but crt.lib is missing /Defaultlib:kernel32.lib
This leads to "Unresolved external symbol" when using polink from command-line and linking to crt.lib, unless kernel32.lib is linked explicitly.
Quote from: Romashka on October 11, 2014, 07:24:38 PM
This leads to "Unresolved external symbol" when using polink from command-line and linking to crt.lib, unless kernel32.lib is linked explicitly.
Not exactly. Try this quick example below :
Setting 32-bit environment for Pelles C...
D:\PellesC>pocc hello.c
D:\PellesC>polink /SUBSYSTEM:CONSOLE hello.obj
D:\PellesC>type hello.c
#include <stdio.h>
int main(void)
{
printf("Hello world!");
return 0;
}
D:\PellesC>hello.exe
Hello world!
D:\PellesC>
The linking depends on crt.lib :
Setting 32-bit environment for Pelles C...
D:\PellesC>ren Lib\crt.lib crt0.lib
D:\PellesC>polink /SUBSYSTEM:CONSOLE hello.obj
POLINK: fatal error: File not found: 'crt.lib'.
Sorry, I didn't understand your point.
Here's what I was referring to:
pocc -c -Ze -Ox -D_UNICODE -DUNICODE -DBUILD_DLL -I"C:\Compilers\PellesC\Include" -I"C:\Compilers\PellesC\Include\Win" libtest.c
polink -machine:x86 -subsystem:console -dll -release -verbose -libpath:"C:\Compilers\PellesC\Lib" -libpath:"C:\Compilers\PellesC\Lib\Win" libtest.obj -out:"D:\projects\BB\tests\output\pellesc-x86\test.dll"
Loading libtest.obj
Processed /Defaultlib:crt.lib
Searching C:\Compilers\PellesC\Lib\crt.lib
Found _time
crt.lib(time.obj)
. . .
Found _signal
crt.lib(signal.obj)
Searching C:\Compilers\PellesC\Lib\crt.lib
Loading *** generated DllMain() ***
Searching C:\Compilers\PellesC\Lib\crt.lib
POLINK: error: Unresolved external symbol '__imp__GetSystemTimeAsFileTime@4'.
. . .
POLINK: error: Unresolved external symbol '__imp__SetConsoleCtrlHandler@8'.
POLINK: fatal error: 38 unresolved external(s).
pocc -c -Tamd64-coff -Ze -Ox -D_UNICODE -DUNICODE -DBUILD_DLL -I"C:\Compilers\PellesC\Include" -I"C:\Compilers\PellesC\Include\Win" libtest.c
polink -machine:amd64 -subsystem:console -dll -release -verbose -libpath:"C:\Compilers\PellesC\Lib" -libpath:"C:\Compilers\PellesC\Lib\Win64" libtest.obj -out:"D:\projects\BB\tests\output\pellesc-x86-64\test.dll"
Loading libtest.obj
Processed /Defaultlib:crt64.lib
Processed /Defaultlib:kernel32.lib
Searching C:\Compilers\PellesC\Lib\crt64.lib
Found time
crt64.lib(time.obj)
Found srand
crt64.lib(srand.obj)
Found rand
crt64.lib(rand.obj)
Searching C:\Compilers\PellesC\Lib\Win64\kernel32.lib
Found __imp_GetSystemTimeAsFileTime
kernel32.lib(KERNEL32.dll)
Found __IMPORT_DESCRIPTOR_KERNEL32
kernel32.lib(KERNEL32.dll)
Found __NULL_IMPORT_DESCRIPTOR
kernel32.lib(KERNEL32.dll)
Found KERNEL32_NULL_THUNK_DATA
kernel32.lib(KERNEL32.dll)
Searching C:\Compilers\PellesC\Lib\crt64.lib
Searching C:\Compilers\PellesC\Lib\Win64\kernel32.lib
Searching C:\Compilers\PellesC\Lib\crt64.lib
Found _DllMainCRTStartup
crt64.lib(_dllcrt0.obj)
. . .
Found signal
crt64.lib(signal.obj)
Searching C:\Compilers\PellesC\Lib\Win64\kernel32.lib
Found __imp_VirtualFree
kernel32.lib(KERNEL32.dll)
. . .
Found __imp_SetConsoleCtrlHandler
kernel32.lib(KERNEL32.dll)
Searching C:\Compilers\PellesC\Lib\crt64.lib
Searching C:\Compilers\PellesC\Lib\Win64\kernel32.lib
Loading *** generated DllMain() ***
Creating object: D:\projects\BB\tests\output\pellesc-x86-64\test.exp
Loading D:\projects\BB\tests\output\pellesc-x86-64\test.exp
Creating library: D:\projects\BB\tests\output\pellesc-x86-64\test.lib
Discarded GetSystemTimeAsFileTime from kernel32.lib(KERNEL32.dll)
. . .
Discarded SetConsoleCtrlHandler from kernel32.lib(KERNEL32.dll)
Discarded .bss from crt64.lib(_ioinit.obj)
Discarded size: 228 bytes
Creating executable: D:\projects\BB\tests\output\pellesc-x86-64\test.dll
Notice there is no "Processed /Defaultlib:kernel32.lib" line when linking with crt.lib, only with crt64.lib there is.
A workaround is to call polink with -defaultlib:kernel32 explicitly but this is inconsistent and proper fix is to add /Defaultlib:kernel32.lib to crt.lib
Maybe crt:_dllcrt0.obj is good place for it ?
VirtualFree needs it there.
It works for me on XP SP3 32Bit
>povars32
Setting 32-bit environment for Pelles C...
>polink -verbose test1.obj
Loading test1.obj
Processed /Defaultlib:crtmt.lib
Searching C:\Dev\PellesC\Lib\crtmt.lib
Found _printf
crtmt.lib(printf.obj)
Found _thrd_sleep
crtmt.lib(thrd_sleep.obj)
Found _thrd_exit
crtmt.lib(thrd_exit.obj)
Found _malloc
crtmt.lib(malloc.obj)
Found _thrd_create
crtmt.lib(thrd_create.obj)
Found _perror
crtmt.lib(perror.obj)
...
Found ___bheap_threshold
crtmt.lib(_crt0dat.obj)
Found __except_handler3
crtmt.lib(seh2.obj)
Found __except_list
crtmt.lib(seh1.obj)
Processed /Defaultlib:kernel32.lib
Found __bheap_alloc
crtmt.lib(_bigheap.obj)
Found ___errno
crtmt.lib(_maperr.obj)
Found ___thrd_new
crtmt.lib(_thrdnew.obj)
Found ___mt_fputs
crtmt.lib(fputs.obj)
...
Found ___inf
crtmt.lib(_values.obj)
Searching C:\Dev\PellesC\Lib\Win\kernel32.lib
Found __imp__InitializeCriticalSection@4
kernel32.lib(KERNEL32.dll)
Found __imp__DeleteCriticalSection@4
kernel32.lib(KERNEL32.dll)
Found __imp__EnterCriticalSection@4
kernel32.lib(KERNEL32.dll)
...
Found KERNEL32_NULL_THUNK_DATA
kernel32.lib(KERNEL32.dll)
Searching C:\Dev\PellesC\Lib\crtmt.lib
Searching C:\Dev\PellesC\Lib\Win\kernel32.lib
Discarded _localeconv from crtmt.lib(localeconv.obj)
Discarded _InitializeCriticalSection@4 from kernel32.lib(KERNEL32.dll)
...
Discarded _DeleteFileA@4 from kernel32.lib(KERNEL32.dll)
Discarded .data from crtmt.lib(memcpy.obj)
Discarded .data from crtmt.lib(memset.obj)
Discarded .bss from crtmt.lib(_ioinit.obj)
Discarded size: 312 bytes
Creating executable: test1.exe
And works also with crt.lib
>polink -verbose hello.obj
Loading hello.obj
Processed /Defaultlib:crt.lib
Searching C:\Dev\PellesC\Lib\crt.lib
Found _printf
crt.lib(printf.obj)
Found _mainCRTStartup
crt.lib(_crt0.obj)
Found _fwrite
crt.lib(fwrite.obj)
Found ___stdout
crt.lib(_files.obj)
Found ___buf_stream
crt.lib(_stbuf.obj)
Found ___printf
crt.lib(_printf.obj)
Found __except_handler3
crt.lib(seh2.obj)
Found __except_list
crt.lib(seh1.obj)
Processed /Defaultlib:kernel32.lib
Found __set_crt_heap_size
crt.lib(_heapsz.obj)
Found ___crtheapsize
crt.lib(_crt0dat.obj)
Found ___bheapinit
crt.lib(_bigheap.obj)
Found ___features
crt.lib(features.obj)
.....
Maybe the problem is only for 64bit version?
frankie,
the problem is with crt.lib when using it with dll.
crtmt.lib works as it use seh1.obj, but crt.lib don't.
Thanks Timo.
Infact with command:
polink -dll -verbose hello.obj
I got the linker errors.
When compiling an executable the entry point module uses seh1 that has a reference to kernel32.dll, when compiling a dll there is no module from crt.lib that references kernel32.dll.
Now the point is that you cannot define e library reference general for a static library, but only for modules inside it. If the module you use from library have no reference to the library you want (kernel32) this should be not a bug, but the normal behaviour. In short I expect that the correct linking is to always reference on command line the libraries you want to link and not expect that some other modules will load it (in the past with the so called single linker pass sometimes you had to put more times the library on command line for references inside other references).
The entry point in crt64 is different and need to call kernel so incidentally the problem is solved ?