andreas-kupries / critcl

Critcl lets you easily embed C code in Tcl. Online documentation at
http://andreas-kupries.github.io/critcl
Other
70 stars 19 forks source link

critcl 3.1.18 fails to build queue example #103

Closed apnadkarni closed 4 years ago

apnadkarni commented 4 years ago

Upgrading from 3.1.17 to 3.1.18 resulted in build failures for my tarray package. Turns out the queue example also fails to build with essentially the same error:

v3118_00000000000000000000000000000012_pic.obj : error LNK2001: unresolved external symbol _queuec2__queuec2_ClassCommand

Both in my package as well as queue, the *_ClassCommand function is not defined in any generated C file. The entire build log for queue is below:


Config:   win32-x86_64-cl
Build:    win32-x86_64-cl
Target:   win32-x86_64
Source:   queuec.tcl  (provide queuec 1) (queuec.tcl: require Tcl 8.4)

Warning  class.h(117): warning C4102: 'error': unreferenced label
Warning  queuec.tcl(53): warning C4129: '#': unrecognized character escape sequence
Warning  MyInitTclStubs(23): warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'Tcl_ObjCmdProc (__cdecl *)'

Library:  queuec.dll
 (tclStubsPtr     =>  TclStubs *tclStubsPtr;)
 (tclPlatStubsPtr =>  TclPlatStubs *tclPlatStubsPtr;)

Sat Feb 15 11:12:57 IST 2020 - D:/src/critcl-3.18/examples/queue/queuec.dll

cl
    -nologo
    -c
    -DUSE_THREAD_ALLOC=1
    -D_REENTRANT=1
    -D_THREAD_SAFE=1
    -DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1
    -DHAVE_READDIR_R=1
    -DTCL_THREADS=1
    -DUSE_TCL_STUBS
    -ID:/src/critcl-3.18/examples/queue/BUILD/tcl8.4
    -ID:/tcl/debug/x64/lib/include
    -ID:/src/critcl-3.18/examples/queue/BUILD
    -FoD:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017_pic.obj
    D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.c
    -W3
    -O2
    -MD
    -GS
    -fp:strict
    -DNDEBUG

v3118_00000000000000000000000000000017.c

D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017_pic.obj: 2559 bytes

link
    -nologo
    -release
    -opt:ref
    -opt:icf,3
    -verbose:lib
    -ltcg
    bufferoverflowU.lib
    -dll
    -out:D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.dll
    @D:/src/critcl-3.18/examples/queue/BUILD/link.fil
    /LIBPATH:D:/tcl/debug/x64/lib/tcl8.6

Searching libraries
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\bufferoverflowU.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\MSVCRT.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\OLDNAMES.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\kernel32.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\vcruntime.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\ucrt\x64\ucrt.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\bufferoverflowU.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\MSVCRT.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\OLDNAMES.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\kernel32.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\vcruntime.lib:

Finished searching libraries
   Creating library D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.lib and object D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.exp

Searching libraries
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\bufferoverflowU.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\MSVCRT.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\OLDNAMES.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\kernel32.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\vcruntime.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\ucrt\x64\ucrt.lib:

Finished searching libraries

Searching libraries
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\bufferoverflowU.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\MSVCRT.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\OLDNAMES.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\um\x64\kernel32.lib:
    Searching C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\vcruntime.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.15063.0\ucrt\x64\ucrt.lib:

Finished searching libraries
v3118_00000000000000000000000000000012_pic.obj : error LNK2001: unresolved external symbol _queuec2__queuec2_ClassCommand
D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.dll : fatal error LNK1120: 1 unresolved externals

ERROR while linking D:/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000017.dll:
child process exited abnormally
Manifest Command: mt -manifest [list $outfile].manifest -outputresource:[list $outfile]\;2
Manifest File:    <<not present>>, ignored

critcl build failed (D:/src/critcl-3.18/examples/queue/queuec.dll)
(FAILED) 
Files left in D:/src/critcl-3.18/examples/queue/BUILD
FAILURES 1
FAILED:  <<Bracket>>
FAILED   
apnadkarni commented 4 years ago

Trying to compile with gcc on Ubuntu, I get the following error log

apn@IO:/mnt/d/src/critcl-3.18/examples/queue$ tclsh build.tcl install

