Home | History | Annotate | Download | only in harfbuzz_ng
      1 cmake_minimum_required(VERSION 2.8.0)
      2 project(harfbuzz)
      3 
      4 enable_testing()
      5 
      6 ## Limit framework build to Xcode generator
      7 if (BUILD_FRAMEWORK)
      8   # for a framework on macOS, use `cmake .. -DBUILD_FRAMEWORK:BOOL=true -G Xcode`
      9   if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
     10     message(FATAL_ERROR
     11       "You should use Xcode generator with BUILD_FRAMEWORK enabled")
     12   endif ()
     13   set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
     14   set(CMAKE_MACOSX_RPATH ON)
     15   set(BUILD_SHARED_LIBS ON)
     16 endif ()
     17 
     18 
     19 ## Disallow in-source builds, as CMake generated make files can collide with autotools ones
     20 if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
     21   message(FATAL_ERROR
     22     "
     23 In-source builds are not permitted!  Make a separate folder for"
     24     " building, e.g.,"
     25     "
     26   mkdir build; cd build; cmake .."
     27     "
     28 Before that, remove the files created by this failed run with"
     29     "
     30   rm -rf CMakeCache.txt CMakeFiles")
     31 endif ()
     32 
     33 
     34 ## HarfBuzz build configurations
     35 option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
     36 option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
     37 option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON)
     38 option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
     39 option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
     40 if (APPLE)
     41   option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON)
     42 endif ()
     43 if (WIN32)
     44   option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
     45   option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF)
     46 endif ()
     47 option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF)
     48 if (HB_BUILD_UTILS)
     49   set(HB_HAVE_GLIB ON)
     50   set(HB_HAVE_FREETYPE ON)
     51 endif ()
     52 
     53 option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
     54 if (HB_HAVE_GOBJECT)
     55   set(HB_HAVE_GLIB ON)
     56 endif ()
     57 
     58 option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF)
     59 if (HB_HAVE_INTROSPECTION)
     60   set(HB_HAVE_GOBJECT ON)
     61   set(HB_HAVE_GLIB ON)
     62 endif ()
     63 
     64 include_directories(AFTER
     65   ${PROJECT_SOURCE_DIR}/src
     66   ${PROJECT_BINARY_DIR}/src
     67   )
     68 
     69 add_definitions(-DHAVE_OT)
     70 add_definitions(-DHAVE_FALLBACK)
     71 
     72 if (BUILD_SHARED_LIBS)
     73   add_definitions(-DHAVE_ATEXIT)
     74 endif ()
     75 
     76 if (MSVC)
     77   add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
     78 endif ()
     79 
     80 if (WIN32 AND NOT MINGW AND BUILD_SHARED_LIBS)
     81   add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
     82 endif ()
     83 
     84 
     85 ## Detect if we are running inside a distribution or regular repository folder
     86 set(IN_HB_DIST FALSE)
     87 if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog")
     88   # perhaps we are on dist directory
     89   set(IN_HB_DIST TRUE)
     90   set(HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
     91 endif ()
     92 
     93 
     94 ## Extract variables from Makefile files
     95 # http://stackoverflow.com/a/27630120/1414809
     96 function (prepend var prefix)
     97   set(listVar "")
     98   foreach (f ${ARGN})
     99     list(APPEND listVar "${prefix}${f}")
    100   endforeach ()
    101   set(${var} "${listVar}" PARENT_SCOPE)
    102 endfunction ()
    103 
    104 function (extract_make_variable variable file prefix)
    105   string(REGEX MATCH "${variable} = ([^$]+)\\$" temp ${file})
    106   string(REGEX MATCHALL "[^ \n\t\\]+" list ${CMAKE_MATCH_1})
    107   prepend(list ${prefix} ${list})
    108   set(${variable} ${list} PARENT_SCOPE)
    109 endfunction ()
    110 
    111 file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
    112 file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
    113 file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES)
    114 
    115 extract_make_variable(HB_BASE_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/")
    116 extract_make_variable(HB_BASE_headers ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/")
    117 extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/")
    118 extract_make_variable(HB_OT_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/")
    119 extract_make_variable(HB_OT_headers ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/")
    120 
    121 if (IN_HB_DIST)
    122   set(RAGEL_GENERATED_DIR "${PROJECT_SOURCE_DIR}/src/")
    123 else ()
    124   set(RAGEL_GENERATED_DIR "${PROJECT_BINARY_DIR}/src/")
    125 endif ()
    126 extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES} ${RAGEL_GENERATED_DIR})
    127 extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES} ${RAGEL_GENERATED_DIR})
    128 
    129 extract_make_variable(HB_VIEW_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/")
    130 extract_make_variable(HB_SHAPE_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/")
    131 extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/")
    132 
    133 extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES} "${PROJECT_SOURCE_DIR}/src/hb-ucdn/")
    134 
    135 file(READ configure.ac CONFIGUREAC)
    136 string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC})
    137 set(HB_VERSION ${CMAKE_MATCH_1})
    138 set(HB_VERSION_MAJOR ${CMAKE_MATCH_2})
    139 set(HB_VERSION_MINOR ${CMAKE_MATCH_3})
    140 set(HB_VERSION_MICRO ${CMAKE_MATCH_4})
    141 
    142 
    143 ## Define ragel tasks
    144 if (NOT IN_HB_DIST)
    145   find_program(RAGEL "ragel" CMAKE_FIND_ROOT_PATH_BOTH)
    146 
    147   if (RAGEL)
    148     message(STATUS "ragel found at: ${RAGEL}")
    149   else ()
    150     message(FATAL_ERROR "ragel not found, get it here -- http://www.complang.org/ragel/ or, use harfbuzz releases https://github.com/harfbuzz/harfbuzz/releases")
    151   endif ()
    152 
    153   foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources} ${HB_OT_RAGEL_GENERATED_sources})
    154     string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output})
    155     set(target_name ${CMAKE_MATCH_1})
    156     add_custom_command(OUTPUT ${ragel_output}
    157       COMMAND ${RAGEL} -G2 -o ${ragel_output} ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -I ${PROJECT_SOURCE_DIR} ${ARGN}
    158       DEPENDS ${PROJECT_SOURCE_DIR}/src/${target_name}.rl
    159       )
    160     add_custom_target(harfbuzz_${target_name} DEPENDS ${PROJECT_BINARY_DIR}/src/${target_name})
    161   endforeach ()
    162 
    163   mark_as_advanced(RAGEL)
    164 endif ()
    165 
    166 
    167 ## Generate hb-version.h
    168 if (NOT IN_HB_DIST)
    169   set(HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in")
    170   set(HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h")
    171   set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true)
    172   configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY)
    173   execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different
    174     "${HB_VERSION_H}.tmp"
    175     "${HB_VERSION_H}"
    176     )
    177   file(REMOVE "${HB_VERSION_H}.tmp")
    178 endif ()
    179 
    180 
    181 ## Define sources and headers of the project
    182 set(project_sources
    183   ${HB_BASE_sources}
    184   ${HB_BASE_RAGEL_GENERATED_sources}
    185 
    186   ${HB_FALLBACK_sources}
    187   ${HB_OT_sources}
    188   ${HB_OT_RAGEL_GENERATED_sources}
    189   )
    190 
    191 set(project_extra_sources)
    192 
    193 set(project_headers
    194   ${HB_VERSION_H}
    195 
    196   ${HB_BASE_headers}
    197   ${HB_OT_headers}
    198   )
    199 
    200 
    201 ## Find and include needed header folders and libraries
    202 if (HB_HAVE_FREETYPE)
    203 
    204   include(FindFreetype)
    205   if (NOT FREETYPE_FOUND)
    206     message(FATAL_ERROR "HB_HAVE_FREETYPE was set, but we failed to find it. Maybe add a CMAKE_PREFIX_PATH= to your Freetype2 install prefix")
    207   endif()
    208 
    209   list(APPEND THIRD_PARTY_LIBS ${FREETYPE_LIBRARIES})
    210   include_directories(AFTER ${FREETYPE_INCLUDE_DIRS})
    211   add_definitions(-DHAVE_FREETYPE=1 -DHAVE_FT_FACE_GETCHARVARIANTINDEX=1)
    212 
    213   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ft.cc)
    214   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h)
    215 
    216 endif ()
    217 
    218 if (HB_HAVE_GRAPHITE2)
    219   add_definitions(-DHAVE_GRAPHITE2)
    220 
    221   find_path(GRAPHITE2_INCLUDE_DIR graphite2/Font.h)
    222   find_library(GRAPHITE2_LIBRARY graphite2)
    223 
    224   include_directories(${GRAPHITE2_INCLUDE_DIR})
    225 
    226   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-graphite2.cc)
    227   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h)
    228 
    229   list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
    230 
    231   mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
    232 endif ()
    233 
    234 if (HB_BUILTIN_UCDN)
    235   include_directories(src/hb-ucdn)
    236   add_definitions(-DHAVE_UCDN)
    237 
    238   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ucdn.cc)
    239   list(APPEND project_extra_sources ${LIBHB_UCDN_sources})
    240 endif ()
    241 
    242 if (HB_HAVE_GLIB)
    243   add_definitions(-DHAVE_GLIB)
    244 
    245   # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindGLIB.cmake
    246   find_package(PkgConfig)
    247   pkg_check_modules(PC_GLIB QUIET glib-2.0)
    248 
    249   find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
    250   find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include)
    251   find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
    252 
    253   include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR})
    254 
    255   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-glib.cc)
    256   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h)
    257 
    258   list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
    259 
    260   mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR)
    261 endif ()
    262 
    263 if (HB_HAVE_ICU)
    264   add_definitions(-DHAVE_ICU)
    265 
    266   # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindICU.cmake
    267   find_package(PkgConfig)
    268   pkg_check_modules(PC_ICU QUIET icu-uc)
    269 
    270   find_path(ICU_INCLUDE_DIR NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR})
    271   find_library(ICU_LIBRARY NAMES libicuuc cygicuuc cygicuuc32 icuuc HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR})
    272 
    273   include_directories(${ICU_INCLUDE_DIR})
    274 
    275   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-icu.cc)
    276   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
    277 
    278   list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY})
    279 
    280   mark_as_advanced(ICU_INCLUDE_DIR ICU_LIBRARY)
    281 endif ()
    282 
    283 if (APPLE AND HB_HAVE_CORETEXT)
    284   # Apple Advanced Typography
    285   add_definitions(-DHAVE_CORETEXT)
    286 
    287   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc)
    288   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
    289 
    290   find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
    291   if (APPLICATION_SERVICES_FRAMEWORK)
    292     list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
    293   endif (APPLICATION_SERVICES_FRAMEWORK)
    294   
    295   mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
    296 endif ()
    297 
    298 if (WIN32 AND HB_HAVE_UNISCRIBE)
    299   add_definitions(-DHAVE_UNISCRIBE)
    300 
    301   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.cc)
    302   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
    303 
    304   list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
    305 endif ()
    306 
    307 if (WIN32 AND HB_HAVE_DIRECTWRITE)
    308   add_definitions(-DHAVE_DIRECTWRITE)
    309 
    310   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-directwrite.cc)
    311   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
    312 
    313   list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4)
    314 endif ()
    315 
    316 if (HB_HAVE_GOBJECT)
    317   include(FindPythonInterp)
    318   include(FindPerl)
    319   
    320   # Use the hints from glib-2.0.pc to find glib-mkenums
    321   find_package(PkgConfig)
    322   pkg_check_modules(PC_GLIB QUIET glib-2.0)
    323   find_program(GLIB_MKENUMS glib-mkenums
    324     HINTS ${PC_glib_mkenums}
    325     )
    326   set(GLIB_MKENUMS_CMD)
    327 
    328   if (WIN32 AND NOT MINGW)
    329     # In Visual Studio builds, shebang lines are not supported
    330     # in the standard cmd.exe shell that we use, so we need to
    331     # first determine whether glib-mkenums is a Python or PERL
    332     # script
    333     execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}" --version
    334       RESULT_VARIABLE GLIB_MKENUMS_PYTHON
    335       OUTPUT_QUIET ERROR_QUIET
    336       )
    337     if (GLIB_MKENUMS_PYTHON EQUAL 0)
    338       message("${GLIB_MKENUMS} is a Python script.")
    339       set(GLIB_MKENUMS_CMD "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}")
    340     else ()
    341       execute_process(COMMAND "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}" --version
    342         RESULT_VARIABLE GLIB_MKENUMS_PERL
    343         OUTPUT_QUIET ERROR_QUIET
    344         )
    345       if (GLIB_MKENUMS_PERL EQUAL 0)
    346         message("${GLIB_MKENUMS} is a PERL script.")
    347         set(GLIB_MKENUMS_CMD "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}")
    348       endif ()
    349       if (NOT GLIB_MKENUMS_PERL EQUAL 0 AND NOT GLIB_MKENUMS_PYTHON EQUAL 0)
    350         message(FATAL_ERROR "Unable to determine type of glib-mkenums script")
    351       endif ()
    352 	endif ()
    353   else ()
    354     set(GLIB_MKENUMS_CMD "${GLIB_MKENUMS}")
    355   endif ()
    356   if (NOT GLIB_MKENUMS_CMD)
    357     message(FATAL_ERROR "HB_HAVE_GOBJECT was set, but we failed to find glib-mkenums, which is required")
    358   endif()
    359 
    360   pkg_check_modules(PC_GOBJECT QUIET gobject-2.0)
    361 
    362   find_library(GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
    363   find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
    364 
    365   include_directories(${GOBJECTCONFIG_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR})
    366   mark_as_advanced(GOBJECT_LIBRARIES GOBJECT_INCLUDE_DIR)
    367 
    368   list(APPEND hb_gobject_sources ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.cc)
    369   list(APPEND hb_gobject_gen_sources
    370     ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
    371     )
    372   list(APPEND hb_gobject_structs_headers
    373     ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.h
    374     )
    375   list(APPEND hb_gobject_headers
    376     ${PROJECT_SOURCE_DIR}/src/hb-gobject.h
    377     ${hb_gobject_structs_headers}
    378     )
    379   list(APPEND hb_gobject_gen_headers
    380     ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
    381     )
    382 
    383   add_custom_command (
    384     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
    385     COMMAND ${GLIB_MKENUMS_CMD}
    386       --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
    387       --identifier-prefix hb_
    388       --symbol-prefix hb_gobject
    389       ${hb_gobject_structs_headers}
    390       ${project_headers}
    391       > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp
    392     COMMAND "${CMAKE_COMMAND}"
    393       "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp"
    394       "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h"
    395       -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
    396     DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
    397       ${hb_gobject_header}
    398       ${project_headers}
    399     )
    400 
    401   add_custom_command (
    402     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
    403     COMMAND ${GLIB_MKENUMS_CMD}
    404       --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
    405       --identifier-prefix hb_
    406       --symbol-prefix hb_gobject
    407       ${hb_gobject_header}
    408       ${project_headers}
    409       > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp
    410     COMMAND "${CMAKE_COMMAND}"
    411       "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp"
    412       "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc"
    413       -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
    414     DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
    415       ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
    416       ${hb_gobject_header}
    417       ${project_headers}
    418     )
    419 endif ()
    420 
    421 ## Atomic ops availability detection
    422 file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c"
    423 "		void memory_barrier (void) { __sync_synchronize (); }
    424 		int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
    425 		int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
    426 		void mutex_unlock (int *m) { __sync_lock_release (m); }
    427 		int main () { return 0; }
    428 ")
    429 try_compile(HB_HAVE_INTEL_ATOMIC_PRIMITIVES
    430   ${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives
    431   SOURCES ${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c)
    432 if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES)
    433   add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES)
    434 endif ()
    435 
    436 file(WRITE "${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c"
    437 "		#include <atomic.h>
    438 		/* This requires Solaris Studio 12.2 or newer: */
    439 		#include <mbarrier.h>
    440 		void memory_barrier (void) { __machine_rw_barrier (); }
    441 		int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
    442 		void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
    443 		int main () { return 0; }
    444 ")
    445 try_compile(HB_HAVE_SOLARIS_ATOMIC_OPS
    446   ${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops
    447   SOURCES ${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c)
    448 if (HB_HAVE_SOLARIS_ATOMIC_OPS)
    449   add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS)
    450 endif ()
    451 
    452 
    453 ## Define harfbuzz library
    454 add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
    455 target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
    456 
    457 ## Define harfbuzz-gobject library
    458 if (HB_HAVE_GOBJECT)
    459   add_library(harfbuzz-gobject
    460     ${hb_gobject_sources}
    461     ${hb_gobject_gen_sources}
    462     ${hb_gobject_headers}
    463     ${hb_gobject_gen_headers}
    464     )
    465   include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
    466   add_dependencies(harfbuzz-gobject harfbuzz)
    467   target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
    468 endif ()
    469 
    470 # On Windows, g-ir-scanner requires a DLL build in order for it to work
    471 if (WIN32)
    472   if (NOT BUILD_SHARED_LIBS)
    473     message("Building introspection files on Windows requires BUILD_SHARED_LIBS to be enabled.")
    474     set(HB_HAVE_INTROSPECTION OFF)
    475   endif ()
    476 endif ()
    477 
    478 if (HB_HAVE_INTROSPECTION)
    479 
    480   find_package(PkgConfig)
    481   pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
    482 
    483   find_program(G_IR_SCANNER g-ir-scanner
    484     HINTS ${PC_g_ir_scanner}
    485     )
    486 
    487   find_program(G_IR_COMPILER g-ir-compiler
    488     HINTS ${PC_g_ir_compiler}
    489     )
    490 
    491   if (WIN32 AND NOT MINGW)
    492     # Note that since we already enable HB_HAVE_GOBJECT
    493     # we would already have PYTHON_EXECUTABLE handy
    494     set(G_IR_SCANNER_CMD "${PYTHON_EXECUTABLE}" "${G_IR_SCANNER}")
    495   else ()
    496     set(G_IR_SCANNER_CMD "${G_IR_SCANNER}")
    497   endif ()
    498 
    499   # We need to account for the varying output directories
    500   # when we build using Visual Studio projects
    501   if("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
    502     set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
    503   else ()
    504     set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
    505   endif ()
    506 
    507   # Get the CFlags that we used to build HarfBuzz/HarfBuzz-GObject
    508   set (hb_defines_cflags "")
    509   foreach(hb_cflag ${hb_cflags})
    510     list(APPEND hb_defines_cflags "-D${hb_cflag}")
    511   endforeach(hb_cflag)
    512 
    513   # Get the other dependent libraries we used to build HarfBuzz/HarfBuzz-GObject
    514   set (extra_libs "")
    515   foreach (extra_lib ${THIRD_PARTY_LIBS})
    516     # We don't want the .lib extension here...
    517     string(REPLACE ".lib" "" extra_lib_stripped "${extra_lib}")
    518     list(APPEND extra_libs "--extra-library=${extra_lib_stripped}")
    519   endforeach ()
    520 
    521   set(introspected_sources)
    522   foreach (f
    523     ${project_headers}
    524     ${project_sources}
    525     ${hb_gobject_gen_sources}
    526     ${hb_gobject_gen_headers}
    527     ${hb_gobject_sources}
    528     ${hb_gobject_headers}
    529     )
    530     if (WIN32)
    531       # Nasty issue: We need to make drive letters lower case,
    532       # otherwise g-ir-scanner won't like it and give us a bunch
    533       # of invalid items and unresolved types...
    534       STRING(SUBSTRING "${f}" 0 1 drive)
    535       STRING(SUBSTRING "${f}" 1 -1 path)
    536       if (drive MATCHES "[A-Z]")
    537         STRING(TOLOWER ${drive} drive_lower)
    538         list(APPEND introspected_sources "${drive_lower}${path}")
    539       else ()
    540         list(APPEND introspected_sources "${f}")
    541       endif ()
    542     else ()
    543       list(APPEND introspected_sources "${f}")
    544     endif ()
    545   endforeach ()
    546 
    547   # Finally, build the introspection files...
    548   add_custom_command (
    549     TARGET harfbuzz-gobject
    550     POST_BUILD
    551     COMMAND ${G_IR_SCANNER_CMD}
    552       --warn-all --no-libtool --verbose
    553       -n hb
    554       --namespace=HarfBuzz
    555       --nsversion=0.0
    556       --identifier-prefix=hb_
    557       --include GObject-2.0
    558       --pkg-export=harfbuzz
    559       --cflags-begin
    560       -I${PROJECT_SOURCE_DIR}/src
    561       -I${PROJECT_BINARY_DIR}/src
    562       ${hb_includedir_cflags}
    563       ${hb_defines_cflags}
    564       -DHB_H
    565       -DHB_H_IN
    566       -DHB_OT_H
    567       -DHB_OT_H_IN
    568       -DHB_GOBJECT_H
    569       -DHB_GOBJECT_H_IN
    570       -DHB_EXTERN=
    571       --cflags-end
    572       --library=harfbuzz-gobject
    573       --library=harfbuzz
    574       -L${hb_libpath}
    575       ${extra_libs}
    576       ${introspected_sources}
    577       -o ${hb_libpath}/HarfBuzz-0.0.gir
    578     DEPENDS harfbuzz-gobject harfbuzz
    579     )
    580 
    581   add_custom_command (
    582     TARGET harfbuzz-gobject
    583     POST_BUILD
    584     COMMAND "${G_IR_COMPILER}"
    585       --verbose --debug
    586       --includedir ${CMAKE_CURRENT_BINARY_DIR}
    587       ${hb_libpath}/HarfBuzz-0.0.gir
    588       -o ${hb_libpath}/HarfBuzz-0.0.typelib
    589     DEPENDS ${hb_libpath}/HarfBuzz-0.0.gir harfbuzz-gobject
    590     )
    591 endif ()
    592 
    593 ## Additional framework build configs
    594 if (BUILD_FRAMEWORK)
    595   set(CMAKE_MACOSX_RPATH ON)
    596   set_target_properties(harfbuzz PROPERTIES
    597     FRAMEWORK TRUE
    598     PUBLIC_HEADER "${project_headers}"
    599     XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
    600   )
    601   set(MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz")
    602   set(MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}")
    603   set(MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}")
    604 endif ()
    605 
    606 
    607 ## Additional harfbuzz build artifacts
    608 if (HB_BUILD_UTILS)
    609   # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindCairo.cmake
    610   find_package(PkgConfig)
    611   pkg_check_modules(PC_CAIRO QUIET cairo)
    612 
    613   find_path(CAIRO_INCLUDE_DIRS NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo)
    614   find_library(CAIRO_LIBRARIESNAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS})
    615 
    616   add_definitions("-DPACKAGE_NAME=\"HarfBuzz\"")
    617   add_definitions("-DPACKAGE_VERSION=\"${HB_VERSION}\"")
    618   include_directories(${CAIRO_INCLUDE_DIRS})
    619 
    620   add_executable(hb-view ${HB_VIEW_sources})
    621   target_link_libraries(hb-view harfbuzz ${CAIRO_LIBRARIESNAMES})
    622 
    623   add_executable(hb-shape ${HB_SHAPE_sources})
    624   target_link_libraries(hb-shape harfbuzz)
    625 
    626   add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
    627   target_link_libraries(hb-ot-shape-closure harfbuzz)
    628 
    629   mark_as_advanced(CAIRO_INCLUDE_DIRS CAIRO_LIBRARIESNAMES)
    630 endif ()
    631 
    632 
    633 ## Install
    634 if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
    635   install(FILES ${project_headers} DESTINATION include/harfbuzz)
    636   if (HB_HAVE_GOBJECT)
    637     install(FILES ${hb_gobject_headers} ${hb_gobject_gen_headers} DESTINATION include/harfbuzz)
    638   endif ()
    639 endif ()
    640 
    641 if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
    642   install(TARGETS harfbuzz
    643     ARCHIVE DESTINATION lib
    644     LIBRARY DESTINATION lib
    645     RUNTIME DESTINATION bin
    646     FRAMEWORK DESTINATION Library/Frameworks
    647     )
    648   if (HB_BUILD_UTILS)
    649     install(TARGETS hb-view
    650       RUNTIME DESTINATION bin
    651     )
    652     install(TARGETS hb-view
    653       RUNTIME DESTINATION bin
    654     )
    655 
    656     install(TARGETS hb-shape
    657       RUNTIME DESTINATION bin
    658     )
    659 
    660     install(TARGETS hb-ot-shape-closure
    661       RUNTIME DESTINATION bin
    662     )
    663   endif ()
    664   if (HB_HAVE_GOBJECT)
    665     install(TARGETS harfbuzz-gobject
    666       ARCHIVE DESTINATION lib
    667       LIBRARY DESTINATION lib
    668       RUNTIME DESTINATION bin
    669     )
    670     if (HB_HAVE_INTROSPECTION)
    671       if("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
    672         set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
    673       else ()
    674         set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
    675       endif ()
    676 
    677       install(FILES "${hb_libpath}/HarfBuzz-0.0.gir"
    678         DESTINATION share/gir-1.0
    679         )
    680 
    681       install(FILES "${hb_libpath}/HarfBuzz-0.0.typelib"
    682         DESTINATION lib/girepository-1.0
    683         )
    684     endif ()
    685   endif ()
    686 endif ()
    687 
    688 # Needs to come last so that variables defined above are passed to
    689 # subdirectories.
    690 add_subdirectory(test)
    691