Thread: BUG #15190: Build configure should have option to disableclock_gettime on MacOS 10.12 and up.

The following bug has been logged on the website:

Bug reference:      15190
Logged by:          Marc Van Olmen
Email address:      marcvanolmen@gmail.com
PostgreSQL version: 10.3
Operating system:   MacOS 10.13
Description:

Steps to reproduce issue.

1. Use MacOS 10.12 or higher. I tested MacOS 10.13 because for latest Xcode
9.3 this is the minimal system.
2. Run the standard configure command and make and make install.
3. It will produce an executable for example ./lib/postgress that use the
function clock_gettime.
4. Trying to run this produced executable on macOS 10.10 or lower will
produce the following error

dyld: Symbol not found: _clock_gettime
  Referenced from:
/Volumes/Checkout/Checkout.app/Contents/Resources/postgres_10/bin/postgres
  Expected in: /usr/lib/libSystem.B.dylib

Proposed solution:

We should have an option that disable to the automatic search for using the
clock_gettime on MacOS 10.12 or higher


Other open source projects have also introduced similar options:

./configure --disable-clock-gettime  

https://github.com/libevent/libevent/issues/399
https://github.com/libevent/libevent/pull/400/files

thanks,

Marc Van Olmen


=?utf-8?q?PG_Bug_reporting_form?= <noreply@postgresql.org> writes:
> 1. Use MacOS 10.12 or higher. I tested MacOS 10.13 because for latest Xcode
> 9.3 this is the minimal system.
> 2. Run the standard configure command and make and make install.
> 3. It will produce an executable for example ./lib/postgress that use the
> function clock_gettime.
> 4. Trying to run this produced executable on macOS 10.10 or lower will
> produce the following error
> dyld: Symbol not found: _clock_gettime

This does not seem like a bug, but user error; or at least, you're
thinking about the problem in the wrong way.  In general, an executable
built on version N of an operating system is not guaranteed to run on
versions before N, because of missing features.  clock_gettime is just one
example of such a feature.  We surely aren't going to introduce configure
options to override every test it makes; but that would be the logical
end result if we proceed as you suggest.  That would be unmaintainable,
and not very usable either --- how would you know which things have to
be disabled to get an executable that works on a desired old OS version?

The right way to proceed is to build in an environment that mimics your
oldest target OS version.  Apple does provide facilities for doing that.
I haven't done it, but IIUC the idea is to install the SDK version
corresponding to your target OS version and then point at that while
building.  See


https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html

particularly this bit:

    Configuring a Makefile-Based Project

    If you have a makefile-based project, you can also take advantage of
    SDK-based development, by adding the appropriate options to your
    compile and link commands. Using SDKs in makefile-based projects
    requires GCC 4.0 or later. To choose an SDK, you use the -isysroot
    option with the compiler and the -syslibroot option with the
    linker. Both options require that you specify the full path to the
    desired SDK directory.

Now, if you've tried that and it doesn't work, we could look into
why not.  But I don't think that expecting executables built in a
default environment to be back-portable is going to get anywhere.

            regards, tom lane


Tom

much appreciated for quick response and detailed answer!

I found a solution based on this, so I’m adding that to this thread so anyone in the future can be helped by this.

Because I’m using "configure make" system to build and I’m using a recent released mac I can only run MacOS 10.13, I had to use some XCode legacy information to get this to work. 
Because Apple has a different philosophy for their own products they want you always to build with the latests SDK (more later) but set a in minimum Deployment target.

1. From this source https://github.com/devernay/xcodelegacy I found the right technique on how to change the build options for a configure approach.
2. From this source https://github.com/phracker/MacOSX-SDKs/releases I was able to find a macos 10.9 SDK and install that on my current XCode setup.
3. Then the following configuration allowed me to compile the postgres code on MacOS 10.13 and have it run also on macOS 10.9.


MACOSX_DEPLOYMENT_TARGET=10.9
SDK_ROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
CPU_ARCH=x86_64

./configure PYTHON=${PYTHON_BIN} \
        --with-python \
        --prefix="${POSTGRES_DEST_BUILD_DIR}" \
        --enable-thread-safety \
        --with-includes="${CHECKOUT_PROJECT_DIR}/build_openssl/include" \
        --with-libraries="${CHECKOUT_PROJECT_DIR}/build_openssl/lib" \
        --with-bonjour \
        --with-pgport=5507 \
        --with-openssl \
        CFLAGS="-arch ${CPU_ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -isysroot ${SDK_ROOT}" \
        CXXFLAGS="-arch ${CPU_ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -isysroot ${SDK_ROOT}" \
        LDFLAGS="-arch ${CPU_ARCH}" \
        LD="-arch ${CPU_ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}  -isysroot ${SDK_ROOT}"


