Linux

PDFium 라이브러리 삽질기 - 2

respiro 2019. 12. 10. 14:43

PDFium 라이브러리 삽질기 - 2

동적 라이브러리로 빌드하기

작성일자: 2019년 12월 10일

      최종수정: 2019년 12월 13일

작성자: N3



지난 삽질에서 여차저차해서 libpdfium.a 를 빌드했다.

이제, 다른 라이브러리 및 시스템에서 사용해볼만한 동적 라이브러리를 빌드하기 위한 삽질을 해 보려한다.


1. 공유 라이브러리로 빌드하기


 먼저, 지난 삽질과정에서 아규먼트 파일을 생성하고, ninja 컴파일 옵션을 생성할 때, 소스의 BUILD.gn 파일을 참조하는 것을 알았다.(build.ninja.d 파일)

 PDFium 소스의 주 디렉토리에서 BUILD.gn 을 살펴본다.


  if (pdf_is_complete_lib) {

    static_component_type = "static_library"

    complete_static_lib = true

    configs -= [ "//build/config/compiler:thin_archive" ]

  }


 args.gn 파일을 생성할 때 사용한 pdf__is_complete_lib = true 인 경우, 정적 라이브러리를 만들도록 되어 있으며, shared library 를 생성하는 룰은 찾을 수 없다.

 

 위 설정을 shared_library 로 변경하고 빌드해 본다.


$ gn args out/shared


# Build arguments go here.

# See "gn args <out_dir> --list" for available build arguments.

pdf_is_standalone = true                     # Set for a non-embedded build.

pdf_is_complete_lib=true

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


is_component_build = false 

is_debug = true                              # Enable debugging features.

is_clang = false                                    


use_system_zlib = true

use_system_libpng = true

use_system_lcms2 = true

use_system_libjpeg = true

use_libjpeg_turbo = true

use_system_libopenjpeg2 = true




$ cd out/shared

$ ninja pdfium

FAILED: build.ninja

../../buildtools/linux64/gn --root=../.. -q gen .

ERROR at //build/config/BUILDCONFIG.gn:640:5: Assertion failed.

    assert(invoker.static_component_type == "static_library" ||

    ^-----


See //BUILD.gn:143:1: whence it was called.

component("pdfium") {

^--------------------

ninja: error: rebuilding 'build.ninja': subcommand failed


pdfium/build/config/BUILDCONFIG.gn 파일의 오류를 찾아보면,  is_component_build 일 때 shared_library 를 활성화하는 것으로 보인다.

조금 전 강제로 변경했던 부분을 고치고 아규먼트를 수정한다.


pdf_is_complete_lib = false

is_component_build = true

로 변경하고 다시 빌드한다.


위 두 옵션을 모두 true 로 사용할 수는 없다.

FAILED: build.ninja

../../buildtools/linux64/gn --root=../.. -q gen .

ERROR at //pdfium.gni:76:1: Assertion failed.

assert(!pdf_is_complete_lib || !is_component_build,

^-----

pdf_is_complete_lib=true requires is_component_build=false

See //BUILD.gn:6:1: whence it was imported.

import("pdfium.gni")

^------------------

ninja: error: rebuilding 'build.ninja': subcommand failed



[respiro@localhost shared]$ ninja pdfium

[911/911] SOLINK ./libpdfium.so


[respiro@localhost shared]$ ls

args.gn        gen        genperf     icudtl.dat       libpdfium.so      re2c

build.ninja    genmacro   genstring   libicuuc.so      libpdfium.so.TOC  toolchain.ninja

build.ninja.d  genmodule  genversion  libicuuc.so.TOC  obj               yasm


[respiro@localhost shared]$ ldd libpdfium.so

        linux-vdso.so.1 =>  (0x00007ffd56fb0000)

        libicuuc.so => /home/respiro/rpmbuild/SOURCES/PDFium/pdfium/out/shared/./libicuuc.so (0x00007f8164213000)

        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8163ff7000)

        liblcms2.so.2 => /lib64/liblcms2.so.2 (0x00007f8163d9d000)

        libopenjp2.so.7 => /lib64/libopenjp2.so.7 (0x00007f8163b4a000)

        libz.so.1 => /lib64/libz.so.1 (0x00007f8163933000)

        libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007fb2140a3000)

        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f816362c000)

        libm.so.6 => /lib64/libm.so.6 (0x00007f816332a000)

        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f8163114000)

        libc.so.6 => /lib64/libc.so.6 (0x00007f8162d46000)

        /lib64/ld-linux-x86-64.so.2 (0x00007f8164c4d000)



