aboutsummaryrefslogblamecommitdiff
path: root/cbt
blob: 1ec2d0f04fc3421dd8764e1e1ed629e4a8dad625 (plain) (tree)
1
2
3
4
5
6
7
8
9
                   

                                                                                                          
                                                  




                                                                                                                     
                 
 











                                            
                


                        
                    

              
                                           

                                                        





                               


                                                                 
                 
                               




                                                                                                          
                     
            
                                   

                                         


          
                                    
 
                                  

                                     
                                                                                                                   

              
 
                                  



                                                                     
                                       





                                                                     
                                     
                     
                                

                                                                      
                                                                                               
                

  
                                

                                   
                                                                                        

  
          









                                                                      
 
                                                        
 

                                                            
 
                                            
                                        
                          
 


                                                
        

                               
                            


                                                                                                          
                                        

                                                       

                                    

                                                       


                          


            
        
 



                             
                                                                                                                                       


                                                            
                                                                        
 



                                                                                                    



                                                                                   
                                                                        


                   
                                                                                           






                                                                                                                            
                          
                                                         
                                                          


              
                               

               
                                             
 




                                                              
                                                                               

  
             



                             










                            
                                                                   


                     
                                                                               



                                                                                                                                                                                                  
                                                         
                                                        
                                                               
                                                                                                                                       



                                                           

  
           
                                                               
                                                                
                 
                                                                                
                                               
                                                                           
            

                                   
                                                                            
                                                                  
                                                                                                                
                                                          
                                                                             

                                                                                                            


                                                                     

                                                                                 
                                                                                                                                                               

                                       

                  
 
                                                                                                              
 

                                           

                                                       
                                            
                                                                                                        
                                                                                                                                                
                                   



                                                                           
                                                                                                
                                                                         
                                                                                                        














                                                                                                                                                                                      
                                                                                   
                                   
                  
                                            
          
 
 
 


                                         
                                         







                                                                                            
              





                                        


                                        
                   

                                                                            
                     
            


                                                        

                                                
                                                        



                                                                                    
                                            
                  

                                                                                                       




                                                                                       
                                                 







                                                                                     
          
    
 
                      
              
#!/usr/bin/env bash
# Launcher bash script that bootstraps CBT from source.
# (Some of the code for reporting missing dependencies and waiting for nailgun to come up is a bit weird.)
# This is intentionally kept as small as possible.
# Welcome improvements to this file:
# - reduce code size through better ideas
# - reduce code size by moving more of this into type-checked Java/Scala code (if possible without performance loss).
# - reduction of dependencies
# - performance improvements
shopt -qs extglob

seconds() {
	date +"%s"
}

nanos() {
	n=$(date +"%N")
	if [ "$n" = "N" ]; then
		n=$(gdate +"%N" 2>/dev/null)
	fi
	if [ "$n" = "" ]; then
		n="0"
	fi
	echo 1$n
}

start_seconds=$(seconds)
start_nanos=$(nanos)

time_taken() {
	i=$(( $(seconds) - start_seconds ))
	n=$(( $(( $(nanos) - start_nanos )) / 1000000 ))
	if [[ ( $n -lt 0 ) ]]; then
		i=$(( i-1 ))
		n=$(( n+1000 ))
	fi
	echo "$i.$n"
}

# utility function to log message to stderr with stating the time
log () {
	msg=$1
	enabled=1
	while test $# -gt 0; do
		if [[ "$1" == "-Dlog="* ]]; then
			if [[ "$1" == *"time"* ]] || [[ "$1" == *"bash"* ]] || [[ "$1" == *"all"* ]]; then
				enabled=0
			fi
		fi
		shift
	done
	if [ $enabled -eq 0 ]; then
		delta=$(time_taken)
		echo "[$delta] $msg" 1>&2
	fi
}

log "Checking for dependencies" "$@"

which javac >/dev/null 2>/dev/null
javac_installed=$?
if [ ! $javac_installed -eq 0 ]; then
	echo "You need to install javac 1.7 or later! CBT needs it to bootstrap from Java sources into Scala." 1>&2
	exit 1
fi

