Menu

#77 OS X 10.11 with Xcode 8.x clock_gettime problem

open
nobody
None
1
2017-08-21
2017-08-21
ilovezfs
No
==> brew test pngcrush --verbose
==> FAILED
Testing pngcrush
/usr/bin/sandbox-exec -f /tmp/homebrew20170821-96619-1hjjqdq.sb /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby -W0 -I /usr/local/Homebrew/Library/Homebrew -- /usr/local/Homebrew/Library/Homebrew/test.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/pngcrush.rb --verbose
==> /usr/local/Cellar/pngcrush/1.8.12/bin/pngcrush /usr/local/Homebrew/Library/Homebrew/test/support/fixtures/test.png /dev/null
dyld: lazy symbol binding failed: Symbol not found: _clock_gettime
  Referenced from: /usr/local/Cellar/pngcrush/1.8.12/bin/pngcrush
  Expected in: /usr/lib/libSystem.B.dylib

dyld: Symbol not found: _clock_gettime
  Referenced from: /usr/local/Cellar/pngcrush/1.8.12/bin/pngcrush
  Expected in: /usr/lib/libSystem.B.dylib

The test block runs

  test do
    system "#{bin}/pngcrush", test_fixtures("test.png"), "/dev/null"
  end

https://jenkins.brew.sh/job/Homebrew%20Core%20Pull%20Requests/6971/version=el_capitan/console
Duplicated here since that log will eventually be deleted: https://gist.github.com/ilovezfs/9a832e6916f440a0851b2341af9abdb9

macOS 10.12 introduced support for clock_gettime() but when compiling with Xcode 8 (or later) and targeting 10.11, the clock_gettime symbol is now found at configure/compile time but referenced weakly. Running the created binary on 10.11 results in a "dyld: lazy symbol binding failed: Symbol not found: _clock_gettime" error.

Note that this occurs even if the build is performed on an OS X 10.11 host using Xcode 8.x. The current version of Xcode for OS X 10.11 is Xcode 8.2.1.

I can work around this issue with the following hack:

diff --git a/Formula/pngcrush.rb b/Formula/pngcrush.rb
index b770314d2f..ae214d91fb 100644
--- a/Formula/pngcrush.rb
+++ b/Formula/pngcrush.rb
@@ -12,6 +12,12 @@ class Pngcrush < Formula
   end

   def install

+    # dyld: lazy symbol binding failed: Symbol not found: _clock_gettime
+    if MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0"
+      inreplace "Makefile", "-DPNGCRUSH_USE_CLOCK_GETTIME=1",
+                            "-DPNGCRUSH_USE_CLOCK_GETTIME=0"
+    end
+
     system "make", "CC=#{ENV.cc}",
                    "LD=#{ENV.cc}",
                    "CFLAGS=#{ENV.cflags}",

It would be great if this could be addressed with a proper upstream fix though, so that we don't have to work around it in the Homebrew formula.

One solid approach to fixing these sorts of Xcode unitary SDK weak linking issues is here:
https://github.com/pyca/cryptography/commit/b637aec1624e558b0e158064264a2523a4dcba31

Note that there was a small bug in that fix, which required follow-up here:
https://github.com/pyca/cryptography/commit/d026b1b226f97991cbf1994521fd1260eb27a762

An approach leveraging the linker flag -Wl,-no_weak_imports is here:
https://github.com/axboe/fio/pull/309

An approach handling the issue via configure is here:
https://github.com/jsquyres/libfabric/commit/469779935f9995b88a6f486fe3c4c4496989af36

An approach using the availability macros is here:
https://github.com/pyca/cryptography/pull/3354/files

Please let me know if you have any questions or need more information.

Discussion

  • Glenn Randers-Pehrson

    On some platforms it is sufficient to enable "LIBS += -lrt" in the Makefile.

    Does that work on the MacOS/XCode versions that are having trouble?
    I believe that would be a better solution if it works because it will give
    you the high-resolution timing.

     
  • ilovezfs

    ilovezfs - 2017-08-21

    No, unfortunately, that just leads to ld: library not found for -lrt.

     
  • Glenn Randers-Pehrson

    Would you configure ImageMagick on your platform and do
    grep GETTIME config/config.h

     
  • ilovezfs

    ilovezfs - 2017-08-21
    bash-3.2$ grep GETTIME config/config.h
    /* #undef HAVE_CLOCK_GETTIME */
    #define HAVE_GETTIMEOFDAY 1
    bash-3.2$
    
     
  • Glenn Randers-Pehrson

    Well, that indicates that -lrt should work. ImageMagick's configure.ac is heavy reading, but somehow it's finding librt. It uses autoconf

    Check for clock_gettime().

    AC_SEARCH_LIBS(clock_gettime, rt,
    [
    AC_DEFINE([HAVE_CLOCK_GETTIME],[1],[Define to 1 if you have clock_gettime.])
    AC_MSG_CHECKING([whether clock_gettime supports CLOCK_REALTIME])
    AC_COMPILE_IFELSE([
    AC_LANG_PROGRAM(
    [[#include <time.h>]],
    [[clockid_t clockType = CLOCK_REALTIME;]])],
    [
    AC_MSG_RESULT(yes)
    AC_DEFINE([HAVE_CLOCK_REALTIME],[1],
    [Define to 1 if clock_gettime supports CLOCK_REALTIME.])
    ],
    AC_MSG_RESULT(no)
    )
    ],
    [
    AC_CHECK_FUNCS([gettimeofday ftime], [break])
    ]
    )</time.h>

    I don't know exactly how to simplify this and incorporate it into pngcrush's Makefile
    (and I'm not much interested in maintaining configure for pngcrush).

     

    Last edit: Glenn Randers-Pehrson 2017-08-21
  • Zhiming Wang

    Zhiming Wang - 2017-08-21

    clock_gettime(3) is found in libc (/usr/lib/system/libsystem_c.dylib) on macOS 10.12+. There's no seperate librt.

    AC_SEARCH_LIBS(clock_gettime, rt, ...) does not guarantee librt is present. It only attempts to link against librt if clock_gettime isn't available when linking aginast no extra libraries; but since it's already in libc, the -lrt step is simply skipped.

     
  • Glenn Randers-Pehrson

    There's no problem with MacOS 10 on pngcrush. It's the problem of finding clock_gettime
    on older versions. Apparently ImageMagick's scheme finds it but simply adding librt to LIBS doesn't do it for pngcrush.

    Incidentally libpng has the same problem. I think you will find that on MacOS 10, the "timepng" tool gets built but on the older Macs it will be omitted.

     
  • ilovezfs

    ilovezfs - 2017-08-21

    There is no clock_gettime on macOS prior to 10.12.

     

Log in to post a comment.