[respiro@localhost test]$ nm libpdfium.so |grep InitLibrary
00000000002f4aaa T FPDF_InitLibrary
00000000002f4abb T FPDF_InitLibraryWithConfig


libicuuc.so 와 libpdfium.so 두 개의 dynamic so 파일이 생성되었다.

시스템의 동적 라이브러리를 사용하도록 설정했기 때문에, lib64 폴더의 동적 라이브러리를 링크하는 것을 볼 수 있다.

(libicuuc.so 는 icu 라이브러리로 일단은 시스템에 설치된 라이브러리와 충돌할 수 있다.)


삽질기-1 의 테스트 코드를 shared 라이브러리를 링크하도록 다시 빌드해본다.

Makefile 경로 수정


LIB_DIR= -L ${PDFIUM_REPO}/out/shared



$ LD_LIBRARY_PATH=../pdfium/out/shared make


$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/pdfium/out/shared/

$ pdf_hello

PDFium hello.


정상 동작하는 것을 확인했다.


다음 삽질기는 gdal 에서 pdfium 을 지원하기 위한 삽질 및 libpdfium 을 CentOS 7 RPM 패키지로 만드는 것이다.

2. 내용 누락 추가

삽질 중(gdal 과 함께 컴파일하는 도중)에 다음의 오류를 발견했다. 

 [respiro@localhost shared]$ readelf -a libpdfium.so |grep CPDF_OCContext

   246: 000000000006bbb0   494 FUNC    LOCAL  DEFAULT   12 _ZNK14CPDF_OCContext8GetO

  3998: 000000000006af90   172 FUNC   LOCAL  HIDDEN    12 _ZNK23CPDF_OCContextInter

  3999: 000000000006b0c0    61 FUNC    LOCAL  HIDDEN    12 _ZN14CPDF_OCContextC2EP13

  4000: 00000000003f35e8    48 OBJECT  LOCAL  HIDDEN    18 _ZTV14CPDF_OCContext

  4001: 000000000006b0c0    61 FUNC    LOCAL  HIDDEN    12 _ZN14CPDF_OCContextC1EP13

  4002: 000000000006b100  1146 FUNC    LOCAL  HIDDEN    12 _ZNK14CPDF_OCContext22Loa

  4003: 000000000006b580   704 FUNC    LOCAL  HIDDEN    12 _ZNK14CPDF_OCContext12Loa


GDAL을 빌드하는 중 동적 라이브러리와 링크중에 위와 같은 링크 오류를 찾았다.

함수를 찾을 수 없어서 확인하니까 모두 HIDDEN 으로 숨겨져 있다.


함수 EXPORT 코드를 확인한 후 수정한다.


~/pdfium/public/fpdfview.h (수정 불필요)

#if defined(COMPONENT_BUILD)

// FPDF_EXPORT should be consistent with |export| in the pdfium_fuzzer

// template in testing/fuzzers/BUILD.gn.

#if defined(WIN32)

#if defined(FPDF_IMPLEMENTATION)

#define FPDF_EXPORT __declspec(dllexport)

#else

#define FPDF_EXPORT __declspec(dllimport)

#endif  // defined(FPDF_IMPLEMENTATION)

#else

#if defined(FPDF_IMPLEMENTATION)

#define FPDF_EXPORT __attribute__((visibility("default")))

#else

#define FPDF_EXPORT

#endif  // defined(FPDF_IMPLEMENTATION)

#endif  // defined(WIN32)

#else

#define FPDF_EXPORT

#endif  // defined(COMPONENT_BUILD)


#if defined(WIN32) && defined(FPDFSDK_EXPORTS)

#define FPDF_CALLCONV __stdcall

