Каждый второй, кто пытается собрать что-то под Windows, получет глубокую психологическую травму, и заранее ожидает от сборки следующих эмоций:
Что касается JDK, если не сходить с пряничной дорожки, делать в точности как в этой инструкции, проблем не будет. Возможные проблемы обозначены в тексте.
Общий смысл происходящего: устанавливаем компиляторы (JDK8, Visual Studio 2013), среду сборки (GNU/Cygwin) и набор стандартных пакетов для неё, собираем из исходников Freetype, заливаем репозиторий JDK, configure, make, java -version.
Мы будем собирать Java и C++ (раз вы читаете эту статью, то, наверное, уже в курсе), поэтому на микроволновке лучше сборкой не заниматься. Нужна рабочая станция или ноутбук с нормальным процессором, и, желательно, SSD вместо жесткого диска для сборочной директории проекта. Кроме сборки, какое-то время потратится на скачивание исходника и установку Visual Studio.
Понадобится подключение к интернету и права администратора Windows. Проблемы пользователей корпоративной инфраструктуры, где всего этого нет, здесь не рассматриваются.
Устанавливаем JDK8
для бута.
Ссылка на загрузку.
Устанавливаем Visual Studio 2013
(версия Express подойдёт).
Ссылка на загрузку. Если вы устанавливаете полную версию, то при установке вам дадут выбор компонентов: достаточно установить только те компоненты, которые относятся к C++ и Windows SDK.
При установке Express, никакого выбора не будет — к счастью, оно само устанавливает именно то, что нам нужно. Это выглядит как-то так:
После установки, обязательно нужно перезагрузить операционную систему.
Важно: нужно установить именно Visual Studio 2013. Не ниже потому, что о версии 2013 говорится в Build Readme. Не выше потому, что если попробовать провести сборку с установленной Visual Studio 2015, то сборщик JDK будет видеть компилятор, но будет ломаться с ошибкой:
C compiler cannot create executables
Если заглянуть в config.log, становится понятна причина:
LINK : fatal error LNK1104: cannot open file 'LIBCMT.lib'
Если тупо сделать
export LINK="/NODEFAULTLIB:libcmt.lib"
то оно развалится:
unresolved external symbol mainCRTStartup.
Если кто-то в комментариях знает, как безболезненно починить эту ошибку и запуститься на 2015, буду очень благодарен. Неприятно быть залоченным на устаревшую версию компилятора, даже если она бесплатная.
Устанавливаем Cygwin.
Ссылка на загрузку.
Важно: сейчас принято использовать msys2 вместо Cygwin. К сожалению, сборка JDK тут же упадет с ошибкой:
configure: error: /usr/bin/bash /x/git/openjdk9/common/autoconf/build-aux/config.sub x86_64-pc-msys failed
Если попытаться прописать msys так же, как там прописан Cygwin, то ошибка меняется:
unsupported operating system msys
Если какой-нибудь герой в комменатриях расскажет, как правильно прописать msys, это было бы здорово.
Устанавливаем пакеты для Cygwin
, описанные в Build Readme.
В скобках указана категория пакета, после знака "—" ради чего мы это ставим.
Назначение каждого экзешника можно почитать в мане, но чтобы собрать этого знать не нужно.
- binutils (devel) – ar.exe
- make (devel) — make.exe
- m4 (interpreters) — m4.exe
- cpio (utils) — cpio.exe
- gawk (base, interpreters) — gawk.exe
- file (base) — file.exe
- zip (archive) — zip.exe
- unzip (archive) — unzip.exe
- procps-ng (system) — free.exe
Для возмущенных таким большим набором зависимостей — скажите спасибо, что не заставили устанавливать Python и Ruby! :)
Для тех, кто ни разу не сталкивался с Cygwin пара замечаний:
- Установка пакетов выглядит как-то так:
- Существует множество пакетов, например, со словом binutils в названии.
Нужно выбирать пакет, в точности по буквам совпадающий с названием из списка, соответствующий группе из списка. (Конечно, если вы точно знаете что делаете, ваша воля :) ) - Принадлежность пакетов к группам в Cygwin время от времени меняется. В частности, группы, перечисленные в этом списке уже не совпадают с группами из Build Readme. Если группы из списка не существует – выберите подходящую (и напишите мне личное сообщение, чтобы я обновил эту инструкцию).
- При установке, вас попросят указать установочные директории. Постарайтесь установить в путь с как можно более коротким имененем, например: C:/cygwin и C:/cygpack. Или вообще c:/cw и c:/cp. Это поможет избежать ошибок с излишне длинными именами файлов, которые не может обработать проводник Windows (NTFS уже иногда может их обрабатывать, а Проводник – еще нет).
- После изначальной установки, в самом Cygwin нет никакого гуя для управления пакетами. Чтобы установить дополнительные пакеты, нужно заново запустить setup.exe. Эта программа не будет устанавливать Cygwin с нуля, а только докачает нужное. Между перезапусками путь до директорий сохраняется.
- Выбор зеркала влияет на скорость, но нам нужно скачать очень мало пакетов, поэтому что выбирать — в среднем всё равно. Выбирайте самое первое зеркало в списке.
- Гуй для установки пакетов немного странный, но вы разберетесь :)
- Как только вы вписали в поле поиска имя пакета, соответствующий список перерисовывается автоматически – enter жать не нужно.
- Чтобы установить пакет, нужно много раз прокликать кнопку со статусом (стрелочки замкнутые в уробороса с надписью skip или какой-то еще), чтобы надпись статуса поменялась на версию пакета, которая будет устанавливаться
- Иногда инсталлятору становится разными способами плохо. Don’t panic. Если установка повисла посередине, то самый простой способ всё вернуть назад — удалить C:/Cygwin, или куда вы там его устанавливаете. Лучше не надеяться, что проверяльщик чексумм битых недокачанных пакетов сможет найти поломку, устраните её полным удалением самостоятельно.
Качать make отдельно не нужно
В прошлых инструкциях часто предполагалось скачать и прописать свой make. По новейшим наблюдениям, делать этого не имеет смысла, того make что установился пакетом в Cygwin — вполне достаточно.
Более того, на официальном сайте лежит устаревшая версия make, поэтому с ней вы получите ошибку типа:
The specified make (by MAKE=/cygdrive/c/Program Files (x86)/GnuWin32/bin/make.exe) is not GNU make 4.0 or newer.
То есть, make вам придется или собирать вручную, или искать уже собранный на сомнительных файлопомойках, как когда-то мы подбирали на них rpm’ки.
Если собственный make вам действительно нужен, то чтобы его использовать, нужно прописать в configure параметрMAKE=/путь/до/make.exe
. Да, другие параметры начинаются на --, например --with-freetype, а вот MAKE должен быть именно в таком виде.
DirectX SDK устанавливать не нужно
Если оно вам действительно нужно (Java 3D?), вы об этом знаете, и знаете что делать. Здесь инструкций не будет.
Собираем FreeType
Собирать FreeType обязательно, даже если очень не хочется и лично вам не нужно.
- Ссылка на загрузку.
Там две группы загрузок: две вверху (Complete package и Sources), и шесть пониже (Binaries… Original source). Элемент Sources есть в обеих группах. Нам нужно скачать зипник элемента Sources из второй группы.
Замечание: Качает сто лет, что делать? Ничего не поделаешь, это Сорсфордж. В момент отображения таймера загрузки попробуйте успеть щелкнуть по ссылке try another mirror и выберите что-нибудь во Франции. Французы не жмотятся на скорость.
- Создаем директорию src/freetype/2.3.5/freetype-2.3.5/lib
- Внутри директории src/freetype/2.3.5/freetype-2.3.5/builds/win32/visual лежит солюшен для Студии.
- Открываем. Если у вас несколько Студий, то от греха подальше лучше открыть в 2013. Сборку с 2015 пробовал, она тоже работает.
- При открытии солюшена Студия попросит one-way upgrade. Соглашаемся (если отображается несколько элементов в списке – соглашаемся для всех).
- После этого Студия может намертво повиснуть, перестав заодним отображаться и в Диспетчере. Задач Windows. Тут на помощь приходит Sysinternals Process Explorer:
technet.microsoft.com/ru-ru/sysinternals/processexplorer.aspx
Нужно найти в дереве devenv.exe, и вначале убить всех его потомков. После этого можно убить и сам devenv.exe (до этого он просто не реагирует на команду умереть).
- Идем в Configuration Manager, в выпадашке Platform выбираем New, New platform: x64, Copy settings from: Win32, OK, Close.
- Там же, выбираем тип сборки – Release Multithreaded (по умолчанию стоит Debug)
- В Solution Explorer, правой кнопкой на проект freetype, properties.
- Указываем Output Directory: src/freetype/2.3.5/freetype-2.3.5/lib (директория указана относительно корня скачанного FreeType). Проверяем, что configuration type выставлен в Static library (.lib).
- Закрываем окно freetype Property Pages. Собираем проект через Build > Build solution.
- Теперь нужно поменять сборку с lib на dll.
Повторяем действия:
В Solution Explorer, правой кнопкой на проект freetype, properties. Указываем Output Directory: src/freetype/2.3.5/freetype-2.3.5/lib. Проверяем, что configuration type выставлен в Dynamic library (.dll)
Закрываем окно freetype Property Pages. Собираем проект через Build > Build solution.
- Открываем директорию src/freetype/2.3.5/freetype-2.3.5/lib в Проводнике и проверяем состав файлов: freetype.dll, freetype.lib, freetype.exp.
Ключевой факт тут такой: теперь у нас в одной корневой директории (src/freetype/2.3.5/freetype-2.3.5) лежат и инклуды (src/freetype/2.3.5/freetype-2.3.5/include), и библиотеки (src/freetype/2.3.5/freetype-2.3.5/lib).
- Готово! Теперь у нас есть жалкие 600 килобайт, ради которых мы мучались последние десять минут.
- Ссылка на загрузку.
Заливаем исходники JDK из репозитория
- Загружаем и устанавливаем Mercurial (TortoiseHg): tortoisehg.bitbucket.org/download/index.html
- Загружаем расширение trees для Mercurial
Файл:
gist.githubusercontent.com/olegchir/8267049ed48f7975aa8ef7d7c1515349/raw/fbe90ac1c639f6c209bc7cebbdcc7ebbd848c734/trees.py
Запоминаем, куда скачали (например: C:/opt/trees.py)
Важно! Согласно инструкциям отсюда:
openjdk.java.net/projects/code-tools/trees
Мы должны были бы загружать вот этот файл:
hg.openjdk.java.net/code-tools/trees/raw-file/tip/trees.py
К сожалению, на момент написания статьи, интеграция этого экстеншена с новой версией Mercurial сломана. Есть следующий баг, с приложенным патчем:
bugs.openjdk.java.net/browse/CODETOOLS-7901672
Чтобы вам не патчить trees самостоятельно, я пропатчил его, и выложил здесь:
gist.githubusercontent.com/olegchir/8267049ed48f7975aa8ef7d7c1515349/raw/fbe90ac1c639f6c209bc7cebbdcc7ebbd848c734/trees.py
В будущем, когда этот тикет будет закрыт, стоит использовать основную версию. Если вы читаете эту инструкцию, когда тикет уже закрыт – напишите мне, я исправлю этот пункт.
- Создаем файл .hgrc в домашнем каталоге пользователя (%USERPROFILE%\.hgrc).
Так как Windows плохо относится к созданию файлов, начинающихся на точку, проще всего открыть консоль Cygwin и выполнить команду:
touch /cygdrive/c/Users/olegchir/.hgrc
Внутри файла пишем:
[extensions] purge = trees = C:\opt\trees.py
Слеши в пути до py-файла – обратные.
- Открываем консоль (cmd.exe), переходим в директорию, где хотим хранить исходники (cd C:\git)
- Клонируем репозиторий:
hg tclone http://hg.openjdk.java.net/jdk9/dev 9dev
Это займет весьма много времени.
Важно! В будущем ссылка может измениться. Смотреть новую ссылку можно здесь: openjdk.java.net/guide/repositories.html
Важно! Постарайтесь установить в путь с как можно более коротким имененем, например: C:/hg. Это поможет избежать ошибок с излишне длинными именами файлов, которые не может обработать проводник Windows (NTFS уже иногда может их обрабатывать, а Проводник – еще нет). Поможет не попасть в глупую ситуацию, когда репозиторий вы уже склонировали, а удалить его — еще не можете.
Неприятненько. При возникновении ошибки «abort: stream ended unexpectedly». Вначале попробуйте перезапустить hg tclone еще несколько раз. Если ошибка продолжает повторятся, то вам предстоит муторная ручная работа. Запомните, какой проект не выгружался до конца (например, langtools). Перезапустите всё с таким аргументом:
hg tclone -r 100 http://hg.openjdk.java.net/jdk9/dev 9dev
Это загрузит только 100 ченжсетов и даст возможность операции tclone завершиться.
Сразу после этого перейдите в директорию проекта, который не докачался (например, langtools), и выполните hg tpull -u 1000.
И дальше добавляйте по 1000 ченжсетов:
hg tpull -u 1000
hg tpull -u 2000
hg tpull -u 3000
Когда ревизии закончатся – нужно перейти в корень (9dev), и выполнить там команду “hg tpull -u” (без указания количества ревизий).
Если после этого упадёт тот же проект – перейдите в него назад, и с более маленьким шагом докачайте оставшиеся ревизии совсем точно до конца, вернитесь в корень и повторите hg tpull -u без аргументов.
Если после этого упадёт другой проект – переходим в его директорию, и повторяем пока всё не склонируется до конца.
- Загружаем и устанавливаем Mercurial (TortoiseHg): tortoisehg.bitbucket.org/download/index.html
Собираем JDK
- Открываем консоль Cygwin (НЕ cmd.exe), переходим в директорию со склонированными исходниками.
- Выполняем команду:
./configure --enable-debug --with-target-bits=64 --with-boot-jdk=/cygdrive/c/opt/Java/jdk1.8.0_111 --with-freetype=/cygdrive/c/my/opt/java/freetype-2.3.5-1-src/src/freetype/2.3.5/freetype-2.3.5
пути до файлов должны совпадать с теми, что мы получили в ходе выполнения инструкции:
--with-boot-jdk указывает на директорию, куда вы загрузили JDK8
--with-freetype указывает на директорию внутри исходников freetype, где есть поддиректории include и lib, и в lib вы собрали .dll и .lib с 64-битным фритайпом
пути до файлов обязаны быть не родными, а начинаться с /cygdrive.
- Долго ждем, пока сконфигурится. Ошибок быть не должно.
Единственная ожидаемая ошибка — при использовании Visual Studio Express:
Cannot locate a valid Visual Studio or Windows SDK installation on disk
Обычно её можно исправить небольшим грязным хаком. Заходим в директорию установки MSVS (обычно это C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC).
Видим что там нет диерктории amd64, зато есть x86_amd64.
Копируем её с новым названием: amd64.
Заходим внутрь amd64, и копируем файл vcvarsx86_amd64.bat с новым именем: vcvars64.bat
Перезапускаем configure с новым параметром: --with-tools-dir:
./configure --enable-debug --with-target-bits=64 --with-boot-jdk=/cygdrive/c/opt/Java/jdk1.8.0_111 --with-freetype=/cygdrive/c/my/opt/java/freetype-2.3.5-1-src/src/freetype/2.3.5/freetype-2.3.5 --with-tools-dir="/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin/amd64"
- В результате выполнения configure видим такой текст:
Configuration summary:
* Debug level: fastdebug
* HS debug level: fastdebug
* JDK variant: normal
* JVM variants: server
* OpenJDK target: OS: windows, CPU architecture: x86, address length: 64
* Version string: 9-internal+0-adhoc.olegchir.openjdk9 (9-internal)
Tools summary:
* Environment: cygwin version 2.6.1(0.305/5/3) (root at /cygdrive/c/cygwin)
* Boot JDK: java version «1.8.0_111» Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode) (at /cygdrive/c/opt/Java/jdk1.8.0_111)
* Toolchain: microsoft (Microsoft Visual Studio 2013)
* C Compiler: Version 18.00.40629 (at /cygdrive/c/progra~2/micros~2.0/vc/bin/amd64/cl)
* C++ Compiler: Version 18.00.40629 (at /cygdrive/c/progra~2/micros~2.0/vc/bin/amd64/cl)
Build performance summary:
* Cores to use: 8
* Memory limit: 20447 MB
- Выполняем команду: make
- Долго ждем, пока соберется. В этот момент у компьютера тратится очень много ресурсов – стоит переключиться на использование другого компьютера, или сходить попить чаю.
Проверяем запуск
Внутри диретктории с исходниками должна появиться директория builds/windows-x86_64-normal-server-fastdebug
С помощью консоли (cmd.exe) заходим в каталог типа:
X:\git\openjdk9\build\windows-x86_64-normal-server-fastdebug\jdk\bin
И выполняем команду: java -version
Должна быть распечатана версия 9-internal.
Troubleshooting
In open source no one can hear your scream
PROFIT
Комментарии (20)
maaGames
07.01.2017 18:03+2> Если кто-то в комментариях знает, как безболезненно починить эту ошибку и запуститься на 2015
Этот косяк часто бывает, когда проект апгрейдится со старый версий. Нужно в путях проекта добавить пути до библиотек компилятора. И до хедеров и исходников и исполняемых файлов. Там вообще всё очень странно и запутано: с одними и теми же параметрами у меня компилировался debug и не компилировался release, пока не подобрал правильные пути (в моём случае на вин7 пришлось указывать пути до sdk 8.1). В общем, если поколдовать, то нужная библиотека найдётся.
jerry_kiwi
07.01.2017 18:58+2Осталось понять, зачем весь вышеописанный производственный подвиг вообще нужен:)
olegchir
07.01.2017 19:01+2Ну например для того, чтобы без перезагрузки ноутбука иметь возможность альт-табнуться в Overwatch и сыграть партию-другую :)
maniacscientist
11.01.2017 20:07+1KVM? Qemu с пробросом? Не заносить деньгу однополым любовникам, чьи менеджеры сказали что версия для линукса не нужна?
PastorGL
07.01.2017 19:46+3Cygwin? Да ну его в пень :(
Интереснее было бы попробовать скрестить ужа с ежом, и собрать на десятке из WSL окружения. Вот это было бы колдунство. По крайней мере, чисто теоретически в последних insider preview такое должно быть возможно, там добавили возможность вызова Win32 бинарей из Linux usermode (и виндовый PATH в нём тоже доступен).
ZaMaZaN4iK
07.01.2017 20:19+4Что люди только не вытворяют, лишь бы GNU\Linux не пользоваться :)
rPman
07.01.2017 21:15вы можете дать инструкцию по кросскомпиляции jdk из linux под win32?
а то java эта именно та вещь которая нужна не только под linux :)olegchir
07.01.2017 21:30+1не могу, нет надобности, у меня все целевые ОС на реальном железе
а вообще, вам зачем? Кросскомпилированное особо не поотлаживаешь, для релизной модифицированной сборки как явления редкого вполне можно поставить винду в виртуалку, для релизной ванильной сборки — уже есть готовые сборки (https://jdk9.java.net/download/)
SamVimes
08.01.2017 09:44+1Собирал недавно Project Valhalla (по сути JDK9 + несколько JEP'ов), никаких профитов не заметил, в основном всё на стадии work in progress (а так хотелось ValueType попробовать). Собирал, кстати, на стареньком Sony Vaio (правда с дебианом, а не виндой), всего за полчаса собралось.
pmcode
Мой опыт сборки под Windows резко закончился на необходимости скачивать 6 гигов компилятора для сборки Atom. Спасибо, после вашей статьи теперь это окончательное табу :) Все-таки задница именно то место, которым данная ОС повернута к айтишникам.
А зачем компилять самому? Есть же снапшоты. Или они совсем древние?
olegchir
Чтобы ковыряться в JDK, собирать с изменениями, и таким образом проверять предположения.
OnYourLips
ОС не при чем, дело в отсутствии средств управления зависимостями для С и C++.
В языках, где они есть, проблемы нет (кроме сборки нативных пакетов для ruby, nodejs и т.д., но тут проблема снова в C и C++).
Если вы под Linux будете собирать зависимости сами, а не использовать dev-пакеты, которые вам собрали ментейнеры дистрибутивов, то будете страдать абсолютно так же. Попробуйте собрать свежую версию чего либо под старым дистрибутивом (dev-пакеты будет устаревшими и не подойдут) — удивитесь.
maniacscientist
Все знают что винда — это пускалка игрушек