Сборка проекта
Сборка (англ. assembly) — двоичный файл, содержащий исполняемый код программы или (реже) другой подготовленный для использования информационный продукт.
Автоматизация сборки — этап написания скриптов или автоматизация широкого спектра задач применительно к ПО, применяемому разработчиками в их повседневной деятельности, включая такие действия, как:
- компиляция исходного кода в бинарный код
- сборка бинарного кода
- выполнение тестов
- разворачивание программы на производственной платформе
- написание сопроводительной документации или описание изменений новой версии
Для автоматизации сборки проектов традиционно используют системы сборки, такие как make на Unix подобных системах и nmake для компилятора Microsoft. Также традиционно написание файлов для сборки проекта под эти системы является задачей нетривиальной. Конечно, пользуясь только Mictosoft Visual Studio можно даже не подозревать о существовании этих файлов, так как интегрированная среда разработки достаточно удобно скрывает всю схему работы, оставляя снаружи несколько диалоговых окон и кнопку Build. Но для сложных проектов использующих массу сторонних библиотек и кроссплатформенных проектов такой подход часто оказывается неприемлемым.
Принципы сборки в java
1. Как работает java компилятор
Текст программы ———\
—> Javac —————> *.class
Дополнения —— [-cp]—/
Текст программы — это исходный код программы на языке java.
Дополнения — это классы, которые необходимо учитывать во время сборки (библиотеки).
В итоге мы получаем набор файлов с расширением class. То есть, если мы используем сторонние библиотеки – мы должны указать их при сборке. Это могут быть скомпилированные классы или собранные подсистемы.
Не всегда для компиляции необходимо указывать дополнительные библиотеки (к примеру, если у нас программа в 1 программный файл). Но если всё же это необходимо, то для этого компилятор java необходимо запустить с аргументом «-cp» (сокращение от —classpath). После этого аргумента идёт список библиотек (jar файлов или файлов class) разделённых символом разделителем файлов (в *nix это «:», в windows это «;»).
Пример компиляции программы из одного файла:
javacHelloWorld.java
Пример компиляции программы c дополнительными библиотеками «myLib» и «my2ndLib»:
javac -cp myLib.jar:my2ndLib.jar NotStandartHelloWorld.java
В java нет разграничения между собранной библиотекой, исполняемым приложением или же подсистемой. Что имеется в виду, что если вы хотите создать самостоятельную сущность в едином файле, вы создаёте jar файл. К примеру, если вы создаёте библиотеку, то это будет jar файл с набором классов, который могут быть использованный другими разработчиками, если это подсистема, то это часть функционала (набор классов) вынесенная за рамки основного модуля, но используемая в нём (что то вроде частной библиотеки), и т.д..
2. Выполнение java-программы.
*.class ————- ———\
—> Java
Дополнения —— [-cp]—/
Выполнение классов работает схожим образом с компиляцией (используются даже те же аргументы).
Если после компиляции у нас получилось 10 классов, то выполняем только класс который содержит функцию main, остальные классы должны быть представлены как библиотеки.
К примеру, запуск программы c дополнительными библиотекой «sout», которая находиться в папку «lib» выглядеть так:
java -cp lib/sout.jar HelloWorld
По умолчанию, все классы в текущем каталоги включены в пути (-cp для классов в текущем каталоге указывать не надо). Что имеется в виду, если мы скомпилировали программу, и в итоге получили множество классов в одной папке, то мы можем запускать только лишь главный класс, остальные классы java попробует найти сама в текущем каталоге (Даже если они находятся во вложенных папках, java и туда заглянет).
Такой подход допустим, когда у нас немного классов, но при больших системах перечисление всех классов не возможно (их количество может превышать тысячи …). Поэтому можно выполнять не класс, а специально собранный jar-файл. Для этого необходимо указать аргументы -jar.
java -cp lib.jar -jar myApp.jar
3. Jar-файл
Jar-файл — это ZIP архив (то есть вы можете разархивировать его). Jar-файл должен в себе содержать набор классов и файл META-INF/MANIFEST.MF, в котором описаны характеристики данного jar-файла.
Основной вариант создания Jar-файла:
jar cf jar-file input-file(s)
Jar – это утилита и набора утилит которые вы получаете при установке java.
Программа jar принимает аргументы в old-UNIX стиле: вначале идут ключи потом аргументы программы, ключ с аргументом указывается последним, не указывать «-» перед аргументами, группировать короткие аргументы («cf» значит «-c -f »).
- Опция c — говорит о том, что вы хотите создать (create) jar-файл.
- Опция f — говорит о том, что вы хотите создать файл (file) с определённым именем (при выполнении данного примера создастся файл с именем «jar-file.jar»).
- Аргумент input-file(s) является разделенный пробеламисписок из одного или нескольких файлов, которые вы хотите включить в ваш JAR-файл. input-file(s) аргумент может содержать символ «*». Если любой из входных является каталогом, содержимое этих каталогов добавляются в архив JAR рекурсивно.
Когда вы создаете JAR-файл, он автоматически получает файл манифеста по умолчанию (если вы его не указали во входных файлах – он будет создан автоматически). В jar-файле может быть только один файл манифеста с указанным путём:
META-INF/MANIFEST.MF
Общая структура манифеста имеет вид:
Заголовок: значение |
Все символы пробелов (\n, \r, \t, …) в «значении» будут удалены, к примеру, манифест:
Manifest-Version:1.0Созданная-By:1.6.0
( Sun Microsystems Inc )
|
Равносилен:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc) |
Когда вы создаете JAR-файл, по умолчанию файл манифеста просто содержит следующее:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc) |
Эти строки показывают, что элементы манифеста имеют форму «заголовок: значение» пар. Имя заголовка отделяется от ее значения двоеточием. Манифест по умолчанию соответствует версии 1.0 спецификации манифест и был создан 1.6.0 версии JDK.
Манифест также могут содержать информацию о других файлах, которые не упакованы в архив (внешние библиотеки который необходимы для функционирования, об этом будет сказано более подробно дальше). Именно то, что информацию о jar-файле должна быть записаны в манифесте зависит от того, как вы собираетесь использовать JAR-файл. Манифест по умолчанию не делает никаких предположений о том, какую информацию он должен записать о других файлах.
Чтоб создать jar-файл с манифестом:
jar cfm jar-file manifest-addition input-file(s)
Ключ «f» и «m» оба требуют аргументов, поэтому мы вначале указываем ключи, а потом в том же порядке указываем (если это необходимо) недостающее аргументы. В начале мы указали аргумент «f», а потом «m», поэтому первый аргумент будет имя выходного файла, а второй это имя (и путь) к манифесту.
Если в написанном вами манифесте не будет одной из выше указанных опций, то они будут добавлены автоматически (то есть, ну указать манифест или указать пустой файл, это одно и то же, это часто применимо в начале разработки…). То, есть если ваш манифест выглядит следующим образом:
Main-Class: Main |
То, в итоговом jar-файле он будет представлен в виде:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc)Main-Class: Main |
Если вы разрабатываете приложение, которое поставляется в JAR-файл, необходимо каким-то образом указать, какой класс в JAR-файле является входной точкой приложения (который содержит функцию main). Вы предоставляете эту информацию с Main-Class заголовка в манифесте, который имеет общий вид:
Main-Class: имя класса |
Значение имени класса является именем класса, который является входной точкой приложения.
После того как вы установите Main-Class заголовка в манифесте, вы запустите файл JAR с помощью следующей формы Java команду:
java -jar JAR-file
Не указав главного класса в манифесте вам придаться выполнять вашу программу так:
java -cp JAR-file.jar MainClass
Если вы хотите указать лишь главный класс в манифесте, то вам не нужно создавать весь манифест, вы можете указать, необходимы параметр при вызове jar:
jar cfe app.jar MyApp MyApp.class
Опция e — говорит о точки входа в программу (entrypoint).
Вам придется ссылаться на классы в другие файлы JAR из JAR-файла (если вы используете сторонние библиотеки в своем приложении). Для этого вам необходимо включить следующие поля в манифест:
Class-Path: jar1-name jar2-name directory-name/jar3-name |
Данный путь указывается относительно расположению выполняемого jar файла. К примеру, Netbeans складывает все библиотеки в папку lib, которую помещает рядом с собранным приложением, и соответственно указывает путь к библиотекам.
Рассмотрим конечный пример манифеста, для исполняемого jar-файла библиотеки к которому находятся рядом с ним в папке «lib»:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc)Main-Class: net.mycompany.product1.MainClass-Path: lib/recoder.jar lib/io-common.jar lib/f
ile-common.jar |