This fixes the issues I was having and now it won’t use the clock_gettime function, because in that SDK it isn’t in the headers file.

Regarding Apple SDK based development:

I know it is different then other platforms and I understand it is not adopted by other platforms and I understand other building systems don’t take the same approach or don’t want to add extra specific platform build systems.


1. You basically only need the SDK for the platform you are running on, 
2. You can specify the oldest OS you will deploy too. 
3. but there is a catch: the behavior of your app can change depending which SDK you link to also.

So their headers are annotated then with minimum OS requirements for newly introduced functions.

Regarding clock_gettime

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h

#if !defined(_DARWIN_FEATURE_CLOCK_GETTIME) || _DARWIN_FEATURE_CLOCK_GETTIME != 0
#if __DARWIN_C_LEVEL >= 199309L
#if __has_feature(enumerator_attributes)
#define __CLOCK_AVAILABILITY __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
#else
#define __CLOCK_AVAILABILITY
#endif

typedef enum {
_CLOCK_REALTIME __CLOCK_AVAILABILITY = 0,
#define CLOCK_REALTIME _CLOCK_REALTIME
_CLOCK_MONOTONIC __CLOCK_AVAILABILITY = 6,
#define CLOCK_MONOTONIC _CLOCK_MONOTONIC
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
_CLOCK_MONOTONIC_RAW __CLOCK_AVAILABILITY = 4,
#define CLOCK_MONOTONIC_RAW _CLOCK_MONOTONIC_RAW
_CLOCK_MONOTONIC_RAW_APPROX __CLOCK_AVAILABILITY = 5,
#define CLOCK_MONOTONIC_RAW_APPROX _CLOCK_MONOTONIC_RAW_APPROX
_CLOCK_UPTIME_RAW __CLOCK_AVAILABILITY = 8,
#define CLOCK_UPTIME_RAW _CLOCK_UPTIME_RAW
_CLOCK_UPTIME_RAW_APPROX __CLOCK_AVAILABILITY = 9,
#define CLOCK_UPTIME_RAW_APPROX _CLOCK_UPTIME_RAW_APPROX
#endif
_CLOCK_PROCESS_CPUTIME_ID __CLOCK_AVAILABILITY = 12,
#define CLOCK_PROCESS_CPUTIME_ID _CLOCK_PROCESS_CPUTIME_ID
_CLOCK_THREAD_CPUTIME_ID __CLOCK_AVAILABILITY = 16
#define CLOCK_THREAD_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID
} clockid_t;

__CLOCK_AVAILABILITY
int clock_getres(clockid_t __clock_id, struct timespec *__res);

__CLOCK_AVAILABILITY
int clock_gettime(clockid_t __clock_id, struct timespec *__tp);

And the compiler can then throw an error/warning if you are trying to use a function that is above your minimum deployment.
But you can also decide at runtime what functions to use, by wrapping your function calls into blocks that check for the OS version you are running on.

regards and thanks for your support again.

Marc


On May 8, 2018, at 3:10 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

PG Bug reporting form <noreply@postgresql.org> writes:
1. Use MacOS 10.12 or higher. I tested MacOS 10.13 because for latest Xcode
9.3 this is the minimal system.
2. Run the standard configure command and make and make install.
3. It will produce an executable for example ./lib/postgress that use the
function clock_gettime.
4. Trying to run this produced executable on macOS 10.10 or lower will
produce the following error
dyld: Symbol not found: _clock_gettime

This does not seem like a bug, but user error; or at least, you're
thinking about the problem in the wrong way.  In general, an executable
built on version N of an operating system is not guaranteed to run on
versions before N, because of missing features.  clock_gettime is just one
example of such a feature.  We surely aren't going to introduce configure
options to override every test it makes; but that would be the logical
end result if we proceed as you suggest.  That would be unmaintainable,
and not very usable either --- how would you know which things have to
be disabled to get an executable that works on a desired old OS version?

The right way to proceed is to build in an environment that mimics your
oldest target OS version.  Apple does provide facilities for doing that.
I haven't done it, but IIUC the idea is to install the SDK version
corresponding to your target OS version and then point at that while
building.  See

https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html

particularly this bit:

   Configuring a Makefile-Based Project

   If you have a makefile-based project, you can also take advantage of
   SDK-based development, by adding the appropriate options to your
   compile and link commands. Using SDKs in makefile-based projects
   requires GCC 4.0 or later. To choose an SDK, you use the -isysroot
   option with the compiler and the -syslibroot option with the
   linker. Both options require that you specify the full path to the
   desired SDK directory.

Now, if you've tried that and it doesn't work, we could look into
why not.  But I don't think that expecting executables built in a
default environment to be back-portable is going to get anywhere.

regards, tom lane