Skip to content

Commit

Permalink
Merge pull request #510 from sbt/wip/jvmopts-in-build
Browse files Browse the repository at this point in the history
FIX #82 adding the ability to specify jvm options via sbt
  • Loading branch information
muuki88 committed Mar 28, 2015
2 parents d96a57d + 62362c2 commit 48b0c19
Show file tree
Hide file tree
Showing 31 changed files with 379 additions and 106 deletions.
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=0.13.6
sbt.version=0.13.8
6 changes: 3 additions & 3 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ resolvers += Resolver.url("sbt-plugin-releases", new URL("http://scalasbt.artifa

resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven"

addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.3")

addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.6.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.0")

addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.7.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.1")

libraryDependencies <+= (sbtVersion) { sv =>
"org.scala-sbt" % "scripted-plugin" % sv
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# #################################
# ##### Default configuration #####
# #################################

# Available replacements
# ------------------------------------------------
# ${{author}} debian author
# ${{descr}} debian package description
# ${{exec}} startup script name
# ${{chdir}} app directory
# ${{retries}} retries for startup
# ${{retryTimeout}} retry timeout
# ${{app_name}} normalized app name
# ${{daemon_user}} daemon user
# -------------------------------------------------

# DEPRECATED, use -J-Xmx1024m instead
# -mem 1024

# Setting -X directly (-J is stripped)
# -J-X
# -J-Xmx1024

# Add additional jvm parameters
# -Dkey=val

# For play applications you may set
# -Dpidfile.path=/var/run/${{app_name}}/play.pid

# Turn on JVM debugging, open at the given port
# -jvm-debug <port>

# Don't run the java version check
# -no-version-check
Original file line number Diff line number Diff line change
Expand Up @@ -150,34 +150,7 @@ addResidual () {
addDebugger () {
addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1"
}
# a ham-fisted attempt to move some memory settings in concert
# so they need not be messed around with individually.
get_mem_opts () {
local mem=${1:-1024}
local perm=$(( $mem / 4 ))
(( $perm > 256 )) || perm=256
(( $perm < 1024 )) || perm=1024
local codecache=$(( $perm / 2 ))

# if we detect any of these settings in ${java_opts} we need to NOT output our settings.
# The reason is the Xms/Xmx, if they don't line up, cause errors.
if [[ "${java_opts}" == *-Xmx* ]] ||
[[ "${java_opts}" == *-Xms* ]] ||
[[ "${java_opts}" == *-XX:MaxPermSize* ]] ||
[[ "${java_opts}" == *-XX:ReservedCodeCacheSize* ]] ||
# check java arguments for settings, too
[[ "${java_args[@]}" == *-Xmx* ]] ||
[[ "${java_args[@]}" == *-Xms* ]] ||
[[ "${java_args[@]}" == *-XX:MaxPermSize* ]] ||
[[ "${java_args[@]}" == *-XX:ReservedCodeCacheSize* ]];
then
echo ""
elif [[ !$no_version_check ]] && [[ "$java_version" > "1.8" ]]; then
echo "-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m"
else
echo "-Xms${mem}m -Xmx${mem}m -XX:MaxPermSize=${perm}m -XX:ReservedCodeCacheSize=${codecache}m"
fi
}

require_arg () {
local type="$1"
local opt="$2"
Expand Down Expand Up @@ -214,7 +187,7 @@ process_args () {

-no-version-check) no_version_check=1 && shift ;;

-mem) require_arg integer "$1" "$2" && app_mem="$2" && shift 2 ;;
-mem) echo "!! WARNING !! -mem option is ignored. Please use -J-Xmx and -J-Xms" && shift 2 ;;
-jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;

-main) custom_mainclass="$2" && shift 2 ;;
Expand Down Expand Up @@ -274,7 +247,6 @@ run() {

# run sbt
execRunner "$java_cmd" \
$(get_mem_opts $app_mem) \
${java_opts[@]} \
"${java_args[@]}" \
-cp "$(fix_classpath "$app_classpath")" \
Expand Down Expand Up @@ -328,7 +300,6 @@ Usage: $script_name [options]
-v | -verbose this runner is chattier
-d | -debug set sbt log level to debug
-no-version-check Don't run the java version check.
-mem <integer> set memory options in MB (default: $sbt_mem, which is $(get_mem_opts $sbt_mem))
-main <classname> Define a custom main class
-jvm-debug <port> Turn on JVM debugging, open at the given port.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# #################################
# ##### Default configuration #####
# #################################
# #####################################
# ##### Environment Configuration #####
# #####################################

# This file gets sourced before the actual bashscript
# gets executed. You can use this file to provide
# environment variables

# Available replacements
# ------------------------------------------------
Expand All @@ -14,21 +18,11 @@
# ${{daemon_user}} daemon user
# -------------------------------------------------

# Setting -Xmx and -Xms in Megabyte
# -mem 1024

# Setting -X directly (-J is stripped)
# -J-X
# -J-Xmx1024

# Add additional jvm parameters
# -Dkey=val

# For play applications you may set
# -Dpidfile.path=/var/run/${{app_name}}/play.pid

# Turn on JVM debugging, open at the given port
# -jvm-debug <port>
# Setting JAVA_OPTS
# -----------------
# JAVA_OPTS="-Dpidfile.path=/var/run/${{app_name}}/play.pid $JAVA_OPTS"

# Don't run the java version check
# -no-version-check
# export env vars for 3rd party libs
# ----------------------------------
# COMPANY_API_KEY=123abc
# export COMPANY_API_KEY
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
source /lib/init/vars.sh
source /lib/lsb/init-functions

# adding bashScriptEnvConfigLocation
[[ -f ${{env_config}} ]] && . ${{env_config}}

# $JAVA_OPTS used in $RUN_CMD wrapper
export JAVA_OPTS

PIDFILE=/var/run/${{app_name}}/running.pid

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
# Source function library.
. /etc/rc.d/init.d/functions

# adding bashScriptEnvConfigLocation
[[ -f ${{env_config}} ]] && . ${{env_config}}

# $JAVA_OPTS used in $RUN_CMD wrapper
export JAVA_OPTS

prog="${{exec}}"

# FIXME The pid file should be handled by the executed script
Expand Down
56 changes: 49 additions & 7 deletions src/main/scala/com/typesafe/sbt/packager/archetypes/JavaApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package packager
package archetypes

import sbt._
import sbt.Keys.{ mappings, target, name, mainClass, sourceDirectory }
import sbt.Keys.{ mappings, target, name, mainClass, sourceDirectory, javaOptions, streams }
import packager.Keys.{ packageName, executableScriptName }
import linux.{ LinuxFileMetaData, LinuxPackageMapping }
import linux.LinuxPlugin.autoImport.{ linuxPackageMappings, defaultLinuxInstallLocation }
Expand Down Expand Up @@ -39,13 +39,19 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
*/
val batTemplate = "bat-template"

/**
* Location for the application.ini file used by the bash script to load initialization parameters for jvm and app
*/
val appIniLocation = "${app_home}/../conf/application.ini"

object autoImport extends JavaAppKeys

import JavaAppPackaging.autoImport._

override def requires = debian.DebianPlugin && rpm.RpmPlugin && docker.DockerPlugin && windows.WindowsPlugin

override def projectSettings = Seq(
javaOptions in Universal := Nil,
// Here we record the classpath as it's added to the mappings separately, so
// we can use its order to generate the bash/bat scripts.
scriptClasspathOrdering := Nil,
Expand All @@ -61,11 +67,34 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
mappings in Universal <++= scriptClasspathOrdering,
scriptClasspath <<= scriptClasspathOrdering map makeRelativeClasspathNames,
bashScriptExtraDefines := Nil,
bashScriptConfigLocation <<= bashScriptConfigLocation ?? None,
// Create a bashConfigLocation if options are set in build.sbt
bashScriptConfigLocation <<= bashScriptConfigLocation ?? Some(appIniLocation),
bashScriptEnvConfigLocation <<= bashScriptEnvConfigLocation ?? None,
bashScriptExtraDefines <++= (bashScriptEnvConfigLocation in Universal) map { _.map { config =>
"[[ -f '" + config +"' ]] && source " + config
}.toSeq },
mappings in Universal := {
val log = streams.value.log
val universalMappings = (mappings in Universal).value
val dir = (target in Universal).value
val options = (javaOptions in Universal).value

bashScriptConfigLocation.value.collect {
case location if options.nonEmpty =>
val configFile = dir / "tmp" / "conf" / "application.ini"
IO.writeLines(configFile, "# options from build" +: options)
val filteredMappings = universalMappings.filter {
case (file, path) => path != appIniLocation
}
// Warn the user if he tries to specify options
if (filteredMappings.size < universalMappings.size) {
log.warn("--------!!! JVM Options are defined twice !!!-----------")
log.warn("application.ini is already present in output package. Will be overriden by 'javaOptions in Universal'")
}
(configFile -> cleanApplicationIniPath(location)) +: filteredMappings

}.getOrElse(universalMappings)

},

// ---
bashScriptDefines <<= (Keys.mainClass in (Compile, bashScriptDefines), scriptClasspath in bashScriptDefines, bashScriptExtraDefines, bashScriptConfigLocation) map { (mainClass, cp, extras, config) =>
val hasMain =
for {
Expand Down Expand Up @@ -123,7 +152,7 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
artifactClassifier.filterNot(_.isEmpty).map("-" + _).getOrElse("") +
".jar"

// Determines a nicer filename for an attributed jar file, using the
// Determines a nicer filename for an attributed jar file, using the
// ivy metadata if available.
private def getJarFullFilename(dep: Attributed[File]): String = {
val filename: Option[String] = for {
Expand Down Expand Up @@ -208,6 +237,20 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
dep <- deps
realDep <- findRealDep(dep, projectArts)
} yield realDep.data -> ("lib/" + getJarFullFilename(realDep))

/**
* Currently unused.
* TODO figure out a proper way to ship default `application.ini` if necessary
*/
protected def applicationIniTemplateSource: java.net.URL = getClass.getResource("application.ini-template")

/**
* @param path that could be relative to app_home
* @return path relative to app_home
*/
private def cleanApplicationIniPath(path: String): String = {
path.replaceFirst("\\$\\{app_home\\}/../", "")
}
}

/**
Expand Down Expand Up @@ -272,4 +315,3 @@ trait JavaAppStartScript {
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait JavaAppKeys {
val bashScriptDefines = TaskKey[Seq[String]]("bashScriptDefines", "A list of definitions that should be written to the bash file template.")
val bashScriptExtraDefines = TaskKey[Seq[String]]("bashScriptExtraDefines", "A list of extra definitions that should be written to the bash file template.")
val bashScriptConfigLocation = TaskKey[Option[String]]("bashScriptConfigLocation", "The location where the bash script will load default argument configuration from.")
val bashScriptEnvConfigLocation = TaskKey[Option[String]]("bashScriptEnvConfigLocation", "The location of a bash script that will be sourced before running the app.")
val bashScriptEnvConfigLocation = SettingKey[Option[String]]("bashScriptEnvConfigLocation", "The location of a bash script that will be sourced before running the app.")
val batScriptExtraDefines = TaskKey[Seq[String]]("batScriptExtraDefines", "A list of extra definitions that should be written to the bat file template.")
val scriptClasspathOrdering = TaskKey[Seq[(File, String)]]("scriptClasspathOrdering", "The order of the classpath used at runtime for the bat/bash scripts.")
val projectDependencyArtifacts = TaskKey[Seq[Attributed[File]]]("projectDependencyArtifacts", "The set of exported artifacts from our dependent projects.")
Expand Down
Loading

0 comments on commit 48b0c19

Please sign in to comment.