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:
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
#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;
}
.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
pdf_is_complete_lib = true
, and thus, linking also single .obj
s, and v8
and xfa
supportclang-cl
instead of MSBuild
(the one provided by Visual Studio's Native Development pack)clang-cl
(currently, version 16.0.0
)Any help is appreciated. Thanks in advance.
After days of failures and (vain) research, I finally found the solution, posted here for future reference.
Depending on flags set in args.gn
, Pdfium will need at least the following to successfully build and start the Getting Started example:
is_component_build = false
and, thus pdf_is_complete_lib = true
, .obj
files built from libc++
and winmm.lib
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.
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
:
ninja -C <out_dir>
; this also builds libc++;pdfium.lib
via ninja -C <out_dir> pdfium
(will only execute a link step)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++>
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
:
ninja -C <out_dir> pdfium
; will compile all the necessary .dll
s along with .pdb
and .lib
files and put them in out_dir
pdfium.lib
in your project and copy emitted .dll
s 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.robocopy
because is more efficient than xcopy
. Also, check on exit code is needed because of the value returned by robocopy
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.