Nipid linkimiseks, ehk kuidas üle saada 'error LNK2019' vigadest

16.03.2018

Pidin hiljuti maadlema error LNK2019: unresolved external symbol tüüpi vigadega. Põhiliselt tekivad need siis, kui lingitavat lihtsalt ei leita .lib või .obj failidest. Rohkem lugemist selle kohta on siin: https://msdn.microsoft.com/en-us/library/799kze2z.aspx.

Puuduvad .lib või .obj faild saab Visual Studio-s lisada nii:

Project Properties > Configuration Properties > Linker > Input > Additional Dependencies > add

Kuidas aga õiged .lib ja .obj failid üles leida, kui need on eri kohtades laiali? Tegelikult saab selle üsna ruttu tehtud, kui kasutada õiget tööriista.

Alustada võib kiirest ülevaatest. Seda saab ruttu teada käsklusega:

dir *.lib /b /s

või

dir *.obj /b /s

/b vorming näitab failid koos teekonnaga ilma üleliigse infota.

/s otsib kõigist alamkataloogidest rekursiivselt.

Esiteks tasub meeles pidada seda, et välja võib olla jäänud mõni süsteemi teegi fail.

Näiteks sain veateate:

error LNK2001: unresolved external symbol __imp_timeGetTime

Tihtipeale on kõige kiirem lahendus kasutada üldotstarbelist interneti otsingumootorit. Veidi otsides leiame, et tuleks lisada linkimisse teek WinMM.lib. Kui meil pole aimu, kust selle faili võiks leida, siis aitab meid jälle tavaline dir käsklus:

dir WinMM.lib /s

Kuna neid faile võib olla arvutis mitmeid, siis selleks et näha ka faili kuupäeva ja suurust, jätan meelega ära /b võtme.

Kui internetiotsinguga vastust ei leia, tasub kõik oletatavad kataloogid läbi otsida. Mõnevõrra aega nõuab kõigi binaarfailide läbiotsimine, kuid kui meil pole paremat ideed, siis see võibki just meid aidata.

.lib failide läbiotsimiseks tegin käsufaili findlib.bat:

@echo off
echo otsime .lib failidest %1
for  /r %%f in (*.lib) do (
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.13.26128\bin\Hostx86\x86\dumpbin.exe" /exports "%%f" | findstr %1
if errorlevel 0 if not errorlevel 1 echo Leitud failist: %%f & echo.
)

Tulemused:

C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86>findlib.bat timeGetTime
otsime .lib failidest timeGetTime
                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\mmos.lib

                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\OneCore.Lib

                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\OneCoreUAP.Lib

                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\OneCoreUAP_downlevel.Lib

                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\OneCore_downlevel.Lib

                  _timeGetTime@0
Leitud failist: C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10586.0\um\x86\WinMM.Lib

.obj failidest otsimiseks tegin käsufaili:

@echo off
echo otsime .obj failidest %1
for  /r %%f in (*.obj) do (
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.13.26128\bin\Hostx86\x86\dumpbin.exe" /SYMBOLS "%%f" | findstr %1
if errorlevel 0 if not errorlevel 1 echo Leitud failist: %%f & echo.
)

Linkimisel on oluline jälgida, et platvorm (x86 või x64) oleks õige.

Samuti on tähtis, et Run-Time Library klapiks kogu rakenduse lõikes.

Selle kohta saab rohkem lugeda siit: https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx

Tegin väikese MSYS2 bash käsufaili, millega saan teada .lib faili kuupäeva, platvormi ning ka Run-Time Library.

$ cat /usr/bin/libinfo.sh
#! /bin/sh
ls -l $1
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.13.26128\bin\Hostx86\x86\dumpbin.exe" -headers $1 | grep machine | head -n 1
grep -aPo '.{0,20}DEFAULTLIB.{0,12}' $1 | head -n 3

Viiteid: https://msdn.microsoft.com/en-us/library/799kze2z.aspx