# log "cutting javac version" "$@"
# javac_version=$(javac -version 2>&1) # e.g. "javac 1.8.0_u60"
# javac_version_update=${javac_version/javac 1./} # e.g. "8.0_u60"
# javac_version_minor_pointed=${javac_version_update%_*} # e.g. "8.0"
# javac_version_minor=${javac_version_minor_pointed%.*} # e.g. "8"
# log "cutting javac version done" "$@"
# if [ ! "$javac_version_minor" -ge "7" ]; then
# 	echo "You need to install javac version 1.7 or greater!" 2>&1
# 	echo "Current javac version is $javac_version" 2>&1
# 	exit 1
# fi

which realpath >/dev/null 2>/dev/null
realpath_installed=$?
which gcc >/dev/null 2>/dev/null
gcc_installed=$?
if [ ! $realpath_installed -eq 0 ] && [ ! $gcc_installed -eq 0 ]; then
	echo "You need realpath or gcc installed! CBT needs it to locate itself reliably." 1>&2
	exit 252
fi

which gpg >/dev/null 2>/dev/null
gpg_installed=$?
if [ ! $gpg_installed -eq 0 ]; then
	echo "(Note: gpg not found. In order to use publishSigned you'll need it.)" 1>&2
fi

CWD=$(pwd)

CBT_SCRIPT="$(readlink "$0")"
if [ "$CBT_SCRIPT" = "" ]; then
	CBT_SCRIPT="$0"
fi
if [ "$CBT_SCRIPT" = "" ]; then
	echo "cannot locate cbt launcher" 1>&2
	exit 252
fi
_DIR=$(dirname "$CBT_SCRIPT" 2>/dev/null || dirname "$0" 2>/dev/null )

log "Find out real path. Build realpath if needed." "$@"

export CBT_HOME
CBT_HOME="$(dirname "$("$_DIR"/realpath/realpath.sh "$0")")"

export NAILGUN="$CBT_HOME"/nailgun_launcher/
export TARGET=target/scala-2.11/classes/
mkdir -p "$NAILGUN$TARGET"

nailgun_out="$NAILGUN/target/nailgun.stdout.log"
nailgun_err="$NAILGUN/target/nailgun.strerr.log"

DEBUG=""
foo(){
	while test $# -gt 0; do
		case "$1" in
			"-debug")
				DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
			;;
			"-Dlog=nailgun")
				nailgun_out=/dev/stderr
				nailgun_err=/dev/stderr
			;;
			"-Dlog=all")
				nailgun_out=/dev/stderr
				nailgun_err=/dev/stderr
			;;
		esac
		shift
	done
}

foo "$@"

if [ ! "$DEBUG" == "" ]; then
	shift
fi

JAVA_OPTS_CBT=($DEBUG -Xmx1536m -Xss10M "-XX:MaxJavaStackTraceDepth=-1" -XX:+TieredCompilation "-XX:TieredStopAtLevel=1" -Xverify:none)

# ng on osx, install via brew install nailgun
# ng-nailgun on unbuntu, install via apt-get install nailgun
NG_EXECUTABLE=$(which ng 2>/dev/null|| env which ng-nailgun 2>/dev/null)

