• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1cmake_minimum_required(VERSION 3.12)
2project(harfbuzz)
3
4message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.")
5
6## Limit framework build to Xcode generator
7if (BUILD_FRAMEWORK)
8  # for a framework build on macOS, use:
9  # cmake -DBUILD_FRAMEWORK=ON -Bbuild -H. -GXcode && cmake --build build
10  if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
11    message(FATAL_ERROR
12      "You should use Xcode generator with BUILD_FRAMEWORK enabled")
13  endif ()
14  set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
15  set (CMAKE_MACOSX_RPATH ON)
16  set (BUILD_SHARED_LIBS ON)
17endif ()
18
19
20## Disallow in-source builds, as CMake generated make files can collide with autotools ones
21if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
22  message(FATAL_ERROR
23    "
24In-source builds are not permitted!  Make a separate folder for"
25    " building, e.g.,"
26    "
27  mkdir build; cd build; cmake .."
28    "
29Before that, remove the files created by this failed run with"
30    "
31  rm -rf CMakeCache.txt CMakeFiles")
32endif ()
33
34
35## HarfBuzz build configurations
36option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
37option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
38option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
39option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
40if (TARGET freetype)
41  set (HB_HAVE_FREETYPE ON)
42  add_definitions(-DHAVE_FREETYPE=1)
43endif ()
44if (APPLE)
45  option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON)
46  set (CMAKE_MACOSX_RPATH ON)
47endif ()
48if (WIN32)
49  option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
50  option(HB_HAVE_GDI "Enable GDI integration helpers on Windows" OFF)
51  option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF)
52endif ()
53option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF)
54if (HB_BUILD_UTILS)
55  set (HB_HAVE_GLIB ON)
56  set (HB_HAVE_FREETYPE ON)
57endif ()
58
59option(HB_BUILD_SUBSET "Build harfbuzz-subset" ON)
60
61option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
62if (HB_HAVE_GOBJECT)
63  set (HB_HAVE_GLIB ON)
64endif ()
65
66option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF)
67if (HB_HAVE_INTROSPECTION)
68  set (HB_HAVE_GOBJECT ON)
69  set (HB_HAVE_GLIB ON)
70endif ()
71
72include_directories(AFTER
73  ${PROJECT_SOURCE_DIR}/src
74  ${PROJECT_BINARY_DIR}/src
75)
76
77# We need PYTHON_EXECUTABLE to be set for running the tests...
78include (FindPythonInterp)
79
80## Functions and headers
81include (CheckFunctionExists)
82include (CheckIncludeFile)
83include (CheckIncludeFiles)
84macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
85  foreach (func_name ${ARGN})
86    string(TOUPPER ${func_name} definition_to_add)
87    check_function_exists(${func_name} HAVE_${definition_to_add})
88    if (${HAVE_${definition_to_add}})
89      add_definitions(-DHAVE_${definition_to_add})
90    endif ()
91  endforeach ()
92endmacro ()
93if (UNIX)
94  list(APPEND CMAKE_REQUIRED_LIBRARIES m)
95endif ()
96check_funcs(atexit mprotect sysconf getpagesize mmap isatty)
97check_include_file(unistd.h HAVE_UNISTD_H)
98if (${HAVE_UNISTD_H})
99  add_definitions(-DHAVE_UNISTD_H)
100endif ()
101check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
102if (${HAVE_SYS_MMAN_H})
103  add_definitions(-DHAVE_SYS_MMAN_H)
104endif ()
105check_include_file(stdbool.h HAVE_STDBOOL_H)
106if (${HAVE_STDBOOL_H})
107  add_definitions(-DHAVE_STDBOOL_H)
108endif ()
109
110# These will be used while making pkg-config .pc files
111set(PC_REQUIRES_PRIV "")
112set(PC_LIBS_PRIV "")
113
114if (NOT MSVC)
115  set(THREADS_PREFER_PTHREAD_FLAG ON)
116  find_package(Threads)
117  if (CMAKE_USE_PTHREADS_INIT)
118    add_definitions("-DHAVE_PTHREAD")
119    list(APPEND THIRD_PARTY_LIBS Threads::Threads)
120    list(APPEND PC_LIBS_PRIV -pthread)
121  endif ()
122endif ()
123
124if (MSVC)
125  add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
126endif ()
127
128
129## Detect if we are running inside a distribution or regular repository folder
130# if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog")
131#   # perhaps we are on dist directory
132#   set (IN_HB_DIST TRUE)
133#   #set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
134# endif ()
135
136
137## Extract variables from Makefile files
138function (extract_make_variable variable makefile_source)
139  string(REGEX MATCH "${variable} = ([^$]+)\\$" temp "${makefile_source}")
140  string(REGEX MATCHALL "[^ \n\t\\]+" listVar "${CMAKE_MATCH_1}")
141  set (${variable} ${listVar} PARENT_SCOPE)
142endfunction ()
143
144# https://stackoverflow.com/a/27630120
145function (add_prefix_to_list var prefix)
146  set (listVar "")
147  foreach (f ${${var}})
148    list(APPEND listVar "${prefix}${f}")
149  endforeach ()
150  set (${var} "${listVar}" PARENT_SCOPE)
151endfunction ()
152
153file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
154file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
155
156extract_make_variable(HB_BASE_headers ${SRCSOURCES})
157add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/")
158
159extract_make_variable(HB_SUBSET_sources ${SRCSOURCES})
160add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
161
162extract_make_variable(HB_SUBSET_headers ${SRCSOURCES})
163add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/")
164
165extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES})
166#if (IN_HB_DIST)
167  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
168#else ()
169#  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
170#endif ()
171
172extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
173add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/")
174extract_make_variable(HB_SHAPE_sources ${UTILSOURCES})
175add_prefix_to_list(HB_SHAPE_sources "${PROJECT_SOURCE_DIR}/util/")
176extract_make_variable(HB_SUBSET_CLI_sources ${UTILSOURCES})
177add_prefix_to_list(HB_SUBSET_CLI_sources "${PROJECT_SOURCE_DIR}/util/")
178extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES})
179add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/")
180
181
182file(READ configure.ac CONFIGUREAC)
183string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC})
184set (HB_VERSION ${CMAKE_MATCH_1})
185set (HB_VERSION_MAJOR ${CMAKE_MATCH_2})
186set (HB_VERSION_MINOR ${CMAKE_MATCH_3})
187set (HB_VERSION_MICRO ${CMAKE_MATCH_4})
188
189## Define sources and headers of the project
190set (project_sources ${PROJECT_SOURCE_DIR}/src/harfbuzz.cc) # use amalgam source
191set (subset_project_sources ${HB_SUBSET_sources})
192set (project_extra_sources)
193set (project_headers ${HB_BASE_headers})
194set (subset_project_headers ${HB_SUBSET_headers})
195
196## Find and include needed header folders and libraries
197if (HB_HAVE_FREETYPE AND NOT TARGET freetype)
198  include (FindFreetype)
199  if (NOT FREETYPE_FOUND)
200    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")
201  endif ()
202
203  list(APPEND THIRD_PARTY_LIBS ${FREETYPE_LIBRARIES})
204  include_directories(AFTER ${FREETYPE_INCLUDE_DIRS})
205  add_definitions(-DHAVE_FREETYPE=1)
206
207  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h)
208
209  # So check_funcs can find its headers
210  set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS})
211  set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES})
212
213  check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
214endif ()
215
216if (HB_HAVE_FREETYPE)
217  list(APPEND PC_REQUIRES_PRIV "freetype2 >= 12.0.6")
218endif ()
219
220if (HB_HAVE_GRAPHITE2)
221  add_definitions(-DHAVE_GRAPHITE2)
222
223  find_path(GRAPHITE2_INCLUDE_DIR graphite2/Font.h)
224  find_library(GRAPHITE2_LIBRARY graphite2)
225
226  include_directories(${GRAPHITE2_INCLUDE_DIR})
227
228  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h)
229
230  list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
231
232  list(APPEND PC_REQUIRES_PRIV "graphite2 >= 1.2.0")
233
234  mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
235endif ()
236
237if (HB_HAVE_GLIB)
238  add_definitions(-DHAVE_GLIB)
239
240  # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindGLIB.cmake
241  find_package(PkgConfig)
242  pkg_check_modules(PC_GLIB QUIET glib-2.0)
243
244  find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
245  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)
246  find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
247
248  include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR})
249
250  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h)
251
252  list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
253
254  list(APPEND PC_REQUIRES_PRIV "glib-2.0 >= 2.19.1")
255
256  mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR)
257endif ()
258
259if (HB_HAVE_ICU)
260  add_definitions(-DHAVE_ICU)
261
262  # https://github.com/WebKit/webkit/blob/fdd7733f2f30eab7fe096a9791f98c60f62f49c0/Source/cmake/FindICU.cmake
263  find_package(PkgConfig)
264  pkg_check_modules(PC_ICU QUIET icu-uc)
265
266  find_path(ICU_INCLUDE_DIR NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR})
267  find_library(ICU_LIBRARY NAMES libicuuc cygicuuc cygicuuc32 icuuc HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR})
268
269  include_directories(${ICU_INCLUDE_DIR})
270
271  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
272
273  list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY})
274
275  mark_as_advanced(ICU_INCLUDE_DIR ICU_LIBRARY)
276endif ()
277
278if (APPLE AND HB_HAVE_CORETEXT)
279  # Apple Advanced Typography
280  add_definitions(-DHAVE_CORETEXT)
281
282  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
283
284  if (HB_IOS)
285    find_library(COREFOUNDATION CoreFoundation)
286    if (COREFOUNDATION)
287      list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION})
288      list(APPEND PC_LIBS_PRIV "-framework CoreFoundation")
289    endif ()
290    mark_as_advanced(COREFOUNDATION)
291
292    find_library(CORETEXT CoreText)
293    if (CORETEXT)
294      list(APPEND THIRD_PARTY_LIBS ${CORETEXT})
295      list(APPEND PC_LIBS_PRIV "-framework CoreText")
296    endif ()
297    mark_as_advanced(CORETEXT)
298
299    find_library(COREGRAPHICS CoreGraphics)
300    if (COREGRAPHICS)
301      list(APPEND THIRD_PARTY_LIBS ${COREGRAPHICS})
302      list(APPEND PC_LIBS_PRIV "-framework CoreGraphics")
303    endif ()
304    mark_as_advanced(COREGRAPHICS)
305  else ()
306    find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
307    if (APPLICATION_SERVICES_FRAMEWORK)
308      list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
309      list(APPEND PC_LIBS_PRIV "-framework ApplicationServices")
310    endif ()
311
312    mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
313  endif ()
314endif ()
315
316if (WIN32 AND HB_HAVE_GDI)
317  add_definitions(-DHAVE_GDI)
318  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
319  list(APPEND THIRD_PARTY_LIBS gdi32)
320  list(APPEND PC_LIBS_PRIV -lgdi32)
321endif ()
322
323if (WIN32 AND HB_HAVE_UNISCRIBE)
324  add_definitions(-DHAVE_UNISCRIBE)
325  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
326  list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
327  list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4)
328endif ()
329
330if (WIN32 AND HB_HAVE_DIRECTWRITE)
331  if (CMAKE_VERSION VERSION_GREATER 3.12)
332    check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H LANGUAGE CXX)
333  else ()
334    check_include_files("windows.h;dwrite_1.h" HAVE_DWRITE_1_H)
335  endif ()
336  if (NOT HAVE_DWRITE_1_H)
337    message(FATAL_ERROR "DirectWrite was enabled explicitly, but required header is missing")
338  endif ()
339  add_definitions(-DHAVE_DIRECTWRITE)
340  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
341endif ()
342
343if (HB_HAVE_GOBJECT)
344  add_definitions(-DHAVE_GOBJECT)
345  include (FindPerl)
346
347  # Use the hints from glib-2.0.pc to find glib-mkenums
348  find_package(PkgConfig)
349  pkg_check_modules(PC_GLIB QUIET glib-2.0)
350  find_program(GLIB_MKENUMS glib-mkenums
351    HINTS ${PC_glib_mkenums}
352  )
353  set (GLIB_MKENUMS_CMD)
354
355  if (WIN32 AND NOT MINGW)
356    # In Visual Studio builds, shebang lines are not supported
357    # in the standard cmd.exe shell that we use, so we need to
358    # first determine whether glib-mkenums is a Python or PERL
359    # script
360    execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}" --version
361      RESULT_VARIABLE GLIB_MKENUMS_PYTHON
362      OUTPUT_QUIET ERROR_QUIET
363    )
364    if (GLIB_MKENUMS_PYTHON EQUAL 0)
365      message("${GLIB_MKENUMS} is a Python script.")
366      set (GLIB_MKENUMS_CMD "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}")
367    else ()
368      execute_process(COMMAND "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}" --version
369        RESULT_VARIABLE GLIB_MKENUMS_PERL
370        OUTPUT_QUIET ERROR_QUIET
371      )
372      if (GLIB_MKENUMS_PERL EQUAL 0)
373        message("${GLIB_MKENUMS} is a PERL script.")
374        set (GLIB_MKENUMS_CMD "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}")
375      endif ()
376      if (NOT GLIB_MKENUMS_PERL EQUAL 0 AND NOT GLIB_MKENUMS_PYTHON EQUAL 0)
377        message(FATAL_ERROR "Unable to determine type of glib-mkenums script")
378      endif ()
379    endif ()
380  else ()
381    set (GLIB_MKENUMS_CMD "${GLIB_MKENUMS}")
382  endif ()
383  if (NOT GLIB_MKENUMS_CMD)
384    message(FATAL_ERROR "HB_HAVE_GOBJECT was set, but we failed to find glib-mkenums, which is required")
385  endif ()
386
387  pkg_check_modules(PC_GOBJECT QUIET gobject-2.0)
388
389  find_library(GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS})
390  find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0)
391
392  include_directories(${GOBJECTCONFIG_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR})
393  mark_as_advanced(GOBJECT_LIBRARIES GOBJECT_INCLUDE_DIR)
394
395  list(APPEND hb_gobject_sources ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.cc)
396  list(APPEND hb_gobject_gen_sources
397    ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
398  )
399  list(APPEND hb_gobject_structs_headers
400    ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.h
401  )
402  list(APPEND hb_gobject_headers
403    ${PROJECT_SOURCE_DIR}/src/hb-gobject.h
404    ${hb_gobject_structs_headers}
405  )
406  list(APPEND hb_gobject_gen_headers
407    ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
408  )
409
410  add_custom_command(
411    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
412    COMMAND ${GLIB_MKENUMS_CMD}
413      --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
414      --identifier-prefix hb_
415      --symbol-prefix hb_gobject
416      ${hb_gobject_structs_headers}
417      ${project_headers}
418      > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp
419    COMMAND "${CMAKE_COMMAND}"
420      "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp"
421      "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h"
422      -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
423    DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl
424      ${hb_gobject_header}
425      ${project_headers}
426  )
427
428  add_custom_command(
429    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc
430    COMMAND ${GLIB_MKENUMS_CMD}
431      --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
432      --identifier-prefix hb_
433      --symbol-prefix hb_gobject
434      ${hb_gobject_header}
435      ${project_headers}
436      > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp
437    COMMAND "${CMAKE_COMMAND}"
438      "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp"
439      "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc"
440      -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake
441    DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl
442      ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h
443      ${hb_gobject_header}
444      ${project_headers}
445  )
446endif ()
447
448
449## Define harfbuzz library
450add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
451target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
452target_include_directories(harfbuzz PUBLIC
453                           "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
454                           "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz>")
455if (HB_HAVE_FREETYPE AND TARGET freetype)
456  target_link_libraries(harfbuzz freetype)
457endif ()
458
459
460## Define harfbuzz-icu library
461if (HB_HAVE_ICU)
462  add_library(harfbuzz-icu ${PROJECT_SOURCE_DIR}/src/hb-icu.cc ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
463  add_dependencies(harfbuzz-icu harfbuzz)
464  target_link_libraries(harfbuzz-icu harfbuzz ${THIRD_PARTY_LIBS})
465
466  if (BUILD_SHARED_LIBS)
467    set_target_properties(harfbuzz harfbuzz-icu PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
468  endif ()
469endif ()
470
471
472## Define harfbuzz-subset library
473if (HB_BUILD_SUBSET)
474  add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
475  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h)
476  add_dependencies(harfbuzz-subset harfbuzz)
477  target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
478
479  if (BUILD_SHARED_LIBS)
480    set_target_properties(harfbuzz harfbuzz-subset PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
481  endif ()
482endif ()
483
484if (UNIX OR MINGW)
485  # Make symbols link locally
486  include (CheckCXXCompilerFlag)
487  CHECK_CXX_COMPILER_FLAG(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
488  if (CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
489    link_libraries(-Bsymbolic-functions)
490  endif ()
491
492  # As of CMake 3.0.0, the compiler id for Apple-provided Clang is now "AppleClang";
493  # thus we use MATCHES instead of STREQUAL to include either regular Clang or AppleClang
494  if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
495    # Make sure we don't link to libstdc++
496    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
497    set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
498    set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
499    set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
500    if (HB_BUILD_SUBSET)
501      set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
502    endif ()
503
504    # No threadsafe statics as we do it ourselves
505    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
506  endif ()
507
508  CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
509  if (COMPILER_SUPPORTS_CXX11)
510    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
511  else()
512    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
513  endif()
514endif ()
515
516
517## Define harfbuzz-gobject library
518if (HB_HAVE_GOBJECT)
519  add_library(harfbuzz-gobject
520    ${hb_gobject_sources}
521    ${hb_gobject_gen_sources}
522    ${hb_gobject_headers}
523    ${hb_gobject_gen_headers}
524  )
525  include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
526  add_dependencies(harfbuzz-gobject harfbuzz)
527  target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
528
529  if (BUILD_SHARED_LIBS)
530    set_target_properties(harfbuzz-gobject PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
531  endif ()
532endif ()
533
534if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW)
535  add_definitions("-DHB_DLL_EXPORT")
536endif ()
537
538# On Windows, g-ir-scanner requires a DLL build in order for it to work
539if (WIN32)
540  if (NOT BUILD_SHARED_LIBS)
541    message("Building introspection files on Windows requires BUILD_SHARED_LIBS to be enabled.")
542    set (HB_HAVE_INTROSPECTION OFF)
543  endif ()
544endif ()
545
546if (HB_HAVE_INTROSPECTION)
547  find_package(PkgConfig)
548  pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
549
550  find_program(G_IR_SCANNER g-ir-scanner
551    HINTS ${PC_g_ir_scanner}
552  )
553
554  find_program(G_IR_COMPILER g-ir-compiler
555    HINTS ${PC_g_ir_compiler}
556  )
557
558  if (WIN32 AND NOT MINGW)
559    # Note that since we already enable HB_HAVE_GOBJECT
560    # we would already have PYTHON_EXECUTABLE handy
561    set (G_IR_SCANNER_CMD "${PYTHON_EXECUTABLE}" "${G_IR_SCANNER}")
562  else ()
563    set (G_IR_SCANNER_CMD "${G_IR_SCANNER}")
564  endif ()
565
566  # We need to account for the varying output directories
567  # when we build using Visual Studio projects
568  if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
569    set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
570  else ()
571    set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
572  endif ()
573
574  # Get the CFlags that we used to build HarfBuzz/HarfBuzz-GObject
575  set (hb_defines_cflags "")
576  foreach (hb_cflag ${hb_cflags})
577    list(APPEND hb_defines_cflags "-D${hb_cflag}")
578  endforeach (hb_cflag)
579
580  # Get the other dependent libraries we used to build HarfBuzz/HarfBuzz-GObject
581  set (extra_libs "")
582  foreach (extra_lib ${THIRD_PARTY_LIBS})
583    # We don't want the .lib extension here...
584    string(REPLACE ".lib" "" extra_lib_stripped "${extra_lib}")
585    list(APPEND extra_libs "--extra-library=${extra_lib_stripped}")
586  endforeach ()
587
588  set (introspected_sources)
589  foreach (f
590    ${project_headers}
591    ${project_sources}
592    ${hb_gobject_gen_sources}
593    ${hb_gobject_gen_headers}
594    ${hb_gobject_sources}
595    ${hb_gobject_headers}
596  )
597    if (WIN32)
598      # Nasty issue: We need to make drive letters lower case,
599      # otherwise g-ir-scanner won't like it and give us a bunch
600      # of invalid items and unresolved types...
601      STRING(SUBSTRING "${f}" 0 1 drive)
602      STRING(SUBSTRING "${f}" 1 -1 path)
603      if (drive MATCHES "[A-Z]")
604        STRING(TOLOWER ${drive} drive_lower)
605        list(APPEND introspected_sources "${drive_lower}${path}")
606      else ()
607        list(APPEND introspected_sources "${f}")
608      endif ()
609    else ()
610      list(APPEND introspected_sources "${f}")
611    endif ()
612  endforeach ()
613
614  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list)
615  foreach (s ${introspected_sources})
616    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list "${s}\n")
617  endforeach ()
618
619  # Finally, build the introspection files...
620  add_custom_command(
621    TARGET harfbuzz-gobject
622    POST_BUILD
623    COMMAND ${G_IR_SCANNER_CMD}
624      --warn-all --no-libtool --verbose
625      --namespace=HarfBuzz
626      --nsversion=0.0
627      --symbol-prefix=hb
628      --symbol-prefix=hb_gobject
629      --identifier-prefix=hb_
630      --include GObject-2.0
631      --pkg-export=harfbuzz-gobject
632      --c-include=hb-gobject.h
633      --cflags-begin
634      -I${PROJECT_SOURCE_DIR}/src
635      -I${PROJECT_BINARY_DIR}/src
636      ${hb_includedir_cflags}
637      ${hb_defines_cflags}
638      -DHB_H
639      -DHB_H_IN
640      -DHB_OT_H
641      -DHB_OT_H_IN
642      -DHB_AAT_H
643      -DHB_AAT_H_IN
644      -DHB_GOBJECT_H
645      -DHB_GOBJECT_H_IN
646      -DHB_EXTERN=
647      --cflags-end
648      --library=harfbuzz-gobject
649      --library=harfbuzz
650      -L${hb_libpath}
651      ${extra_libs}
652      --filelist ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list
653      -o ${hb_libpath}/HarfBuzz-0.0.gir
654    DEPENDS harfbuzz-gobject harfbuzz ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list
655  )
656
657  add_custom_command(
658    TARGET harfbuzz-gobject
659    POST_BUILD
660    COMMAND "${G_IR_COMPILER}"
661      --verbose --debug
662      --includedir ${CMAKE_CURRENT_BINARY_DIR}
663      ${hb_libpath}/HarfBuzz-0.0.gir
664      -o ${hb_libpath}/HarfBuzz-0.0.typelib
665    DEPENDS ${hb_libpath}/HarfBuzz-0.0.gir harfbuzz-gobject
666  )
667endif ()
668
669
670## Additional framework build configs
671if (BUILD_FRAMEWORK)
672  set (CMAKE_MACOSX_RPATH ON)
673  set_target_properties(harfbuzz PROPERTIES
674    FRAMEWORK TRUE
675    PUBLIC_HEADER "${project_headers}"
676    XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
677  )
678  set (MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz")
679  set (MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}")
680  set (MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}")
681endif ()
682
683
684## Additional harfbuzz build artifacts
685if (HB_BUILD_UTILS)
686  # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindCairo.cmake
687  find_package(PkgConfig)
688  pkg_check_modules(PC_CAIRO QUIET cairo)
689
690  find_path(CAIRO_INCLUDE_DIRS NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo)
691  find_library(CAIRO_LIBRARIESNAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS})
692
693  add_definitions("-DPACKAGE_NAME=\"HarfBuzz\"")
694  add_definitions("-DPACKAGE_VERSION=\"${HB_VERSION}\"")
695  include_directories(${CAIRO_INCLUDE_DIRS})
696
697  add_executable(hb-view ${HB_VIEW_sources})
698  target_link_libraries(hb-view harfbuzz ${CAIRO_LIBRARIESNAMES})
699
700  add_executable(hb-shape ${HB_SHAPE_sources})
701  target_link_libraries(hb-shape harfbuzz)
702
703  add_executable(hb-subset ${HB_SUBSET_CLI_sources})
704  target_link_libraries(hb-subset harfbuzz harfbuzz-subset)
705
706  add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
707  target_link_libraries(hb-ot-shape-closure harfbuzz)
708
709  mark_as_advanced(CAIRO_INCLUDE_DIRS CAIRO_LIBRARIESNAMES)
710endif ()
711
712
713## Install
714include (GNUInstallDirs)
715
716if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
717  install(FILES ${project_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
718  if (HB_HAVE_GOBJECT)
719    install(FILES ${hb_gobject_headers} ${hb_gobject_gen_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz)
720  endif ()
721endif ()
722
723# get these variables in the required format
724list(REMOVE_DUPLICATES PC_REQUIRES_PRIV)
725string(REPLACE ";" ", " PC_REQUIRES_PRIV "${PC_REQUIRES_PRIV}")
726list(REMOVE_DUPLICATES PC_LIBS_PRIV)
727string(REPLACE ";" " " PC_LIBS_PRIV "${PC_LIBS_PRIV}")
728
729# Macro to write pkg-config .pc configuration files
730macro ( make_pkgconfig_pc_file name )
731  file(READ "${PROJECT_SOURCE_DIR}/src/${name}.pc.in" FSTR)
732
733  string(REPLACE "%prefix%" "${CMAKE_INSTALL_PREFIX}" FSTR ${FSTR})
734  string(REPLACE "%exec_prefix%" "\${prefix}" FSTR ${FSTR})
735
736  if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
737    string(REPLACE "%includedir%" "${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
738  else ()
739    string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" FSTR ${FSTR})
740  endif ()
741
742  if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
743    string(REPLACE "%libdir%" "${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
744  else ()
745    string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}" FSTR ${FSTR})
746  endif ()
747
748  string(REPLACE "%VERSION%" "${HB_VERSION}" FSTR ${FSTR})
749  string(REPLACE "%requires_private%" "${PC_REQUIRES_PRIV}" FSTR ${FSTR})
750  string(REPLACE "%libs_private%" "${PC_LIBS_PRIV}" FSTR ${FSTR})
751
752  file(WRITE "${PROJECT_BINARY_DIR}/${name}.pc" ${FSTR})
753
754  install(
755    FILES "${PROJECT_BINARY_DIR}/${name}.pc"
756    DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
757    COMPONENT pkgconfig
758  )
759endmacro ( make_pkgconfig_pc_file )
760
761if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
762  install(TARGETS harfbuzz
763    EXPORT harfbuzzConfig
764    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
765    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
766    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
767    FRAMEWORK DESTINATION Library/Frameworks
768  )
769  make_pkgconfig_pc_file("harfbuzz")
770  install(EXPORT harfbuzzConfig
771      NAMESPACE harfbuzz::
772      DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
773  )
774  if (HB_HAVE_ICU)
775    install(TARGETS harfbuzz-icu
776      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
777      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
778      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
779      FRAMEWORK DESTINATION Library/Frameworks
780    )
781    make_pkgconfig_pc_file("harfbuzz-icu")
782  endif ()
783  if (HB_BUILD_SUBSET)
784    install(TARGETS harfbuzz-subset
785      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
786    )
787    make_pkgconfig_pc_file("harfbuzz-subset")
788  endif ()
789  if (HB_BUILD_UTILS)
790    if (WIN32 AND BUILD_SHARED_LIBS)
791      install(TARGETS harfbuzz-subset
792        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
793      )
794    endif ()
795    install(TARGETS hb-view
796      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
797    )
798    install(TARGETS hb-subset
799      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
800    )
801
802    install(TARGETS hb-shape
803      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
804    )
805
806    install(TARGETS hb-ot-shape-closure
807      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
808    )
809  endif ()
810  if (HB_HAVE_GOBJECT)
811    install(TARGETS harfbuzz-gobject
812      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
813      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
814      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
815    )
816    make_pkgconfig_pc_file("harfbuzz-gobject")
817    if (HB_HAVE_INTROSPECTION)
818      if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
819        set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
820      else ()
821        set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>")
822      endif ()
823
824      install(FILES "${hb_libpath}/HarfBuzz-0.0.gir"
825        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gir-1.0
826      )
827
828      install(FILES "${hb_libpath}/HarfBuzz-0.0.typelib"
829        DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0
830      )
831    endif ()
832  endif ()
833endif ()
834