-
PDFium 라이브러리 삽질기 - 3Linux 2019. 12. 11. 17:15
PDFium 라이브러리 삽질기 - 3
RPM 패키징 및 gdal 함께 사용하기 (1)
작성일자: 2019년 12월 11일
최종수정: 2019년 12월 13일
작성자: N3
1. gdal 과 함께 빌드하기
gdal 에서 사용하기 위해 빌드 테스트를 해 본다.
사용한 버전은 gdal 2.3.2 버전이다.
$ cd ~/pdfium
$ mkdir include lib
$ cd include
$ ln -sf ~/pdfium/public pdfium
$ cd ../lib
$ ln -sf ../out/shared/*.so .
$ cd ~/gdal-2.3.2
$ ./configure \
..
--with-pdfium=~/pdfium/ \
..
checking for pdfium... no
configure: error: pdfium requested but not found
gdal 의 configure 에서 with-pdfium 설정시 pdfium 의 유무를 판단하는 코드를 살펴 본다.
echo '#include <fpdfview.h>' > testpdfium.cpp
echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
TEST_CXX_FLAGS="-std=c++0x"${CXX} ${CXXFLAGS} ${CPPFLAGS} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB}해당 코드를 앞에서 테스트했던 코드로 변경해서 테스트 해 보면....testpdfium.cpp:2:10: fatal error: core/include/fpdfapi/fpdf_page.h: 그런 파일이나 디렉터리가 없습니다#include <core/include/fpdfapi/fpdf_page.h>위 헤더 include 를 삭제한다. 그리고 테스트를 위한 링크 라이브러리 옵션을 추가한다.
--with-pdfium-extra-lib-for-test="-lpthread -lm -lc -lstdc++ -lz -ljpeg -lopenjp2 -llcms2 -lpng"
정상적으로 빌드 테스트되는 것을 확인할 수 있다. 이제 빌드해 본다.
$ make
In file included from gdal_pdf.h:53,
from pdfdataset.cpp:36:
pdfsdk_headers.h:119:10: fatal error: core/include/fpdfapi/fpdf_page.h: 그런 파일이나 디렉터리가 없습니다
#include <core/include/fpdfapi/fpdf_page.h>
gdal 에서 사용하고 있는 pdfium 의 헤더 경로가 최신 pdfium 과 다르다.
앞의 테스트코드 처럼 해당 코드에서 위 헤더추가를 모두 제거해준다.
iff -urN gdal-2.3.2-fedora/configure gdal-2.3.2-pdfium/configure
--- gdal-2.3.2-fedora/configure 2019-12-10 13:45:09.745538100 +0900
+++ gdal-2.3.2-pdfium/configure 2019-12-10 13:54:50.597897767 +0900
@@ -34698,7 +34698,6 @@
if test "x$with_pdfium_lib" = "x" ; then
rm -f testpdfium.*
echo '#include <fpdfview.h>' > testpdfium.cpp
- echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
TEST_CXX_FLAGS="-std=c++0x"
if test ! -z "`uname | grep Darwin`" ; then
diff -urN gdal-2.3.2-fedora/frmts/pdf/pdfsdk_headers.h gdal-2.3.2-pdfium/frmts/pdf/pdfsdk_headers.h
--- gdal-2.3.2-fedora/frmts/pdf/pdfsdk_headers.h 2018-09-21 18:04:33.000000000 +0900
+++ gdal-2.3.2-pdfium/frmts/pdf/pdfsdk_headers.h 2019-12-10 13:53:44.849271839 +0900
@@ -116,9 +116,9 @@
#include <cstring>
//#include <fpdfsdk/include/fsdk_define.h>
#include <fpdfview.h>
-#include <core/include/fpdfapi/fpdf_page.h>
-#include <core/include/fpdfapi/fpdf_objects.h>
-#include "fpdfsdk/include/fsdk_rendercontext.h"
+//#include <core/include/fpdfapi/fpdf_page.h>
+//#include <core/include/fpdfapi/fpdf_objects.h>
+//#include "fpdfsdk/include/fsdk_rendercontext.h"
#endif // HAVE_PDFIUM
#endif
수정 후, 다시 빌드 해 본다.
..
pdfobject.h:313:9: error: ‘CPDF_Object’ does not name a type; did you mean ‘PSObject’?
CPDF_Object* m_po;
^~~~~~~~~~~
..
삽질과 서핑 도중 아래의 선배 삽질러를 찾았다.
gdal 3.1(최신 소스코드) 에 pdfium 을 링크하기 위해 pdfium 을 패치한 내용들이다. 아래 링크는 clang 을 사용하며, static 라이브러리를 생성한다.
몇 개의 패치코드는 살펴볼 필요가 있다.
위 링크의 내용들을 참조하고 gdal 3.1 의 pdf 포맷 지원 코드를 현재 2.3.2 코드로 백포팅하기로 한다.
위 코드로 업그레이드하면, 관련되어서 업그레이드할 것들이 많다.
gdal 의 pdfium 최신 패치 확인하기
일단 URL 및 소스와 패치만 확인하고 패치코드 일부를 적용한 pdfium rpm 패키지를 만들어 본다.
gdal 과 함께 컴파일하는 것은 다음 삽질과정으로 남겨두고, gdal 테스트를 위해 먼저 pdfium 을 패키징해서 시스템에 설치해둔다.
2. CentOS 7 용 PDFium RPM 패키지 만들기
이제 삽질한 파일들과 내용들을 참조하여 CentOS 7 용 RPM 패키지로 만들어 본다.
패키지 이름은 대충 libpdfium 로 한다.
라이브러리 버전을 확인할 수 없어 일단은 chromium/3989 를 사용했다.
정적 라이브러리를 위한 옵션
# Build arguments go here.
# See "gn args <out_dir> --list" for available build arguments.
is_official_build = true
pdf_is_standalone = true # Set for a non-embedded build.
pdf_is_complete_lib = true # Static Library - libpdfium.a
pdf_enable_xfa = false # XFA support enabled.
pdf_enable_v8 = false # Javascript support enabled.
pdf_use_skia = false # Avoid skia backend experiment.
pdf_use_skia_paths = false # Avoid other skia backend experiment.
pdf_bundle_freetype = true
use_system_freetype = false
clang_use_chrome_plugins = false
use_goma = false
use_custom_libcxx = false
use_sysroot = false
use_rtti = true
is_component_build = false # Dynamic Library - libpdfium.so
is_debug = false # Enable debugging features.
is_clang = false # Avoid dependency hell.
use_system_zlib = true
use_system_libpng = true
use_system_lcms2 = true
use_system_libjpeg = true
use_libjpeg_turbo = true
use_system_libopenjpeg2 = true
동적 라이브러리를 위한 빌드
# Build arguments go here.
# See "gn args <out_dir> --list" for available build arguments.
is_official_build = true
pdf_is_standalone = true # Set for a non-embedded build.
pdf_is_complete_lib = false # Static Library
is_component_build = true # Dynamic Library
pdf_enable_xfa = false # XFA support enabled.
pdf_enable_v8 = false # Javascript support enabled.
pdf_use_skia = false # Avoid skia backend experiment.
pdf_use_skia_paths = false # Avoid other skia backend experiment.
pdf_bundle_freetype = true
use_system_freetype = false
clang_use_chrome_plugins = false
use_goma = false
use_custom_libcxx = false
use_sysroot = false
use_rtti = true
is_debug = false # Enable debugging features.
is_clang = false # Avoid dependency hell.
use_system_zlib = true
use_system_libpng = true
use_system_lcms2 = true
use_system_libjpeg = true
use_libjpeg_turbo = true
use_system_libopenjpeg2 = true
libpdfium.spec
%global commit 26cd122a8d10d33091bac50b025df919405a0950
%global shortcommit %(c=%{commit}; echo ${c:0:7})
%global chromium_rev "chromium/3989"
Name: libpdfium
Version: 0.0.3989
Release: 1%{?dist}
Summary: PDF generation and rendering library
Group: Development/Libraries
License: BSD 3-clause
URL: https://pdfium.googlesource.com/pdfium/
Source0: .
# Static Build Argument
Source1: pdfium-static-args.gn
Source2: pdfium-shared-args.gn
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
BuildRequires: zlib-devel
BuildRequires: libpng-devel
BuildRequires: libjpeg-turbo-devel
BuildRequires: openjpeg2-devel > 2.3.0
BuildRequires: lcms2-devel
BuildRequires: devtoolset-8-gcc-c++
BuildRequires: git
Requires: zlib
Requires: libpng
Requires: libjpeg-turbo
Requires: openjpeg2
Requires: lcms2
%description
Used in Chrome for displaying PDFs and print preview. Used in Android for PDF rendering
%package devel
Summary: Libraries and headers for pdfium
Group: Development/Libraries
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
You should install the libpdfium-devel package if you would like to
compile applications based on pdfium.
%prep
%build
## Change GCC
##scl enable devtoolset-8 bash
export DEPOT_TOOLS_URL="https://chromium.googlesource.com/chromium/tools/depot_tools.git"
export PDFIUM_URL="https://pdfium.googlesource.com/pdfium.git"
mkdir -p %{name}
cd %{name}
export CURDIR=`pwd`
export DEPOT_TOOLS_DIR=$CURDIR/depot_tools
if [ ! -d "$DEPOT_TOOLS_DIR" ]; thengit clone "$DEPOT_TOOLS_URL" depot_toolselsepushd $DEPOT_TOOLS_DIRgit checkout mastergit pullpopdfiexport PATH="$DEPOT_TOOLS_DIR:$PATH"# Checkout sources# From https://pdfium.googlesource.com/pdfium/gclient config --unmanaged "$PDFIUM_URL"# Tested Revisiongclient sync --revision="$chromium_rev"# Current Revision##gclient sync## Static Buildpushd pdfiummkdir -p out/staticcp %{SOURCE1} out/static/args.gngn gen out/static# Test Build Error##ninja -C out/static pdfium_allninja -C out/static pdfium## Shared Buildmkdir -p out/sharedcp %{SOURCE2} out/shared/args.gngn gen out/shared##ninja -C out/shared pdfium_allninja -C out/shared pdfiumpopd%installmkdir -p %{buildroot}/%{_includedir}/pdfiummkdir -p %{buildroot}/%{_libdir}cd %{name}/pdfium# Header InstallHEADER_SUBDIRS="build fpdfsdk core/fxge core/fxge/agg core/fxge/dib core/fpdfdoc core/fpdfapi/parser core/fpdfapi/page core/fpdfapi/render core/fxcrt third_party/agg23 third_party/base third_party/base/allocator/partition_allocator third_party/base/numerics"cp -r public %{buildroot}/%{_includedir}/pdfiumfor subdir in $HEADER_SUBDIRS; domkdir -p "%{buildroot}/%{_includedir}/pdfium/$subdir"cp "$subdir"/*.h "%{buildroot}/%{_includedir}/pdfium/$subdir"done# Static Library Installinstall -m 0644 out/static/obj/libpdfium.a %{buildroot}%{_libdir}/libpdfium.a# Shared Library Installinstall -m 0755 out/shared/*.so %{buildroot}%{_libdir}/%cleanrm -rf %{buildroot}%pre%postun%files%defattr(-,root,root,-)%doc%{_libdir}/*.so%files devel%defattr(-,root,root,-)%{_includedir}/pdfium%{_libdir}/libpdfium.a%changelog* Wed Dec 11 2019 N3 <n3syskr@gmail.com> - 0.0.0-1- initial build헤더파일과 정적 라이브러리는 devel 패키지로 따로 분리하였다.
gdal 과 빌드하기 위해 위에서 참조한 URL 로부터 pdfium 패치를 가져와 다시 빌드할 것이다.
pdfium 패치
diff -urN pdfium/core/fpdfapi/page/cpdf_occontext.cpp pdfium-a/core/fpdfapi/page/cpdf_occontext.cpp
--- pdfium/core/fpdfapi/page/cpdf_occontext.cpp 2019-12-11 15:41:16.595645562 +0900
+++ pdfium-a/core/fpdfapi/page/cpdf_occontext.cpp 2019-12-11 15:41:52.535538284 +0900
@@ -181,7 +181,7 @@
return bState;
}
-bool CPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj) const {
+bool CPDF_OCContextInterface::CheckObjectVisible(const CPDF_PageObject* pObj) const {
for (size_t i = 0; i < pObj->m_ContentMarks.CountItems(); ++i) {
const CPDF_ContentMarkItem* item = pObj->m_ContentMarks.GetItem(i);
if (item->GetName() == "OC" &&
diff -urN pdfium/core/fpdfapi/page/cpdf_occontext.h pdfium-a/core/fpdfapi/page/cpdf_occontext.h
--- pdfium/core/fpdfapi/page/cpdf_occontext.h 2019-12-11 15:41:16.596645587 +0900
+++ pdfium-a/core/fpdfapi/page/cpdf_occontext.h 2019-12-11 15:42:16.940144477 +0900
@@ -17,15 +17,21 @@
class CPDF_Document;
class CPDF_PageObject;
-class CPDF_OCContext final : public Retainable {
+class CPDF_OCContextInterface : public Retainable {
+ public:
+ virtual ~CPDF_OCContextInterface() = default;
+ virtual bool CheckOCGVisible(const CPDF_Dictionary* pOCGDict) const = 0;
+ virtual bool CheckObjectVisible(const CPDF_PageObject* pObj) const;
+};
+
+class CPDF_OCContext : public CPDF_OCContextInterface {
public:
enum UsageType { View = 0, Design, Print, Export };
template <typename T, typename... Args>
friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
- bool CheckOCGVisible(const CPDF_Dictionary* pOCGDict) const;
- bool CheckObjectVisible(const CPDF_PageObject* pObj) const;
+ bool CheckOCGVisible(const CPDF_Dictionary* pOCGDict) const override;
private:
CPDF_OCContext(CPDF_Document* pDoc, UsageType eUsageType);
diff -urN pdfium/core/fpdfapi/render/cpdf_renderoptions.h pdfium-a/core/fpdfapi/render/cpdf_renderoptions.h
--- pdfium/core/fpdfapi/render/cpdf_renderoptions.h 2019-12-11 15:41:16.596645587 +0900
+++ pdfium-a/core/fpdfapi/render/cpdf_renderoptions.h 2019-12-11 15:41:52.535538284 +0900
@@ -56,16 +56,16 @@
void SetDrawAnnots(bool draw) { m_bDrawAnnots = draw; }
bool GetDrawAnnots() const { return m_bDrawAnnots; }
- void SetOCContext(RetainPtr<CPDF_OCContext> context) {
+ void SetOCContext(RetainPtr<CPDF_OCContextInterface> context) {
m_pOCContext = context;
}
- const CPDF_OCContext* GetOCContext() const { return m_pOCContext.Get(); }
+ const CPDF_OCContextInterface* GetOCContext() const { return m_pOCContext.Get(); }
private:
Type m_ColorMode = kNormal;
bool m_bDrawAnnots = false;
Options m_Options;
- RetainPtr<CPDF_OCContext> m_pOCContext;
+ RetainPtr<CPDF_OCContextInterface> m_pOCContext;
};
#endif // CORE_FPDFAPI_RENDER_CPDF_RENDEROPTIONS_H_diff -urN pdfium/core/fpdfdoc/cpdf_annotlist.cpp pdfium-a/core/fpdfdoc/cpdf_annotlist.cpp--- pdfium/core/fpdfdoc/cpdf_annotlist.cpp 2019-12-11 15:41:16.596645587 +0900+++ pdfium-a/core/fpdfdoc/cpdf_annotlist.cpp 2019-12-11 15:41:52.536538309 +0900@@ -246,7 +246,7 @@if (pOptions) {const CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();- const CPDF_OCContext* pOCContext = pOptions->GetOCContext();+ const auto pOCContext = pOptions->GetOCContext();if (pAnnotDict && pOCContext &&!pOCContext->CheckOCGVisible(pAnnotDict->GetDictFor(pdfium::annotation::kOC))) {앞의 삽질에서 동적 라이브러리로 빌드하는 경우, icu libicuuc.so 파일이 생긴다.
이 라이브러리 이름이 시스템의 icu 라이브러리 이름과 충돌하며 API 도 완전히 호환되지 않는다.
그래서, 생성되는 라이브러리의 이름을 변경하기로 삽질해보자.
먼저, third_party/icu 폴더로 이동한다.
config.gni 파일을 열고 다음 변수를 추가한다.
declare_args() {
# Tells icu to load an external data file rather than rely on the icudata
# being linked directly into the binary.
icu_use_data_file = true
icu_rename = false
}
그리고, BUILD.gn 파일에 다음을 추가한다.
is_fuchsia 는 운영체제가 구글의 자체 운영체제인지 묻는 옵션이다. 이 옵션을 건들지 말고, 새로운 옵션을 추가해 이름만 수정한다.
..
if (is_fuchsia || icu_rename) {
# Fuchsia puts its own libicui18n.so in /system/lib where we need to put our
# .so when doing component builds, so we need to give this a different name.
output_name = "icui18n_cr"
}
..
if (is_fuchsia || icu_rename) {
# Fuchsia puts its own libicuuc.so in /system/lib where we need to put our
# .so when doing component builds, so we need to give this a different name.
output_name = "icuuc_cr"
}
전체 icu 라이브러리 이름 변경 패치
diff -urN pdfium/third_party/icu/BUILD.gn pdfium-icu/third_party/icu/BUILD.gn
--- pdfium/third_party/icu/BUILD.gn 2019-12-11 15:31:28.283025785 +0900
+++ pdfium-icu/third_party/icu/BUILD.gn 2019-12-11 16:36:25.528721775 +0900
@@ -630,7 +630,7 @@
configs += [ ":icu_code" ]
public_configs = [ ":icu_config" ]
- if (is_fuchsia) {
+ if (is_fuchsia || icu_rename) {
# Fuchsia puts its own libicui18n.so in /system/lib where we need to put our
# .so when doing component builds, so we need to give this a different name.
output_name = "icui18n_cr"
@@ -1080,7 +1080,7 @@
defines += [ "U_ICUDATAENTRY_IN_COMMON" ]
- if (is_fuchsia) {
+ if (is_fuchsia || icu_rename) {
# Fuchsia puts its own libicuuc.so in /system/lib where we need to put our
# .so when doing component builds, so we need to give this a different name.
output_name = "icuuc_cr"
diff -urN pdfium/third_party/icu/config.gni pdfium-icu/third_party/icu/config.gni
--- pdfium/third_party/icu/config.gni 2019-12-11 15:31:28.645034782 +0900
+++ pdfium-icu/third_party/icu/config.gni 2019-12-11 16:35:57.330023671 +0900
@@ -6,4 +6,5 @@
# Tells icu to load an external data file rather than rely on the icudata
# being linked directly into the binary.
icu_use_data_file = true
+ icu_rename = false
}
동적 라이브러리를 빌드할 때,
icu_rename = true
옵션을 추가해서 빌드하면,
libicuuc.so 파일의 이름이 libicuuc_cr.so 이름으로 생성되어 기존 icu 라이브러리와 충돌하지 않게 할 수 있다.
RPM 패키지을 만들고 로컬 인스톨해둔다.
Dependencies Resolved
=====================================================================================
Package Arch Version Repository Size
=====================================================================================
Installing:
libpdfium-devel x86_64 0.0.3989-1.el7 n3sys 3.4 M
Installing for dependencies:
libpdfium x86_64 0.0.3989-1.el7 n3sys 1.9 M
Transaction Summary
=====================================================================================
Install 1 Package (+1 Dependent package)
Total download size: 5.3 M
Installed size: 19 M
RedHat 계열에서 아래 소스 rpm 을 사용하면 된다.
테스트 시작 시점에 리비전 번호는 3989 였다. 현재는 3999다.
최신 버전으로 테스트하려면, libpdfium.spec 파일에서 해당 리비전 번호를 수정해서 테스트하면 된다.
%global chromium_rev "chromium/3989"
...
gclient sync --revision="$chromium_rev"
$ rpmbuild --rebuild libpdfium-0.0.3989-1.el7.src.rpm
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/respiro/rpmbuild/BUILDROOT/libpdfium-0.0.3989-1.el7.x86_64
Wrote: /home/respiro/rpmbuild/SRPMS/libpdfium-0.0.3989-1.el7.src.rpm
Wrote: /home/respiro/rpmbuild/RPMS/x86_64/libpdfium-0.0.3989-1.el7.x86_64.rpm
Wrote: /home/respiro/rpmbuild/RPMS/x86_64/libpdfium-devel-0.0.3989-1.el7.x86_64.rpm
설치 후 , 앞에서 만든 테스트 프로그램을 빌드하고 실행해 본다.
PDFIUM_REPO= /usr/include/pdfium/
INC_DIR= -I ${PDFIUM_REPO}/public
LIB_DIR= -L /lib64
실행이 정상 동작하고 있다.
이제 gdal 과 링크하기 위한 삽질을 시작하기 위한 준비를 마쳤다.
'Linux' 카테고리의 다른 글
PDFium 라이브러리 삽질기 - 5 (0) 2019.12.16 PDFium 라이브러리 삽질기 - 4 (0) 2019.12.13 PDFium 라이브러리 삽질기 - 2 (0) 2019.12.10 PDFium 라이브러리 삽질기 - 1 (0) 2019.12.10 TmaxOS 3.9.1 x64 설치기 (0) 2019.08.20