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