2013-08-21

Установка OpenJDK 7 на Mac OS X 10.6.8, часть 2

Пока думал над вчерашней проблемой сборки JDK, в голову пришла следующая идея. Каждый фрагмент native-кода, не компилирующийся на 10.6 Snow Leopard, можно обернуть следующим образом:
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070
 /*
  * 10.7+ Implementation goes here
  */
#else // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#define __MAC_OS_X_VERSION_MAJOR__ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ / 100
#define __MAC_OS_X_VERSION_MINOR__ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ / 10 % 10
#define __MAC_OS_X_VERSION_UPDATE__ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ % 10
 /*
  * If the class is not found, java.lang.NoClassDefFoundError will be thrown.
  */
 const jclass throwable = (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
 if (throwable != NULL) {
  char message[64];
  sprintf(message, "Not implemented in Mac OS X %d.%d.%d", __MAC_OS_X_VERSION_MAJOR__, __MAC_OS_X_VERSION_MINOR__, __MAC_OS_X_VERSION_UPDATE__);
  (*env)->ThrowNew(env, throwable, message);
 }
#endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
Это позволит по крайней мере собрать код (а заодно и оценить объём native-кода, опирающегося на специфичное для 10.7 API).

Второй плюс заключается в том, что на этапе исполнения мы получим простое и понятное UnsupportedOperationException вместо аварийного останова JVM.

2013-08-20

Установка OpenJDK 7 на Mac OS X 10.6.8

... или почему не стоит этого делать.

Как известно, есть добрый человек, который всем страждущим облегчает задачу сборки OpenJDK. Также известно, что с некоторых пор он по неясной причине перестал поддерживать процесс сборки OpenJDK 7+ на Mac OS X 10.6.8 (Snow Leopard), с заявлением вроде "собирайте на свой страх и риск".

В общем, попытка собрать OpenJDK 7 из исходного кода привела к следующему:

Building lib:sources/openjdk7/build/macosx-x86_64/lib/lwawt/liblwawt.dylib
Begin parallel compiles: sources/openjdk7/jdk/make/sun/lwawt

sources/openjdk7/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m: In function '__Java_sun_java2d_opengl_CGLLayer_nativeSetScale_block_invoke_1':
sources/openjdk7/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m:224: error: request for member 'contentsScale' in something not a structure or union
make[5]: *** [sources/openjdk7/build/macosx-x86_64/tmp/sun/sun.lwawt/lwawt/obj64/CGLLayer.o] Error 1

sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m: In function '__Java_sun_awt_CGraphicsDevice_nativeGetScaleFactor_block_invoke_1':
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:298: warning: comparison between pointer and integer
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:300: warning: 'NSScreen' may not respond to '-backingScaleFactor'
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:300: warning: (Messages without a matching method signature
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:300: warning: will be assumed to return 'id' and accept
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:300: warning: '...' as arguments.)
sources/openjdk7/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m:300: error: incompatible types in assignment
make[5]: *** [sources/openjdk7/build/macosx-x86_64/tmp/sun/sun.lwawt/lwawt/obj64/CGraphicsDevice.o] Error 1

sources/openjdk7/jdk/src/macosx/native/sun/awt/AWTView.m: In function '__Java_sun_lwawt_macosx_CPlatformView_nativeGetLocationOnScreen_block_invoke_1':
sources/openjdk7/jdk/src/macosx/native/sun/awt/AWTView.m:1337: warning: 'NSWindow' may not respond to '-convertRectToScreen:'
sources/openjdk7/jdk/src/macosx/native/sun/awt/AWTView.m:1337: error: incompatible types in assignment
make[5]: *** [sources/openjdk7/build/macosx-x86_64/tmp/sun/sun.lwawt/lwawt/obj64/AWTView.o] Error 1

Ну и анализ ошибок сборки:
  1.  До 10.7 Lion в классе CALayer (который является суперклассом CGLLayer) отсутствует свойство contentsScale. Соответственно, не будет работать реализация метода AWT sun.java2d.opengl.CGLLayer#nativeSetScale().
  2. До 10.7 Lion в классе NSScreen отсутствует свойство backingScaleFactor. Соответственно, не будет работать реализация метода AWT sun.awt.CGraphicsDevice#nativeGetScaleFactor().
  3. До 10.7 Lion в классе NSWindow отсутствует метод convertRectToScreen(). Соответственно, не будет работать реализация метода AWT sun.lwawt.macosx.CPlatformView#nativeGetLocationOnScreen().
Очевидно, что бинарные сборки JDK 1.7 тоже не стоит устанавливать на 10.6 Snow Leopard, несмотря на многочисленные известные обходные пути с использованием Pacifist или PackageMaker (1, 2). В том маловероятном случае, когда будет вызван один из вышеупомянутых методов AWT, JVM просто завершит работу.

Таким образом, кроме случаев, когда целью установки JDK является чисто серверная разработка (без использования AWT), единственной альтернативой для тех, кто не желает обновляться до 10.7 Lion, будет собрать JDK c поддержкой X11 (sun.awt.X11.XToolkit) вместо стандартного apple.awt.CToolkit.

2013-08-13

Вот чем меня бесят содомиты из компании Apple...

... так это тем, что нихрена не тестируют работу Mac OS X, устновленной на case-sensistive раздел. Несколько дней "мак" работал через пень-колоду. Каждые несколько секунд планировщик пытался запустить /usr/libexec/flashupdater. На деле же файл называется /usr/libexec/FlashUpdater.
P. S. Тем же страдают другие содомиты из компаний Valve и Blizzard, пишущие софт для Mac OS X, разработанной содомитами из компании Apple. Но это, слава б*гу, работе не мешает. Пусть пишут. Юниксоиды хреновы.

2013-08-05

Mac OS X и прелести резервного копирования

Сегодня столкнулся с тем, что Time Machine, при нехватке свободного места на диске, предназначенном для хранения резервных копий, может запросто завершить работу с сообщением об ошибке, оставив на диске "половину бэкапа".

С "половиной бэкапа" стандартными средствами ничего сделать нельзя (ни удалить, ни "дописать").

В общем, меня спасла вот эта статья.

Сила BSD и слабость GNU

Пытаюсь написать портируемый шелл-скрипт. Читаю man [
("man test" на моём "маке" выдаёт справку по реализации test в GNU Coreutils).

RHEL 6.x (на самом деле, любой GNU userspace):
       -h FILE
              FILE exists and is a symbolic link (same as -L)

       -L FILE
              FILE exists and is a symbolic link (same as -h)

И ничерта не понятно, какой из ключей стоит использовать, а какой оставлен для совместимости с античными версиями.

Mac OS X (то же самое, кстати, справедливо и для FreeBSD — проверено):
     -h file       True if file exists and is a symbolic link.  This operator is retained for compatibility with pre-
                   vious versions of this program. Do not rely on its existence; use -L instead.

Nuff said, как говорится.

2013-07-04

"Хотя это немного слишком анально сохраняющий вкус для многих людей"

Именно так служба Google Translate переводит фразу "though it is a little bit too anally retentive for many people's tastes".

А началось всё с того, что ваш покорный слуга решил выяснить, каковы в C# договорённости для именования констант. А они, как оказалось, вот такие:
The recommended naming and capitalization convention is to use Pascal casing for constants (Microsoft has a tool named StyleCop that documents all the preferred conventions and can check your source for compliance - though it is a little bit too anally retentive for many people's tastes)
Источник.

2013-06-24

git-flow

Открыл для себя замечательную реализацию разумной парадигмы создания веток (branching) и управления новыми версиями (release management) -- git-flow. Вроде бы совсем не rocket science, но самоорганизоваться проще, когда уже есть готовые инструменты.

Ссылки:
В довершение могу сказать, что для пользователей "маков"
  • git-flow доступен не только в дереве HomeBrew, но и в MacPorts;
  • замечательный Git-клиент SourceTree поддерживает git-flow.