# on osx: install via brew install nailgun. /usr/local/Cellar/nailgun/*/libexec/nailgun-server-*.jar
# on unbuntu: install via apt-get install nailgun. /usr/share/java/nailgun.jar
# on debian: install via apt-get install nailgun. /usr/share/java/nailgun-server.jar
# on fedora: install via dnf install nailgun. /usr/share/java/nailgun/nailgun-server.jar
NG_SERVER_JAR=$( \
	find /usr/local/Cellar/nailgun/*/libexec/nailgun-server-*.jar 2>/dev/null \
	|| find /usr/share/java/nailgun.jar 2>/dev/null \
	|| find /usr/share/java/nailgun-server.jar 2>/dev/null \
	|| find /usr/share/java/nailgun/nailgun-server.jar 2>/dev/null \
)

nailgun_installed=0
if ([ "$NG_EXECUTABLE" == "" ] || [ "$NG_SERVER_JAR" == "" ]) && [ "$1" != "direct" ]; then
	nailgun_installed=1
	echo "(Note: nailgun not found. It makes CBT faster! Try 'brew install nailgun' or 'apt-get install nailgun'.)" 1>&2
fi

NAILGUN_PORT=4444
NG="$NG_EXECUTABLE --nailgun-port $NAILGUN_PORT"

if [ "$1" = "kill" ]; then
	echo "Stopping background process (nailgun)" 1>&2
	$NG ng-stop >> "$nailgun_out" 2>> "$nailgun_err" &
	exit 1
fi

which nc >/dev/null 2>/dev/null
nc_installed=$?

log "Check for running nailgun with nc." "$@"

server_up=1
if [ $nc_installed -eq 0 ]; then
	nc -z -n -w 1 127.0.0.1 $NAILGUN_PORT > /dev/null 2>&1
	server_up=$?
else
	echo "(Note: nc not found. It will make slightly startup faster.)" 1>&2
fi

use_nailgun=0
if [  "$1" = "direct" ]; then
	use_nailgun=1
	shift
fi
loop=1
if [ "$1" == "loop" ]; then
	loop=0
	shift
fi
clearScreen=1
if [ "$1" == "clear" ]; then
	clearScreen=0
	shift
fi

if [ $nailgun_installed -eq 1 ] || [ "$1" = "publishSigned" ]; then
	use_nailgun=1
fi

if [ $use_nailgun -eq 0 ] && [ $server_up -eq 0 ] && [ ! "$DEBUG" == "" ]; then
	echo "Can't use \`-debug\` (without \`direct\`) when nailgun is already running. If you started it up with \`-debug\` you can still connect to it. Otherwise use \`cbt kill\` to kill it."
	exit 1
fi

if [ $use_nailgun -eq 0 ] && [ ! $server_up -eq 0 ]; then
	log "Starting background process (nailgun)" "$@"
	# try to start nailgun-server, just in case it's not up
	java "${options[@]}" "${JAVA_OPTS_CBT[@]}" -jar "$NG_SERVER_JAR" 127.0.0.1:$NAILGUN_PORT >> "$nailgun_out" 2>> "$nailgun_err" &
	if [ ! "$DEBUG" == "" ]; then
		echo "Started nailgun server in debug mode"
		exit 1
	fi
fi

stage1 () {
	log "Checking for changes in cbt/nailgun_launcher" "$@"
	NAILGUN_INDICATOR=$NAILGUN$TARGET../classes.last-success
	changed=1
	NAILGUN_SOURCES=("$NAILGUN"*.java "$CBT_HOME"/libraries/common-0/*.java)
	for file in "${NAILGUN_SOURCES[@]}"; do
		if [ "$file" -nt "$NAILGUN_INDICATOR" ]; then changed=0; fi
	done
	exitCode=0
	if [ $changed -eq 0 ]; then
		echo "Stopping background process (nailgun) if running" 1>&2
		$NG ng-stop >> "$nailgun_out" 2>> "$nailgun_err" &
		#rm $NAILGUN$TARGET/cbt/*.class 2>/dev/null # defensive delete of potentially broken class files
		echo "Compiling cbt/nailgun_launcher" 1>&2
		COMPILE_TIME=$(date +%YY%mm%dd%HH%MM.%SS|sed "s/[YmdHMS]//g")
		#echo javac -Xlint:deprecation -Xlint:unchecked -d "$NAILGUN$TARGET" "${NAILGUN_SOURCES[@]}"
		javac -Xlint:deprecation -Xlint:unchecked -d "$NAILGUN$TARGET" "${NAILGUN_SOURCES[@]}"
		exitCode=$?
		if [ $exitCode -eq 0 ]; then
			touch -t "$COMPILE_TIME" "$NAILGUN_INDICATOR"
			if [ $use_nailgun -eq 0 ]; then
				echo "Starting background process (nailgun)" 1>&2
				java "${options[@]}" "${JAVA_OPTS_CBT[@]}" -jar "$NG_SERVER_JAR" 127.0.0.1:$NAILGUN_PORT >> "$nailgun_out" 2>> "$nailgun_err" &
				sleep 1
			fi
		fi
	fi

	log "run CBT and loop if desired. This allows recompiling CBT itself as part of compile looping." "$@"

	if [ $exitCode -eq 0 ]; then
		if [ ! $use_nailgun -eq 0 ]
		then
			log "Running JVM directly" "$@"
			options=($JAVA_OPTS)
			# JVM options to improve startup time. See https://github.com/cvogt/cbt/pull/262
			java "${options[@]}" "${JAVA_OPTS_CBT[@]}" -cp "$NAILGUN$TARGET" cbt.NailgunLauncher "$(time_taken)" "$CWD" "$loop" "$@"
			exitCode=$?
		else
			log "Running via background process (nailgun)" "$@"
			for i in 0 1 2 3 4 5 6 7 8 9; do
				log "Adding classpath." "$@"
				$NG ng-cp "$NAILGUN$TARGET" >> "$nailgun_out" 2>> "$nailgun_err"
				log "Checking if nailgun is up yet." "$@"
				$NG cbt.NailgunLauncher check-alive >> "$nailgun_out" 2>> "$nailgun_err"
				alive=$?
				if [ $alive -eq 131 ] || [ $alive -eq 33 ]; then
				# the 33 is not working right now
				#	echo "Nailgun call failed. Try 'cbt kill' and check the error log cbt/nailgun_launcher/target/nailgun.stderr.log" 1>&2
				#elif [ $alive -eq 33 ]; then
					break
				else
					log "Nope. Sleeping for 0.5 seconds" "$@"
					#if [ "$i" -gt 1 ]; then
					#	echo "Waiting for nailgun to start... (In case of problems try -Dlog=nailgun or check logs in cbt/nailgun_launcher/target/*.log)" 1>&2
					#fi
				fi
				sleep 0.3
			done
			log "Running CBT via Nailgun." "$@"
			$NG cbt.NailgunLauncher "$(time_taken)" "$CWD" "$loop" "$@"
			exitCode=$?
		fi
		log "Done running CBT." "$@"
	fi
}


USER_PRESSED_CTRL_C=130

CBT_LOOP_FILE="$CWD/target/.cbt-loop.tmp"
CBT_KILL_FILE="$CWD/target/.cbt-kill.tmp"
if [ $loop -eq 0 ]; then
	which fswatch >/dev/null 2>/dev/null
	export fswatch_installed=$?
	if [ ! $fswatch_installed -eq 0 ]; then
		echo "please install fswatch to use cbt loop, e.g. via brew install fswatch"
		exit 1
	fi
fi
while true; do
	if [ $clearScreen -eq 0 ]; then
		clear
	fi
	if [ -f "$CBT_LOOP_FILE" ]; then
		rm "$CBT_LOOP_FILE"
	fi
	if [ -f "$CBT_KILL_FILE" ]; then
		rm "$CBT_KILL_FILE"
	fi
	stage1 "$@"
	if [ ! $loop -eq 0 ] || [ $exitCode -eq $USER_PRESSED_CTRL_C ]; then
		log "not looping, exiting" "$@"
		break
	else
		for file in "${NAILGUN_SOURCES[@]}"; do
			echo "$file" >> "$CBT_LOOP_FILE"
		done
		files=
		if [ -f "$CBT_LOOP_FILE" ]; then
			files=($(sort "$CBT_LOOP_FILE"))
		fi
		pids=
		if [ -f "$CBT_KILL_FILE" ]; then
			pids=($(cat "$CBT_KILL_FILE")) # FIXME: should we uniq here?
			#rm "$CBT_LOOP_FILE"
		fi
		echo ""
		echo "Watching for file changes... (ctrl+c short press for loop, long press for abort)"
		for file in "${files[@]}"; do
			if [ $file == "" ]; then
				echo "warning: empty file found in loop file list" 1>&2
			fi
		done
		fswatch --one-event "${files[@]}"
		for pid in "${pids[@]}"; do
			if [ $pid == "" ]; then
				echo "warning: empty pid found in pid kill list" 1>&2
			else
				log "killing process $pid"
				kill -KILL $pid
			fi
		done
	fi
done

log "Exiting CBT" "$@"
exit $exitCode