After successfully building Pdfium as per Google's docs, I created a new C++ console app with VS2022 and tried to embed .lib resulting from Pdfium build but, it results in several unresolved symbols which, I guess, should be included in standard C++. As an example, here is two of the unresolved symbols:
fx_string.obj: error LNK2001: unresolved external symbol "void __cdecl std::Cr::__libcpp_verbose_abort(char const *,...)"
fpdf_parser_utility.obj : error LNK2001: unresolved external symbol "public: class std::Cr::basic_ostream<char,struct std::Cr::char_traits<char> > & __cdecl std::Cr::basic_ostream<char,struct std::Cr::char_traits<char> >::write(char const *,__int64)"
Steps taken:
build Pdfium following docs steps using below args.gn:
use_goma = false
is_debug = false
pdf_use_skia = false
pdf_enable_xfa = false
pdf_enable_v8 = false
pdf_is_standalone = false
is_component_build = false
pdf_is_complete_lib = true
Created a simple C++ console app with following content (copied from Getting started):
#include <iostream>
#include "../PDFium/public/fpdfview.h"
int main()
{
std::cout << "PDFium test!\n";
FPDF_LIBRARY_CONFIG config{};
config.version = 2;
config.m_pUserFontPaths = NULL;
config.m_pIsolate = NULL;
config.m_v8EmbedderSlot = 0;
FPDF_InitLibraryWithConfig(&config);
FPDF_DestroyLibrary();
return 0;
}
Copied Pdfium's public folder and resulting .lib file into a separate folder of the project, added necessary fields for linker and set C++ language spec to stdc++20; below, the corresponding tags in .vcxproj
<!-- other tags -->
<ClCompile>
<!-- other tags -->
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<!-- other tags -->
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)PDFium\x64</AdditionalLibraryDirectories>
<AdditionalDependencies>PDFium.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
(Unsuccessful) Tests did
Tried to compile PDFium with and without pdf_is_complete_lib = true, and thus, linking also single .objs, and v8 and xfa support
Tried to compile with Microsoft's clang-cl instead of MSBuild (the one provided by Visual Studio's Native Development pack)
Tried to compile with depot tools's clang-cl (currently, version 16.0.0)
Tried several options found here and there on SO and on internet
Any help is appreciated. Thanks in advance.
After days of failures and (vain) research, I finally found the solution, posted here for future reference.
TL;DR;
Depending on flags set in args.gn, Pdfium will need at least the following to successfully build and start the Getting Started example:
if is_component_build = false and, thus pdf_is_complete_lib = true, .obj files built from libc++ and winmm.lib
if is_component_build = true and, thus pdf_is_complete_lib = false, all .dll resulting from compilation, i.e.:
absl.dll
icuuc.dll
libc++.dll
partition_alloc.dll
pdfium.dll
zlib.dll
Read also the important note below which tries to explain the difference between the two flags.
Long description
As per docs, once .ninja files has been generated as result of gn args <out_dir>, it can be seen which .obj, .lib and .dll files are needed to build pdfium_unitests.exe. Comparing those with the ones used to generate pdfium.lib (or pdfium.dll depending on flags, see below), it can be spotted the required libraries.
With is_component_build = false and pdf_is_complete_lib = true:
start default compilation with ninja -C <out_dir>; this also builds libc++;
generate pdfium.lib via ninja -C <out_dir> pdfium (will only execute a link step)
(optionally) generate a libc++.lib using depot tool's lld-link which will contain all .obj files from compilation of libc++:
"C:\path\to\pdfium\third_party\llvm-build\Release+Asserts\bin\lld-link.exe" /lib /OUT:libc++.lib /nologo /WX /ignore:4221 <space-separated list of .obj files in C:\out_dir\obj\buildtools\third_party\libc++\libc++>
link pdfium.lib, all libc++'s .obj files in C:\out_dir\obj\buildtools\third_party\libc++\libc++ (or, libc++.lib from previous step), winmm.lib in your project; e.g.:
<Link>
<!-- other options -->
<AdditionalDependencies>pdfium.lib;libc++.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
With is_component_build = true and pdf_is_complete_lib = false:
start compilation with ninja -C <out_dir> pdfium; will compile all the necessary .dlls along with .pdb and .lib files and put them in out_dir
link pdfium.lib in your project and copy emitted .dlls in output directory; assuming emitted files are in C:\pdfium\result, project's .vcxproj will look like this:
<!-- ... -->
<Link>
<AdditionalLibraryDirectories>C:\pdfium\result</AdditionalLibraryDirectories>
<AdditionalDependencies>pdfium.dll.lib</AdditionalDependencies>
</Link>
<!-- ... -->
<PostBuildEvent>
<Command>cmd /c "robocopy C:\pdfium\result $(OutDir) /xf *.lib & if %errorlevel% geq 8 exit 0 else exit %errorlevel%"</Command>
</PostBuildEvent>
<!-- ... -->
Note: the files you'll need are listed in tl;dr; section.
Note 2: used robocopy because is more efficient than xcopy. Also, check on exit code is needed because of the value returned by robocopy
Important note
pdf_is_complete_lib and is_component_build will set, respectively, /MT and /MD flags during compilation.
Although might not seem a problem, MSBuild will complain if the two types are mixed and thus, you'll need either to recompile Pdfium or change the way your code is generated via Project Properties > C/C++ > Code Generation > Runtime Library.
For more information see Google docs, Microsoft docs on flags and linker warning and, eventually, this SO question which can help in choose the code generation that most suits your needs.
Related
I have a C++ library which is compiled as dynamic and static library. Recently I add resource version file to source. The dynamic library compilation works fine, but static library compilation started failing for 64 bit target with following error:
LINK : warning LNK4068: /MACHINE not specified; defaulting to X86
x64\Release\dllmain.obj : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'
Following is my compilation script:
#ECHO OFF
call "%VS140COMNTOOLS%"\\vsvars32.bat
SET SourceDir=D:\Projects\MySampleLib
SET TargetDir=D:\Projects\Packages
ECHO 32 bit MySampleLib .LIB compilation VS2010
msbuild.exe %SourceDir%\MySampleLib\MySampleLib.vcxproj /t:Clean;Rebuild /p:Configuration=Release;Platform=Win32;ConfigurationType=StaticLibrary;PlatformToolset=v100
ECHO 64 bit MySampleLib .LIB compilation VS2010
msbuild.exe %SourceDir%\MySampleLib\MySampleLib.vcxproj /t:Clean;Rebuild /p:Configuration=Release;Platform=x64;ConfigurationType=StaticLibrary;PlatformToolset=Windows7.1SDK
The error occurs when Lib.exe command tries to link the MySampleLib.res
Note: The error only appeared after I added the resource file. I don't want to add the resource file to static libs.
I finally fixed the issue by modifying the following .vcxproj entry
<ItemGroup>
<ResourceCompile Include="MySampleLib.rc" />
</ItemGroup>
to
<ItemGroup Condition="'$(ConfigurationType)'!='StaticLibrary'">
<ResourceCompile Include="MySampleLib.rc" />
</ItemGroup>
This prevented linking of resource file in static compilation.
During the compilation process of my application (Debug mode), I am getting the following error, related to the CRT library:
16>libcpmt.lib(stdhndlr.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in poStat.obj
According to the Microsoft MSDN topic, I need to set the runtime library to /MTd in order to append the correct library compiled with debug mode. I also have to define a _DEBUG flag - and thats exactly what I have done.
Even though I have did everything it requires to use the CRT with debug mode, its still trying to use one without the debug mode (libcpmt.lib instead of the libcpmtd.lib).
How can I fix this?
Update
When I go to the C:\Program Files\Microsoft Visual Studio 11.0\VC\lib and change the name of libcpmtd.lib to the libcpmt.lib (had to temporary remove the existing libcpmt.lib) it builds successfully in a debug mode.
As Hans Passant already pointed out, the reason you have this is because some of the .lib or .obj files you are linking were compiled with Release settings, and some with Debug. The real question for you now is how to find which libraries or object files need to be fixed. Here is one way to do this
link /dump /all "Path_To_Lib_or_Obj" | findstr /L "\/DEFAULTLIB"
This will print out all default libraries, including CRT. This command has to be executed for each .lib and .obj that appears on your linker build command. For Debug you should see something like:
/DEFAULTLIB:msvcprtd
/DEFAULTLIB:MSVCRTD
/DEFAULTLIB:OLDNAMES
...
and for Release:
/DEFAULTLIB:msvcprt
/DEFAULTLIB:MSVCRT
/DEFAULTLIB:OLDNAMES
...
We are building Tcl ourselves in order to distribute our own compiled binaries with an application. The application itself links against the Tcl library and uses the API internally.
To build Tcl we got the sources from http://sourceforge.net/projects/tcl/, we then navigate into the /win directory, change the buildall.vc.bat file to point to our MSVC installation and then we run that bat file. Building works as expected and outputs are produced in /win/Release_VC11. More specifically, tcl85.lib and tcl85.dll are produced.
When we link against this .lib from within our Qt C++ application, we get a bunch of linker errors. For example:
commands.obj : error LNK2019: unresolved external symbol __imp_Tcl_AppendResult
referenced in function "int __cdecl CallQMessageBox(void *,struct Tcl_Interp *,
int,char * * const)" (?CallQMessageBox##YAHPEAXPEAUTcl_Interp##HQEAPEAD#Z)
However, when we link against the tcl85.lib file provided as part of the ActiveState Tcl distribution, the linker does not have any issues and builds fine. We verified that its the exact same version of Tcl in both cases.
We are using MSVC 2012 (Express Edition) to build Tcl, and the build command remains unmodified in buildall.vc.bat:
::set OPTS=threads
if not %SYMBOLS%.==. set OPTS=symbols
nmake -nologo -f makefile.vc release OPTS=%OPTS% %1
We've been trying all sorts of things with not luck.
Ok, figured it out:
I was building Tcl as a 32bit binary instead of a 64bit one.
Replacing
call "D:\tools\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat"
with
call "D:\tools\Microsoft Visual Studio 11.0\VC\bin\x86_amd64\vcvarsx86_amd64.bat"
and adding AMD64 to the nmake command like this
nmake -nologo -f makefile.vc release OPTS=%OPTS% %1 MACHINE=AMD64
in buildall.vc.bat seems to have fixed it.
I have a project in visual studio 2012 which uses opencv dynamic libraries. It compiled, linked and worked well.
I want to change the project so it uses static libraries instead of dynamic libraries.
I changed the library directories in project VC++ directory from
C:\thirdparty\opencv\build\x86\vc11\lib
to:
C:\thirdparty\opencv\build\x86\vc11\staticlib
but when I want to build the project, I am getting a lot of linker error such as:
Error 110 error LNK2001: unresolved external symbol _TIFFWriteScanline myproject\opencv_highgui245.lib(grfmt_tiff.obj)
and more importantly a lot of error such as this:
Error 1 error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in myproject.obj myproject\opencv_core245.lib(system.obj)
What other changes should I do to convert a project which uses dynamic libraries to use static libraries?
Edit 1
After change /md to /mt and adding some new libraries to the list of input libraries:
opencv_calib3d245.lib
opencv_contrib245.lib
opencv_core245.lib
opencv_features2d245.lib
opencv_flann245.lib
libtiff.lib
libpng.lib
libjpeg.lib
libjasper.lib
IlmImf.lib
zlib.lib
opencv_gpu245.lib
opencv_haartraining_engine.lib
opencv_highgui245.lib
opencv_imgproc245.lib
opencv_legacy245.lib
opencv_ml245.lib
opencv_nonfree245.lib
opencv_objdetect245.lib
opencv_photo245.lib
opencv_stitching245.lib
opencv_ts245.lib
opencv_video245.lib
opencv_videostab245.lib
I am getting some new errors:
Error 9 error LNK2001: unresolved external symbol _AVIFileCreateStreamA#12 myproject\opencv_highgui245.lib(cap_vfw.obj)
Error 8 error LNK2001: unresolved external symbol _AVIFileGetStream#16 myproject\opencv_highgui245.lib(cap_vfw.obj)
Error 5 error LNK2001: unresolved external symbol _AVIFileInit#0 myproject\opencv_highgui245.lib(cap_vfw.obj)
Error 7 error LNK2001: unresolved external symbol _AVIFileOpenA#16 myproject\opencv_highgui245.lib(cap_vfw.obj)
Apparently some library is missing, but which one?
Edit 2
need to add more library to list. Full list of library is as follow:
opencv_calib3d245.lib
opencv_contrib245.lib
opencv_core245.lib
opencv_features2d245.lib
opencv_flann245.lib
libtiff.lib
libpng.lib
libjpeg.lib
libjasper.lib
IlmImf.lib
zlib.lib
opencv_gpu245.lib
opencv_haartraining_engine.lib
opencv_highgui245.lib
opencv_imgproc245.lib
opencv_legacy245.lib
opencv_ml245.lib
opencv_nonfree245.lib
opencv_objdetect245.lib
opencv_photo245.lib
opencv_stitching245.lib
opencv_ts245.lib
opencv_video245.lib
opencv_videostab245.lib
Vfw32.Lib
comctl32.lib
This solved the problem.
I am able to get the static libraries working in VS 2013 by changing the project's Runtime Library to /MTd
and then including these Linker >> Input >> Additional Dependencies:
opencv_core248d.lib
opencv_imgproc248d.lib
opencv_highgui248d.lib
opencv_ml248d.lib
opencv_video248d.lib
opencv_features2d248d.lib
opencv_calib3d248d.lib
opencv_objdetect248d.lib
opencv_contrib248d.lib
opencv_legacy248d.lib
opencv_flann248d.lib
libpngd.lib
libtiffd.lib
zlibd.lib
IlmImfd.lib
libjasperd.lib
libjpegd.lib
comctl32.lib
gdi32.lib
vfw32.lib
If you are building using CMake then it is very simple because it is one of the OpenCV CMake options; just set BUILD_WITH_STATIC_CRT to off. Eg. on the CMake command-line
-DBUILD_WITH_STATIC_CRT=OFF
For Visual Studio 2012 with OpenCV 3.0.0, these problems still apply, and the solutions in this thread are relevant. Here's my setup to get it to work:
Windows' System Environment Variables
Set in Windows' System Environment Variables: OPENCV_DIR = D:\OpenCV\build\x64\v11 (replace D:\OpenCV\ with whatever your path to opencv is. Also, x64 for 64-bit machines, x86 for 32-bit machines).
Use staticlib for AdditionalLibraryDirectories
Set the Additional Library Directories (View > Property Pages > Configuration Properties > Linker > General > Additional Library Directories) to: $(OPENCV_DIR)\staticlib;%(AdditionalLibraryDirectories)
Runtime Library
Change the Code Generation > Runtime Library to Multi-threaded Debug (/MTd) per uosɐſ's answer, otherwise you'll get this kind of error:
Error 1 error LNK2038: mismatch detected for 'RuntimeLibrary': value
'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in Source.obj
C:\Users\...\documents\visual studio 2012\Projects\OpenCVTest2\OpenCVTest2\opencv_core300d.lib(alloc.obj) OpenCVTest2
Finally, the Additional Dependencies list
My Additional Dependencies must include all the library names in the staticlib directory. Mind the version numbers; since I'm using OpenCV 3.0.0, the filenames ends with *300d.lib. I believe the comctl32.lib and vfw32.lib are not in the staticlib, but I added them just in case (View > Property Pages > Configuration Properties > Linker > Input > Additional Dependencies):
opencv_calib3d300d.lib
opencv_core300d.lib
opencv_features2d300d.lib
opencv_flann300d.lib
opencv_hal300d.lib
opencv_highgui300d.lib
opencv_imgcodecs300d.lib
opencv_imgproc300d.lib
opencv_ml300d.lib
opencv_objdetect300d.lib
opencv_photo300d.lib
opencv_shape300d.lib
opencv_stitching300d.lib
opencv_superres300d.lib
opencv_ts300d.lib
opencv_video300d.lib
opencv_videostab300d.lib
libtiffd.lib
libpngd.lib
libjpegd.lib
libjasperd.lib
IlmImfd.lib
libwebpd.lib
ippicvmt.lib
zlibd.lib
comctl32.lib
vfw32.lib
x86 vs x64
I also ran into this issue that VS2012 claims the target machine does not match the module machine type like this guy. The solution is given here.
Dude, let me tell you... been there done that..
I tried the static lib thing (a couple of times..) It's evil.
If you are using Visual Studio, you better degrade back to
VS2010. VS2012 and up wasn't used to build these libraries. And that
is true at least for version 244. You might just be able to link but
you will get crashes with very basic functions.. So spare yourself.
If you use GCC you might just find that the .a libs are evil
indeed.. They were cross-compiled in windows for LINUX. Trying to
link with cygwin, MinGw won't do the job.
After trying for 2 days I decided that it was enough time wasted, and retreated back to the DLL's, which work ok if you use VS2010.
Let it not be a turnoff.. If you did manage to link, please share with us all how :)
I have build an application which depends on OpenCV 2.4.9 with static linking.
1)
I have just added linker additional dependencies:
opencv_core249d.lib
opencv_imgproc249d.lib
opencv_highgui249d.lib
opencv_ml249d.lib
opencv_video249d.lib
opencv_features2d249d.lib
opencv_calib3d249d.lib
opencv_objdetect249d.lib
opencv_contrib249d.lib
opencv_legacy249d.lib
opencv_flann249d.lib
libpngd.lib
libtiffd.lib
zlibd.lib
IlmImfd.lib
libjasperd.lib
libjpegd.lib
comctl32.lib
gdi32.lib
vfw32.lib
2)
Linker => General => Additional Library Directories => changed $(OPENCV_DIR)\x86\vc12\lib to $(OPENCV_DIR)\x86\vc12\staticlib where OPENCV_DIR is environment variable set to:
C:\OpenCV 2.4.9\opencv\build
3)
and changed C/C++ => Code Generation => Multi-threaded debug DLL (MD) to Multi-threaded debug (MTd)
and enjoyed the successful build.
the same thing works for release mode (of course link against non-debug libs)
So working on getting my eclipse IDE going so I can develop my arduino uno in eclipse.
My C++ is weak so this is probably a nube error on my part.
I have a blink program that looks for an arduino library I compiled from the arduino IDE's library.
My code points to the header file and my code find it fine; meaning I can click on:
#include <arduino.h>
and go view the header
this: "C:/programs/arduino-1.0/hardware/arduino/cores/328p_lib/libuno_library.a"
is a valid path... but I get the following error:
>****** Build of configuration Debug for project project1 ****
>make all
>Building target: project1.elf
>Invoking: AVR C++ Linker
>avr-g++ -Wl,-Map,project1.map,--cref -L"C:\programs\arduino->1.0\hardware\arduino\cores\328p_lib" -mmcu=atmega328p -o "project1.elf" ./code/code1.o >-l"C:/programs/arduino-1.0/hardware/arduino/cores/328p_lib/libuno_library.a"
>c:/programs/winavr/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: cannot find ->lC:/programs/arduino-1.0/hardware/arduino/cores/328p_lib/libuno_library.a
>make: *** [project1.elf] Error 1
>**** Build Finished ******
Well after wasting 2 days or so of fun time I finally found the problem.
http://sourceforge.net/projects/avr-eclipse/forums/forum/664382/topic/4640554
When adding the static library to the linker you have to remove the lib prefix and the .a suffix. not sure what that is about.
Right click on the project>Click on C/C++ BUild> Settings > GCC C++ Linker> Libraries
Click the first icon Add> Add the library name ( without the .a suffix, the suffix will be added automatically)
This will ensure that the library is added to the project.
If the library is part of another project >Go to GCC C Compiler> directories >Add the directory
This will ensure that the library is there for getting the compilation done.