Click here to Skip to main content
13,900,395 members
Click here to Skip to main content
Add your own
alternative version

Stats

22.1K views
1.8K downloads
33 bookmarked
Posted 17 Nov 2017
Licenced CPOL

Compiling MuPDF DLL to Render and Edit PDF Documents

, 23 Nov 2018
Rate this:
Please Sign up or sign in to vote.
MuPDF is an open-sourced, high performance PDF rendering and editing engine written in C. This article describes how to compile its source code to a DLL for use in other programming languages.
Note about the download:

The download contains a pre-compiled MuPDF DLL (versioned 1.14) with a simple C# demo project which utilizes functionalities in the DLL to convert PDF documents into image files.

As an alternative to downloading the above files, you can also clone my fork on GitHub to have all code files you need and get started with the MuPDF Sharp.sln file in the platform/win32 folder.

Introduction

MuPDF is an open-sourced, high performance PDF rendering and editing engine written in C. However, the compilation results of its source code do not contain a DLL for use from other languages, such as C#, Visual BASIC, etc. This article will show you the way to compile the source code to a dynamic link library.

What We Need

The source code of MuPDF can be downloaded from its official website, or from the mirror on GitHub.com. The following list contains all we need to compile the MuPDF source code.

  1. Visual Studio 2017 with the C++ desktop development payload and the latest update.
  2. Windows SDK from 7.0 up. The Windows 10 SDK might also work as well, but I have not tested it.
  3. (Optional, but recommended) Python to extract function names to a definition file for the compilation of the DLL file.
  4. About 1 GB free bytes on your hard drive for code compilation.

Compiling the Source Code

The source code of MuPDF is separated to several directories containing thousands of code files.

  1. source: the C code files
  2. include: the header files
  3. thirdparty: the code files of related open-source projects
  4. platform: projects for code compilation
  5. resources: resources (fonts, character maps, color profiles, PDF names, etc.) used by the engine
  6. scripts: some code files which help compilation

The Related Project Files

Navigate to the platform/win32 directory, you will see quite a few C project files and a solution file named mupdf.sln.

Note:

I suggest you make a copy of mupdf.sln and work on that copy later.

NEVER modify the source code unless you know what you are doing and want to participate in contributing to the MuPDF project. Have you modified the source code, you may have trouble merging the source code later, when you want to keep synchronized with the MuPDF project.

Open that solution file, copy with Visual Studio 2017, you will be prompted to upgrade the solution and the projects. Do it. Afterwards, you will see more than 10 projects loaded.

The most important projects about compiling a DLL file are listed below:

  1. libmupdf: The project to compile a static library file, libmupdf.lib, which will be used to compile the DLL file
  2. libresources: The project to handle resources, used by libmupdf
  3. libthirdparty: The related open-source projects, used by libmupdf
  4. bin2coff: The automation project which generates font resource files for the other projects.

If your goal is to compile the MuPDF DLL file only, the rest of the projects in the solution are ignorable. So you can safely unload them or remove them from the solution.

The projects must be compiled in the reverse order as they are listed above, from bin2coff to libmupdf, for the dependencies among them.

Compiling Source Projects

For the above 4 projects, we begin with the bin2coff.

Check the Configuration and Platform drop down list on the Property Pages dialog. The first one contains only Release and the later one contains only Win32. So there's no need to change them.

Optional: Find the Windows SDK version property and change it to 7.0. If you are targeting Windows 8 up and have the Windows 8.1 SDK in Visual Studio installed on your machine, you can skip this procedure. I did this because I never targeted my projects to Windows 8.

You may also change the Platform Toolset property to Visual Studio 2017 - Windows XP (v141_xp).

Click the OK button to close the dialog.

Compile the project. Things should go well.

Open the properties dialog for the next essential project file: libthirdparty.

Check the Configuration dropdown list, and you can see that there are quite a few items, such as the Platform dropdown list. For convenience, we select All Configurations from the Configuration dropdown list and All Platforms from the Platform dropdown list, so our changes will be applied to all compilation configurations and platforms.

Change the Windows SDK Version and the Platform Toolset properties when needed.

Repeat the above procedure and compile rest of the projects one by one. Finally, you will get a static library file named libmupdf.lib, in the output folder.

Note:

The SDK version you choose here may affect the compatibility of the DLL. If you have used the Windows 10 SDK here, your DLL may not run on earlier versions of Windows systems.

Creating the DLL

We are very close to what we want now.