Config:   linux-x86_64-gcc
Build:    linux-x86_64-gcc
Target:   linux-x86_64
Source:   queuec.tcl  (provide queuec 1) (queuec.tcl: require Tcl 8.4)(FAILED) Files left in /mnt/d/src/critcl-3.18/examples/queue/BUILD
FAILURES 1
FAILED:  /mnt/d/src/critcl-3.18/examples/queue/queuec.tcl
FAILED
FAILED   Sun Feb 16 07:54:44 IST 2020 - /mnt/d/src/critcl-3.18/examples/queue/queuec.tcl  FAILED
FAILED   gcc
FAILED          -c
FAILED          -fPIC
FAILED          -DUSE_THREAD_ALLOC=1
FAILED          -D_REENTRANT=1
FAILED          -D_THREAD_SAFE=1
FAILED          -DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1
FAILED          -DHAVE_READDIR_R=1
FAILED          -DTCL_THREADS=1
FAILED          -DUSE_TCL_STUBS
FAILED          -I/mnt/d/wsl/tcl/lib/tcl8.6/critcl3.1.18/critcl_c/tcl8.4
FAILED          -I/mnt/d/wsl/tcl/include
FAILED          -I/mnt/d/src/critcl-3.18/examples/queue/BUILD
FAILED          -I/mnt/d/src/critcl-3.18/examples/queue
FAILED          -o
FAILED          /mnt/d/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000012_pic.o
FAILED          /mnt/d/src/critcl-3.18/examples/queue/BUILD/v3118_00000000000000000000000000000012.c
FAILED          -O2
FAILED          -DNDEBUG
FAILED
FAILED   In file included from class.tcl:459:0:
FAILED   class.h: In function ‘_queuec2__queuec2_ClassCommand’:
FAILED   class.h:287:7: error: stray ‘@’ in program
FAILED   class.h:287:12: error: stray ‘@’ in program
FAILED   class.h:287:8: error: ‘stem’ undeclared (first use in this function); did you mean ‘stat’?
FAILED   class.h:287:8: note: each undeclared identifier is reported only once for each function it appears in
FAILED   class.h:287:13: error: expected ‘:’ or ‘...’ before ‘_CM_0_METHODS’
FAILED
FAILED   ERROR while compiling code in /mnt/d/src/critcl-3.18/examples/queue/queuec.tcl:  FAILED   child process exited abnormally

The offending line is

        case @stem@_CM_0_METHODS: return _queuec2__queuec2_CM_0_METHODS_Cmd (class, interp, objc, objv); break;

The @stem@ is not getting replaced clearly.

andreas-kupries commented 4 years ago

Yes. This is what I saw in my environment as well. Still no idea how this was truncated out of my mail to you. See now pull request #106 for the possible fix.

andreas-kupries commented 4 years ago

Ok. Thanks for the additional files showing the difference windows vs linux. I am currently quite unsure how on Windows the class related parts are not emitted.

Actually, it seems to be a impossibility ... One of the missing things is

#line 230 "class.h"
    const char*   name;                       /* Class name, for debugging */
    long int      counter;                    /* Id generation counter */
    char          buf [sizeof("::queuec")+20]; /* Stash for the auto-generated object names. */

right. Now look at https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.h#L229-L232

This piece of code is an unconditional part of the class.h header file.

... ... ... Ok, the only idea coming to mind right now is that your Windows system has some old(er) variant of the class.h floating around where this code is not present, and critcl::class is using that. It could even be a full older version of critcl::class used instead of the new.

Oh! ... a moment ... Ok, pushed commit cbac524f6dbab31a96d3029da79310f09831804f to tell us where the packages and the template file come from.

Back to the oh! ... While adding the code above I realized that the class.h file is actually a ^Z-separated set of multiple templates, and the code in question is such a fragment. The second actually, called mgrsetup in GenerateCode, see https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L431

And that part further show us, just a tiny bit later that this code is left out (set to empty) when tcl-api is not set. So this is what the package believes, no tcl-api. But on linux it must have tcl-api set.

The default is true: https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L128

The class definition can override the defaults: https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L886-L894

The new commit a6c2556a86910dbcec9d2b8f09da226716a9972a now has code to track the flag settings.

