SBT: исключить класс из Jar
Я конвертирую старый проект jar в SBT и по странным причинам, которые нелегко решить, этот проект поставляется с " javax/servlet/Servlet.class" внутри него. Поэтому мне нужно как-то исключить этот класс из файла jar, сгенерированного package-bin. Как это сделать? Предпочтительно я хотел бы исключить использование подстановочного знака (т.е. javax. *).
Плагин сборки SBT выглядит так, как будто он имеет функции, которые будут делать это, но я обеспокоен тем, что использование сборки sbt означает, что мой проект jar не будет работать в проекте модуля мулити (т.е. если Я включаю его как зависимость в военном файле, тогда для военных проектов нужно сказать, чтобы запустить сборку в проекте зависимой jar, а не package-bin - но я могу быть ошибочно здесь).
Ответы
Ответ 1
Каждая задача объявляет другие задачи и настройки, которые она использует. Вы можете использовать inspect
для определения этих входов, как описано в Проверка параметров и в недавнем учебном стиле блоге Джона Cheng.
В этом случае соответствующая задача, используемая packageBin
, равна mappings
. Задача mappings
собирает файлы, которые должны быть включены в банку, и отображает их в путь в банке. Некоторый фон объясняется Картографическими файлами, но в результате mappings
создает значение типа Seq[(File, String)]
. Здесь Файл - это входной файл, предоставляющий содержимое, а String - путь в банке.
Итак, чтобы изменить сопоставления для задачи packageBin
, отфильтруйте пути из сопоставлений по умолчанию, которые вы не хотите включать:
mappings in (Compile,packageBin) ~= { (ms: Seq[(File, String)]) =>
ms filter { case (file, toPath) =>
toPath != "javax/servlet/Servlet.class"
}
}
mappings in (Compile,packageBin)
выбирает сопоставления для основной задачи пакета (в отличие от тестовых источников или задачи packageSrc).
x ~= f
означает "установить x в результат применения функции f к предыдущему значению x". (Подробнее см. Подробнее о настройках.)
Фильтр отбрасывает все пары, где путь соответствует классу Servlet.
Ответ 2
Я придумал это решение, он определяет новую задачу компиляции, которая зависит от предыдущей задачи компиляции (таким образом, эффективно позволяя мне подключаться сразу после скомпилирования источника и перед его упаковкой)
def mySettings = {
// add functionality to the standard compile task
inConfig(Compile)(Seq(compile in Compile <<= (target,streams,compile in Compile) map{
(targetDirectory, taskStream, analysis) =>
import taskStream.log
// this runs after compile but before package-bin
recursiveListFiles(targetDirectory, ".*javax.*".r) foreach {
file =>
log.warn("deleting matched resource: " + file.getAbsolutePath())
IO.delete(file)
}
analysis
})) ++
Seq(name := "MyProject", version := "1.0", exportJars := true)
}
def recursiveListFiles(f: File, r: Regex): Array[File] = {
val these = f.listFiles
val good = these.filter(f => r.findFirstIn(f.getName).isDefined)
good ++ these.filter(_.isDirectory).flatMap(recursiveListFiles(_, r))
}
Его немного сложнее, чем я надеялся, но он позволяет мне делать всевозможные модификации перед упаковкой (в этом случае поиск целевой папки, удаляющей все файлы классов, которые соответствуют регулярному выражению). Также он выполнил мою вторую задачу - придерживаться жизненного цикла SBT по умолчанию.