To obtain a dynamic library file out of the static library file, we need to create another project.

Tip:

The reason why I don't modify the libmupdf project to make it generate a DLL file is that I want to keep the other projects referencing libmupdf in the solution still be compilable, and easier the process when we synchronize the source code files later when the MuPDF source code gets updated.

To create the DLL file, we will have to do three things:

  1. Create a new project to output a DLL file.
  2. Reference related static library files in that project.
  3. Define functions being exposed in the DLL file.

Setting Up the DLL Project

To create a DLL file, we create a new project in the MuPDF solution. I simply named it MuPDFLib in my solution.

Modify the project as the following list by right clicking the project file in the solution explorer and selecting the "Properties" command:

  1. Select All Configurations and All Platforms.
  2. Change the SDK version to 7.0 (or leave it along, if you are targeting Windows 8 up and installed the Windows 8.1 SDK in Visual Studio installation)
  3. Change the Configuration to Dynamic Library (.dll).
  4. Remove the CLR support (optional).
  5. Switch to the Linker/Input section in the project properties dialog, and set the Module Definition File property to "libmupdf.def" (we will generate this file later).
  6. Click OK button to close the project properties dialog.

Referencing Related Static Library Files

Right click the References in the MuPDFLib project in the solution explorer. From the popped-up context menu, select the Add Reference command, which will open a dialog. In that dialog, check the checkbox besides libmupdf, libresources and libthirdparty.

Creating the Definition File of DLL Functions

The above setting will not yet compile a workable DLL file out of the MuPDF source code, unless we create the missing libmupdf.def function definition file referenced by the project. A definition file is a list which defines what functions can be exposed out of the compiled DLL file.

Functions in MuPDF project are placed in header files in the include folder. However, since the project contains quite some scores of header files, it is not a funny task to extract those function names manually.

Fortunately, the developers of SumatraPDF (a PDF viewer application which based on MuPDF) created a Python script to generate that def file for us. You can copy the script file from the repository of SumatraPDF and place it in the scripts folder where you store the source code of MuPDF.

The script needs some modifications to reflect the latest changes of MuPDF. I uploaded my own version to my GitHub repository. If you already have Python 2.7 installed on your computer, place the script files, gen_libmupdf.def.py, util.py into the scripts folder, double click gen_libmupdf.def.py and it will generate the def file in the platform/win32 folder.

Having the def file generated, we can start compiling the DLL file.

Note:

You may encounter a few LNK2001 errors at compilation indicating that certain functions were not resolved. Simply delete those functions from the def file and proceed.

If you don't have Python and you don't want to install it, you may have to manually edit the def file with a code editor, or program your own application to generate the def file.

I suggest you use the Python script to do the dirty job for you.

Eventually, you will obtain the DLL file in the platform/win32/Release (or platform/win32/Debug, etc.) folder. Where you can find the DLL file depends on your compilation configuration.

Examining Exported Functions

So far, we have already obtained the DLL file of the MuPDF engine. You can examine whether the functions have been exported by the DLL file with the DLL Export Viewer, a small utility developed by nirsoft.net.

The exported functions in DLL Export Viewer may look like the following picture:

Shrinking the DLL File by Excluding Unwanted Fonts

Some of you may notice that the compiled DLL is a little bit large, up to about 34 megabytes. The reason why it takes so much space is that it has embedded many fonts for international character support. We can shrink its size to about 8 megabytes by excluding those font files from the compiled DLL.

To make the customized DLL, open the libmupdf project, expand the !include/fitz folder and click the config.h file. You can see a lot of comments and definition directives there. Scroll down to the comment with a text "Choose which fonts to include", and below, there are some commented lines, like the following:

/*
    Choose which fonts to include.
    By default we include the base 14 PDF fonts,
    DroidSansFallback from Android for CJK, and
    Charis SIL from SIL for epub/html.
    Enable the following defines to AVOID including
    unwanted fonts.
*/
/* To avoid all noto fonts except CJK, enable: */
/* #define TOFU */

Like it said, by defining TOFU;TOFU_CJK_EXT, you will exclude several huge noto fonts and CJK extension fonts from the DLL file, and reduce the output size from 34 megabytes to about 8 megabytes.

WARNING:

Be careful when following the instruction in the source code: Enable the following defines to AVOID including unwanted fonts.

If you modify the source code by uncommenting the lines below the above line, you will encounter source code conflicts later when you synchronize with the updated source code.