That said. I am not convinced that it is the flag settings. The queue example does not change the api flags, at all. And I suspect that your class doesn't either. Especially as this is something which is new in critcl::class 1.1.

Now that leaves only one more thing ... That Windows treats the ^Z separated file differently than Linux. I do a plain read to slurp the file entire into memory, then split on ^Z ... Ohh ... I believe it comes to me again ... On windows the ^Z may be the default EOF character. Which means that the read takes only the first of all the templates, and the remainder does not exist, after splitting they are all empty. ... Confirmed via reading the fconfigure manpage.

That issue is now in the critcl::util::Get. (That is where the read is). For a quicker fix I updated the class package to have its own Get command now, with -eofchar {} to override platform defaults.

See commit e68b312a8b10ed6f17ef703d39a154c3708157dc.

Now that issue you see should truly be gone. Please trial.

apnadkarni commented 4 years ago

Could build both queue and my tarray extension successfully with ak-issue-103 branch.

Thanks

/Ashok

From: Andreas Kupries notifications@github.com Sent: Monday, February 17, 2020 2:30 AM To: andreas-kupries/critcl critcl@noreply.github.com Cc: apnadkarni apnmbx-wits@yahoo.com; Author author@noreply.github.com Subject: Re: [andreas-kupries/critcl] critcl 3.1.18 fails to build queue example (#103)

Ok. Thanks for the additional files showing the difference windows vs linux. I am currently quite unsure how on Windows the class related parts are not emitted.

Actually, it seems to be a impossibility ... One of the missing things is

line 230 "class.h"

   const char*   name;                       /* Class name, for debugging */
   long int      counter;                    /* Id generation counter */
   char          buf [sizeof("::queuec")+20]; /* Stash for the auto-generated object names. */

right. Now look at https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.h#L229-L232

This piece of code is an unconditional part of the class.h header file.

... ... ... Ok, the only idea coming to mind right now is that your Windows system has some old(er) variant of the class.h floating around where this code is not present, and critcl::class is using that. It could even be a full older version of critcl::class used instead of the new.

Oh! ... a moment ... Ok, pushed commit https://github.com/andreas-kupries/critcl/commit/cbac524f6dbab31a96d3029da79310f09831804f cbac524 to tell us where the packages and the template file come from.

Back to the oh! ... While adding the code above I realized that the class.h file is actually a ^Z-separated set of multiple templates, and the code in question is such a fragment. The second actually, called mgrsetup in GenerateCode, see https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L431

And that part further show us, just a tiny bit later that this code is left out (set to empty) when tcl-api is not set. So this is what the package believes, no tcl-api. But on linux it must have tcl-api set.

The default is true: https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L128

The class definition can override the defaults: https://github.com/andreas-kupries/critcl/blob/master/lib/critcl-class/class.tcl#L886-L894

The new commit https://github.com/andreas-kupries/critcl/commit/a6c2556a86910dbcec9d2b8f09da226716a9972a a6c2556 now has code to track the flag settings.

That said. I am not convinced that it is the flag settings. The queue example does not change the api flags, at all. And I suspect that your class doesn't either. Especially as this is something which is new in critcl::class 1.1.

Now that leaves only one more thing ... That Windows treats the ^Z separated file differently than Linux. I do a plain read to slurp the file entire into memory, then split on ^Z ... Ohh ... I believe it comes to me again ... On windows the ^Z may be the default EOF character. Which means that the read takes only the first of all the templates, and the remainder does not exist, after splitting they are all empty. ... Confirmed via reading the fconfigure manpage.

That issue is now in the critcl::util::Get. (That is where the read is). For a quicker fix I updated the class package to have its own Get command now, with -eofchar {} to override platform defaults.

See commit https://github.com/andreas-kupries/critcl/commit/e68b312a8b10ed6f17ef703d39a154c3708157dc e68b312.

Now that issue you see should truly be gone. Please trial.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andreas-kupries/critcl/issues/103?email_source=notifications&email_token=AATVJ6RWH6NEYZXZSY4QK73RDGSLPA5CNFSM4KVVMDNKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEL4SARA#issuecomment-586752068 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AATVJ6UDW25HZNLYEMZ5Z7DRDGSLPANCNFSM4KVVMDNA .

andreas-kupries commented 4 years ago

PR merged.