#else

#define FPDF_CALLCONV

#endif


./build/config/BUILDCONFIG.gn (아래와 같이 제거한다.)

if (is_posix) {

  if (current_os != "aix") {

    default_compiler_configs +=

        [ "//build/config/gcc:symbol_visibility_hidden" ]

  }

}

symbol visibility hidden 을 제거한다.


~/pdfium/BUILD.gn 파일의 옵션을 보면, 수정할 필요없다.


config("pdfium_implementation_config") {

  defines = [ "FPDF_IMPLEMENTATION" ]

  visibility = [ ":pdfium_public_headers" ]

}



group("pdfium_public_headers") {

  public_deps = [

    ":pdfium_public_headers_impl",

  ]

  public_configs = [

    ":pdfium_public_config",

    ":pdfium_implementation_config",

  ]

}



빌드된 라이브러리를 확인한다.


[respiro@localhost shared]$ readelf -a libpdfium.so |grep CPDF_OCCon

...


0000004b3b58  0a3000000007 R_X86_64_JUMP_SLO 0000000000132d10 _ZN14CPDF_OCContextD0E + 0

0000004b3b60  173300000007 R_X86_64_JUMP_SLO 00000000001334e0 _ZNK14CPDF_OCContext15 + 0

0000004b8f70  0ac100000007 R_X86_64_JUMP_SLO 0000000000132510 _ZN14CPDF_OCContextC1E + 0

   583: 00000000001329e0   704 FUNC    GLOBAL DEFAULT   12 _ZNK14CPDF_OCContext12Loa

   711: 00000000004a9b70    48 OBJECT  WEAK   DEFAULT   21 _ZTV14CPDF_OCContext

  1574: 00000000002f31b0    26 OBJECT  WEAK   DEFAULT   14 _ZTS23CPDF_OCContextInter

  1812: 0000000000133200   730 FUNC    GLOBAL DEFAULT   12 _ZNK14CPDF_OCContext13Loa

  2284: 0000000000132eb0   323 FUNC    GLOBAL DEFAULT   12 _ZNK14CPDF_OCContext13Get

  2608: 0000000000132d10    36 FUNC    GLOBAL DEFAULT   12 _ZN14CPDF_OCContextD0Ev

  2753: 0000000000132510    65 FUNC    GLOBAL DEFAULT   12 _ZN14CPDF_OCContextC1EP13

  3146: 00000000004a9b10    24 OBJECT  WEAK   DEFAULT   21 _ZTI23CPDF_OCContextInter

  3209: 00000000004a9b28    24 OBJECT  WEAK   DEFAULT   21 _ZTI14CPDF_OCContext

  4728: 0000000000132cf0    28 FUNC    GLOBAL DEFAULT   12 _ZN14CPDF_OCContextD1Ev

  5079: 00000000001323e0   172 FUNC    GLOBAL DEFAULT   12 _ZNK23CPDF_OCContextInter

  5939: 00000000001334e0   177 FUNC    GLOBAL DEFAULT   12 _ZNK14CPDF_OCContext15Che

  6302: 0000000000133000   512 FUNC    GLOBAL DEFAULT   12 _ZNK14CPDF_OCContext8GetO

  6803: 0000000000132cf0    28 FUNC    GLOBAL DEFAULT   12 _ZN14CPDF_OCContextD2Ev

  6887: 00000000004a9b40    48 OBJECT  WEAK   DEFAULT   21 _ZTV23CPDF_OCContextInter

  7527: 0000000000132510    65 FUNC    GLOBAL DEFAULT   12 _ZN14CPDF_OCContextC2EP13

...


3. Test


$ cd out/shared


[respiro@localhost shared]$ ./pdfium_test  --help

Unrecognized argument --help

