diff --git a/.circleci/config.yml b/.circleci/config.yml index cd54b659f..f558e6d66 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,7 +25,7 @@ jobs: - image: base/devel steps: - checkout - - run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel + - run: pacman --noconfirm -Syu freetype2 cairo icu gettext gobject-introspection gcc gcc-libs glib2 graphite pkg-config ragel python - run: ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 - run: make && (make check || (cat `find -name '*.log'` && false)) @@ -34,7 +34,7 @@ jobs: - image: fedora steps: - checkout - - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config || true + - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python || true - run: NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 - run: mkdir build && cd build && ../configure && make && (make check || (cat `find -name '*.log'` && false)) diff --git a/CMakeLists.txt b/CMakeLists.txt index d75bb58c8..435d4fa54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ if (BUILD_SHARED_LIBS) add_definitions("-DHB_EXTERN=__declspec(dllexport) extern") else () set (CMAKE_CXX_FLAGS "-fvisibility=hidden ${CMAKE_CXX_FLAGS}") - set (CMAKE_C_FLAGS "-fvisibility=hidden ${CMAKE_CXX_FLAGS}") + set (CMAKE_C_FLAGS "-fvisibility=hidden ${CMAKE_C_FLAGS}") add_definitions("-DHB_EXTERN=__attribute__((visibility(\"default\"))) extern") endif () endif () @@ -524,11 +524,19 @@ if (UNIX OR MINGW) link_libraries(-Bsymbolic-functions) # Make sure we don't link to libstdc++ - set (CMAKE_CXX_FLAGS "-fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}") - if (NOT APPLE) - set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") - set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") - set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C) + if (BUILD_SHARED_LIBS AND ( + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR + CMAKE_CXX_COMPILER_ID STREQUAL "GNU" + )) + set (CMAKE_CXX_FLAGS "-fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}") + endif () + set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") + set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") + set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C) + + # No threadsafe statics as we do it ourselves + if (BUILD_SHARED_LIBS) + set (CMAKE_CXX_FLAGS "-fno-threadsafe-statics ${CMAKE_CXX_FLAGS}") endif () endif () @@ -782,22 +790,20 @@ endif () ## Tests if (UNIX OR MINGW) if (BUILD_SHARED_LIBS) - # does some "make" stuff inside - #add_test(NAME check-defs.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-defs.sh) - #set_tests_properties(check-defs.sh PROPERTIES ENVIRONMENT "libs=.") + string(REPLACE ";" " " space_separated_headers "${project_headers}") + add_custom_command(TARGET harfbuzz POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env "headers=${space_separated_headers}" python ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src) add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh) - set_tests_properties(check-symbols.sh PROPERTIES ENVIRONMENT "libs=.") - - if (NOT APPLE) - add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh) - add_test(NAME check-static-inits.sh - COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/CMakeFiles/harfbuzz.dir/src # ugly hack - ) - set_tests_properties(check-libstdc++.sh check-static-inits.sh - PROPERTIES ENVIRONMENT "libs=.") - endif () + add_test(NAME check-static-inits.sh + COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack + ) + add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh) + add_test(NAME check-defs.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-defs.sh) + set_tests_properties(check-symbols.sh check-static-inits.sh check-libstdc++.sh check-defs.sh + PROPERTIES ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src") endif () add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh) diff --git a/configure.ac b/configure.ac index ade962afb..54c5260e8 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,9 @@ if test "x$GCC" = "xyes"; then # Make sure we don't link to libstdc++ CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" + # No threadsafe statics and C++ as we do it ourselves + CXXFLAGS="$CXXFLAGS -fno-threadsafe-statics" + # Assorted warnings CXXFLAGS="$CXXFLAGS -Wcast-align" diff --git a/src/Makefile.am b/src/Makefile.am index 912a98cb0..833d1f956 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -223,21 +223,14 @@ CLEANFILES += $(pkgconfig_DATA) CLEANFILES += harfbuzz.def harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS) - $(AM_V_GEN) (echo EXPORTS; \ - (cat $^ || echo 'hb_ERROR ()' ) | \ - $(EGREP) '^hb_.* \(' | \ - sed -e 's/ (.*//' | \ - LC_ALL=C sort; \ - echo LIBRARY libharfbuzz-0.dll; \ - ) >"$@" - @ ! grep -q hb_ERROR "$@" \ - || ($(RM) "$@"; false) + $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@ GENERATORS = \ gen-arabic-table.py \ gen-indic-table.py \ gen-use-table.py \ + gen-def.py \ $(NULL) EXTRA_DIST += $(GENERATORS) diff --git a/src/check-defs.sh b/src/check-defs.sh index c7eac3551..9b4b7572a 100755 --- a/src/check-defs.sh +++ b/src/check-defs.sh @@ -5,7 +5,6 @@ export LC_ALL test -z "$srcdir" && srcdir=. test -z "$libs" && libs=.libs -test -z "$MAKE" && MAKE=make stat=0 if which nm 2>/dev/null >/dev/null; then @@ -16,26 +15,36 @@ else fi defs="harfbuzz.def" -$MAKE $defs > /dev/null +if ! test -f "$defs"; then + echo "check-defs.sh: '$defs' not found; skipping test" + exit 77 +fi + tested=false for def in $defs; do lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'` - so=$libs/lib${lib}.so + for suffix in so dylib; do + so=$libs/lib${lib}.$suffix + if ! test -f "$so"; then continue; fi - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" - if test -f "$so"; then + # On mac, C symbols are prefixed with _ + if test $suffix = dylib; then prefix="_"; fi - echo "Checking that $so has the same symbol list as $def" - { - echo EXPORTS - echo "$EXPORTED_SYMBOLS" - # cheat: copy the last line from the def file! - tail -n1 "$def" - } | diff "$def" - >&2 || stat=1 + if test -f "$so"; then - tested=true - fi + echo "Checking that $so has the same symbol list as $def" + { + echo EXPORTS + echo "$EXPORTED_SYMBOLS" | sed -e "s/^${prefix}hb/hb/g" + # cheat: copy the last line from the def file! + tail -n1 "$def" + } | diff "$def" - >&2 || stat=1 + + tested=true + fi + done done if ! $tested; then echo "check-defs.sh: libharfbuzz shared library not found; skipping test" diff --git a/src/gen-def.py b/src/gen-def.py new file mode 100755 index 000000000..ad1606ec3 --- /dev/null +++ b/src/gen-def.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import io, os, re, sys + +headers_content = [] +for h in os.environ["headers"].split (' '): + if h.endswith (".h"): + with io.open(h, encoding='utf8') as f: headers_content.append (f.read ()) + +result = ("EXPORTS\n" + + "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))) + + "\nLIBRARY libharfbuzz-0.dll") + +with open (sys.argv[1], "w") as f: f.write (result)