I advice you that DO NOT modify the source code; DO modify the libmupdf project properties and add definitions to the Preprocessor Definitions property as the screenshot shows. Notice the ";" before "TOFU" which separates definitions from <different options>.

Recompile the MuPDFLib project and check out the size of the DLL file. It should be much smaller.

Consuming Functions in the DLL File

I am not going to write too much in this article on how to consume the functions in the DLL. For C# programmers, you may use the Platform Invoking technology. Previously, I wrote an article P/Invoking MuPDF library to render PDF documents. You may refer to it by clicking the link above.

The download link at the top of this article has a sample project, which demonstrates how to use P/Invoke from C# to consume functions in the compiled DLL file.

Keeping Synchronized with the MuPDF Project

As the MuPDF project revolves, the source code may get changed.

Here's a short summary on keeping synchronized with the MuPDF project.

  1. If your source code is cloned from GitHub, update it; otherwise you may download the source code from the official website and overwrite the existing code files. I prefer the former approach since it downloads less bytes at update.
    1. When updating the source code, merge the GitHub source into your repository.
    2. If source code conflicts occur, use the Source.
    3. Don't forget to update the submodules, otherwise your project might not compile.
  2. Open the platform/win32 folder, compare the file modification dates of each project file with the upgraded ones.
  3. Open Visual Studio.
  4. If a certain related projects are changed, DO remove those projects from the Solution Explorer in Visual Studio; DO NOT remove the vcxproj files from the Windows Explorer. If no projects have been changed, skip to step 8 to recompile the DLL file from the source code.
  5. Add the updated vcproj files back to the solution via Solution Explorer by adding the existing project and let Visual Studio update them and generate the corresponding vcxproj files, overwriting the old ones.
  6. Repeat the steps in Compiling source projects section in this article to change the Windows SDK, code references, and other project properties.
  7. Add back project references to MuPDFLib project--the project that compiles the DLL file.
  8. Regenerate the def file for DLL exporting if necessary.
  9. Tweak the libmupdf project to shrink the output DLL file by defining font related preprocessor definitions if you want.
  10. Recompile the MuPDFLib project and get the DLL file.
  11. Check the commit history of MuPDF project and see whether header files (*.h files) in the project have been changed. When changes have occurred, find out what has been changed by comparing commission histories.
  12. Change your source code to adapt to the new MuPDF project API if it changes.

History

  1. Initial publication in November, 2017
  2. Updated source code in the GitHub fork, and fixed typos in font resource section.
  3. Updated source code in the GitHub fork, recompiled the DLL, updated article to reflect the latest source code changes on November 24th, 2018

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

wmjordan
Team Leader
China China
I am now programming applications for the Internet of Things.

You may also be interested in...

Comments and Discussions

 
QuestionmuPDF licence Pin
JimmyO26-Nov-18 1:58
memberJimmyO26-Nov-18 1:58 
AnswerRe: muPDF licence Pin
wmjordan26-Nov-18 13:36
professionalwmjordan26-Nov-18 13:36 
QuestionHi! No project "generated"? Pin
Jose Villaro2-Nov-18 6:30
memberJose Villaro2-Nov-18 6:30 
AnswerRe: Hi! No project "generated"? Pin
wmjordan24-Nov-18 18:00
professionalwmjordan24-Nov-18 18:00 
GeneralRe: Hi! No project "generated"? Pin
Jose Villaro25-Nov-18 1:18
memberJose Villaro25-Nov-18 1:18 
AnswerRe: Hi! No project "generated"? Pin
wmjordan25-Nov-18 0:56
professionalwmjordan25-Nov-18 0:56 
QuestionThank you! Make this a fork on GitHub? Pin
hmlch19-Nov-17 21:26
memberhmlch19-Nov-17 21:26 
AnswerRe: Thank you! Make this a fork on GitHub? Pin
wmjordan21-Nov-17 19:14
professionalwmjordan21-Nov-17 19:14 
AnswerRe: Thank you! Make this a fork on GitHub? Pin
wmjordan25-Nov-17 20:21
professionalwmjordan25-Nov-17 20:21 
GeneralRe: Thank you! Make this a fork on GitHub? Pin
hmlch28-Nov-17 5:06
memberhmlch28-Nov-17 5:06 
PraiseMessage Closed Pin
19-Nov-17 19:31
grouplinensrang19-Nov-17 19:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190306.1 | Last Updated 24 Nov 2018
Article Copyright 2017 by wmjordan
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid