1cmake_minimum_required(VERSION 2.8.0) 2project(harfbuzz) 3 4enable_testing() 5 6## Limit framework build to Xcode generator 7if (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) 16endif () 17 18 19## Disallow in-source builds, as CMake generated make files can collide with autotools ones 20if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") 21 message(FATAL_ERROR 22 " 23In-source builds are not permitted! Make a separate folder for" 24 " building, e.g.," 25 " 26 mkdir build; cd build; cmake .." 27 " 28Before that, remove the files created by this failed run with" 29 " 30 rm -rf CMakeCache.txt CMakeFiles") 31endif () 32 33 34## HarfBuzz build configurations 35option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF) 36option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF) 37option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON) 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) 42endif () 43if (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) 46endif () 47option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF) 48if (HB_BUILD_UTILS) 49 set(HB_HAVE_GLIB ON) 50 set(HB_HAVE_FREETYPE ON) 51endif () 52 53option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF) 54if (HB_HAVE_GOBJECT) 55 set(HB_HAVE_GLIB ON) 56endif () 57 58option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF) 59if (HB_HAVE_INTROSPECTION) 60 set(HB_HAVE_GOBJECT ON) 61 set(HB_HAVE_GLIB ON) 62endif () 63 64include_directories(AFTER 65 ${PROJECT_SOURCE_DIR}/src 66 ${PROJECT_BINARY_DIR}/src 67 ) 68 69add_definitions(-DHAVE_OT) 70add_definitions(-DHAVE_FALLBACK) 71 72if (BUILD_SHARED_LIBS) 73 add_definitions(-DHAVE_ATEXIT) 74endif () 75 76if (MSVC) 77 add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS) 78endif () 79 80if (WIN32 AND NOT MINGW AND BUILD_SHARED_LIBS) 81 add_definitions("-DHB_EXTERN=__declspec(dllexport) extern") 82endif () 83 84 85## Detect if we are running inside a distribution or regular repository folder 86set(IN_HB_DIST FALSE) 87if (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") 91endif () 92 93 94## Extract variables from Makefile files 95# http://stackoverflow.com/a/27630120/1414809 96function (prepend var prefix) 97 set(listVar "") 98 foreach (f ${ARGN}) 99 list(APPEND listVar "${prefix}${f}") 100 endforeach () 101 set(${var} "${listVar}" PARENT_SCOPE) 102endfunction () 103 104function (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) 109endfunction () 110 111file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES) 112file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES) 113file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES) 114 115extract_make_variable(HB_BASE_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/") 116extract_make_variable(HB_BASE_headers ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/") 117extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/") 118extract_make_variable(HB_OT_sources ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/") 119extract_make_variable(HB_OT_headers ${SRCSOURCES} "${PROJECT_SOURCE_DIR}/src/") 120 121if (IN_HB_DIST) 122 set(RAGEL_GENERATED_DIR "${PROJECT_SOURCE_DIR}/src/") 123else () 124 set(RAGEL_GENERATED_DIR "${PROJECT_BINARY_DIR}/src/") 125endif () 126extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES} ${RAGEL_GENERATED_DIR}) 127extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES} ${RAGEL_GENERATED_DIR}) 128 129extract_make_variable(HB_VIEW_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/") 130extract_make_variable(HB_SHAPE_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/") 131extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES} "${PROJECT_SOURCE_DIR}/util/") 132 133extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES} "${PROJECT_SOURCE_DIR}/src/hb-ucdn/") 134 135file(READ configure.ac CONFIGUREAC) 136string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC}) 137set(HB_VERSION ${CMAKE_MATCH_1}) 138set(HB_VERSION_MAJOR ${CMAKE_MATCH_2}) 139set(HB_VERSION_MINOR ${CMAKE_MATCH_3}) 140set(HB_VERSION_MICRO ${CMAKE_MATCH_4}) 141 142 143## Define ragel tasks 144if (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) 164endif () 165 166 167## Generate hb-version.h 168if (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") 178endif () 179 180 181## Define sources and headers of the project 182set(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 191set(project_extra_sources) 192 193set(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 202if (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 216endif () 217 218if (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) 232endif () 233 234if (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}) 240endif () 241 242if (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) 261endif () 262 263if (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) 281endif () 282 283if (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) 296endif () 297 298if (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) 305endif () 306 307if (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) 314endif () 315 316if (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 ) 419endif () 420 421## Atomic ops availability detection 422file(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") 429try_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) 432if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES) 433 add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES) 434endif () 435 436file(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") 445try_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) 448if (HB_HAVE_SOLARIS_ATOMIC_OPS) 449 add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS) 450endif () 451 452 453## Define harfbuzz library 454add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers}) 455target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS}) 456 457## Define harfbuzz-gobject library 458if (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}) 468endif () 469 470# On Windows, g-ir-scanner requires a DLL build in order for it to work 471if (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 () 476endif () 477 478if (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 ) 591endif () 592 593## Additional framework build configs 594if (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}") 604endif () 605 606 607## Additional harfbuzz build artifacts 608if (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) 630endif () 631 632 633## Install 634if (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 () 639endif () 640 641if (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 () 686endif () 687 688# Needs to come last so that variables defined above are passed to 689# subdirectories. 690add_subdirectory(test) 691