Usage: pdfium_test [OPTION] [FILE]...

  --show-config        - print build options and exit

  --show-metadata      - print the file metadata

  --show-pageinfo      - print information about pages

  --show-structure     - print the structure elements from the document

  --send-events        - send input described by .evt file

  --mem-document       - load document with FPDF_LoadMemDocument()

  --render-oneshot     - render image without using progressive renderer

  --lcd-text           - render text optimized for LCD displays

  --no-nativetext      - render without using the native text output

  --grayscale          - render grayscale output

  --limit-cache        - render limiting image cache size

  --force-halftone     - render forcing halftone

  --printing           - render as if for printing

  --no-smoothtext      - render disabling text anti-aliasing

  --no-smoothimage     - render disabling image anti-alisasing

  --no-smoothpath      - render disabling path anti-aliasing

  --reverse-byte-order - render to BGRA, if supported by the output format

  --save-attachments   - write embedded attachments <pdf-name>.attachment.<attachment-name>

  --save-images        - write embedded images <pdf-name>.<page-number>.<object-number>.png

  --save-thumbs        - write page thumbnails <pdf-name>.thumbnail.<page-number>.png

  --save-thumbs-dec    - write page thumbnails' decoded stream data<pdf-name>.thumbnail.decoded.<page-number>.png

  --save-thumbs-raw    - write page thumbnails' raw stream data<pdf-name>.thumbnail.raw.<page-number>.png

  --no-system-fonts    - do not use system fonts, overrides --font-dir

  --bin-dir=<path>     - override path to v8 external data

  --font-dir=<path>    - override path to external fonts

  --scale=<number>     - scale output size by number (e.g. 0.5)

  --pages=<number>(-<number>) - only render the given 0-based page(s)

  --txt   - write page text in UTF32-LE <pdf-name>.<page-number>.txt

  --png   - write page images <pdf-name>.<page-number>.png

  --ppm   - write page images <pdf-name>.<page-number>.ppm

  --annot - write annotation info <pdf-name>.<page-number>.annot.txt

  --md5   - write output image paths and their md5 hashes to stdout.

  --time=<number> - Seconds since the epoch to set system time.


$ pdfium_test --png gdalautotest-2.3.2/gdrivers/data/adobe_style_geospatial_with_xmp.pdf


adobe_style_geospatial_with_xmp.pdf


ninja 빌드시에  ninja pdfium_all 옵션으로 빌드하면, 두 가지 테스트 도구를 더 생성한다.

pdfium_unittests

pdfium_embeddertests


이 외에 test 폴더에도 테스트 도구들이 더 생성된다.

testing/tools/run_corpus_tests.py

testing/tools/run_javascript_tests.py

testing/tools/run_pixel_tests.py


$ ./run_corpus_tests.py  --build-dir ~/PDFium/pdfium/out/shared/

..
test_control.pdf result is suppressed
text_field.pdf result is suppressed
text_field.pdf result is suppressed
text_field.pdf result is suppressed
text_field.pdf result is suppressed


Summary of Failures:
/home/respiro/PDFium/pdfium/testing/corpus/fx/FRC_4.5_part1/FRC_4.5.4_ICCBased.pdf
/home/respiro/PDFium/pdfium/testing/corpus/fx/color/color_icc_based.pdf
/home/respiro/PDFium/pdfium/testing/corpus/fx/other/3bigpreview.pdf
/home/respiro/PDFium/pdfium/testing/corpus/fx/text/050_extra_m.pdf
/home/respiro/PDFium/pdfium/testing/corpus/fx/text/5.5_simple_font.pdf
/home/respiro/PDFium/pdfium/testing/corpus/fx/text/test_m.pdf
/home/respiro/PDFium/pdfium/testing/corpus/third_party/tcpdf/example_033.pdf
/home/respiro/PDFium/pdfium/testing/corpus/third_party/tcpdf/example_038.pdf
/home/respiro/PDFium/pdfium/testing/corpus/third_party/tcpdf/example_055.pdf

Test cases executed: 693
  Successes: 599
  Suppressed: 85
    Surprises: 0
  Failures: 9

 ./run_pixel_tests.py  --build-dir ~/PDFium/pdfium/out/shared/
...
Summary of Failures:
/home/respiro/rpmbuild/SOURCES/PDFium/pdfium/testing/resources/pixel/bug_1308.pdf

Test cases executed: 84
  Successes: 77
  Suppressed: 6
    Surprises: 0
  Failures: 1


fail 이 있지만 일단 무시하자.