#
# @(#)GNUmakefile	1.124 98/12/16
#
# Makefile for Java interpreter 
#

BUILDDIR = ../..
include $(BUILDDIR)/Platform.gmk
LIBRARY = jvm
PRODUCT = java
PACKAGE = java.lang
LIB_LOCATION = $(LIBDIR)/$(ARCH)/classic
include $(BUILDDIR)/makefiles/Defs.gmk

#
# Files common to all ports:
#
include $(MINCLUDES)jvm.cmk
include $(MINCLUDES)jvm.jmk

#
# Utility for installing a file.  Should be moved to a more general
# place for rules. 
#
define install-file
@echo Installing $@
@mkdir -p $(@D)
@$(RM) $@
@cp $< $@
endef

#
# Solaris-specific files
#
FILES_c += \
	$(TARGDIR)signals_md.c \
	$(TARGDIR)gc_md.c \
	$(TARGDIR)javai_md.c \
	$(OTHER_JVM_c)

ifeq ($(ARCH),sparc)
ARCHNAME = sparc
FILES_s += $(TARGDIR)machgc_$(ARCHNAME).s
FILES_s += $(TARGDIR)invokeNative_sparc.s
else
ARCHNAME = p5
FILES_c += $(TARGDIR)machgc_nonsparc.c
FILES_s += $(TARGDIR)invokeNative_x86.s
endif

ifeq ($(VARIANT),OPT)
ifdef QUANTIFY
FILES_c += executeJava_$(ARCHNAME).c
else
FILES_s += $(TARGDIR)executeJava_$(ARCHNAME).s
FILES_c += $(TARGDIR)runtimeHelper_$(ARCHNAME).c
endif
endif

#
# Create the classic subdirectory.
#
INIT = $(LIB_LOCATION)

#
# For the VM dll, FILES_export is infact FILES_java.
#
FILES_export = $(FILES_java)

#
# Native methods in inner classes are currently a pain. 
#   - Make sure the outer class is in FILES_export or FILES_java, so
#     the outer class will get compiled.
#   - Then set EXPORTED_inner so javah will be run on the inner class.
#
EXPORTED_inner = 

#
# Add to the default C and assembly file search paths.  Allow
# $(PLATFORM_SRC)/javavm variants to override $(SHARE_SRC)/javavm versions.
# Clear any initial vpath settings to ensure that we don't look in
# unexpected places for JVM files.
#
vpath %.c
vpath %.c   $(PLATFORM_SRC)/javavm/runtime:$(SHARE_SRC)/javavm/runtime

vpath %.s
vpath %.s   $(PLATFORM_SRC)/javavm/runtime

#
# Tell Library.gmk that this file must be installed as well.
#
INIT = $(LIB_LOCATION)/Xusage.txt

#
# Tell Library.gmk that we are interested in creating a mapfile for
# this shared library.
#
ifeq ($(PRIVATIZE_JVM_SYMBOLS),true)
LINK_WITH_MAPFILE = true
endif

#
# Rules.
#
include $(BUILDDIR)/makefiles/Library.gmk

#
# Includes for JVM only
#
OTHER_INCLUDES = -I$(PLATFORM_SRC)/javavm/include \
		 -I$(PLATFORM_SRC)/hpi/export \
		 -I$(PLATFORM_SRC)/native/common \
		 -I$(SHARE_SRC)/javavm/include \
		 -I$(SHARE_SRC)/hpi/export \
		 -I$(SHARE_SRC)/native/common

#
# Optional local flags with defaults: turn on from command line like
#
#   % gnumake PAGED_HEAPS=true HEAPMETERS=true
#

# By default use a contiguous (memory mapped) heap
PAGED_HEAPS = false
ifeq ($(PAGED_HEAPS), true)
    CPPFLAGS_COMMON += -DPAGED_HEAPS
endif

# By default do not compile to record statistics
STATISTICS = false
ifeq ($(STATISTICS), true)
    CPPFLAGS_COMMON += -DSTATISTICS
endif

# By default disable heap metering
HEAPMETERS = false
ifeq ($(HEAPMETERS), true)
    CPPFLAGS_COMMON += -DHEAPMETERS
endif

# By default leave out locking statistics
LOCKSTATS = false
ifeq ($(LOCKSTATS), true)
    CPPFLAGS_COMMON += -DLOCKSTATS
endif

# By default compile in heap profiler
HPROF = true
ifeq ($(HPROF), true)
    CPPFLAGS_COMMON += -DHPROF
endif

# By default enable JNI check support
CHECK_JNI = true
ifeq ($(CHECK_JNI), true)
    CPPFLAGS_COMMON += -DCHECK_JNI
endif

# By default enable JCOV support in debug build.
JCOV = true
ifeq ($(JCOV), true)
ifeq ($(VARIANT), DBG)
    CPPFLAGS_COMMON += -DJCOV
endif
endif

CPPFLAGS_COMMON += -DBREAKPTS
CPPFLAGS_OPT    += -DTRIMMED
CPPFLAGS_DBG    += -DTRACING -DJCOV

ifeq ($(CC_VERSION),gcc)
CPPFLAGS_COMMON += -DHAVE_ALIGNED_LONGLONGS -DHAVE_ALIGNED_DOUBLES
endif

CPPFLAGS_COMMON += $(VERSION_DEFINES)

#
# Bootstrap stage.
#
JAVAC_CMD = $(JAVAC_BOOT_CMD)
JAVAH_CMD = $(JAVAH_BOOT_CMD)

OTHER_LDLIBS += -lm -lnsl -ldl

ifneq ($(CC_VERSION), gcc)
OTHER_CFLAGS += $(PLATFORM_SRC)/javavm/runtime/mflush_$(ARCH).il
endif

#
# Generate specialized invokers.
#
InvokerGen.class: $(SHARE_SRC)/javavm/runtime/InvokerGen.java
	$(JAVAC_BOOT) -d . -nowarn $<

invokers.c: InvokerGen.class

invokers.c: $(SHARE_SRC)/javavm/include/invokers.txt
	$(RM) $@
	$(BOOTDIR)/bin/java -classpath . InvokerGen < $< > $@

#
# Install the non-standard VM usage message file
#
$(LIB_LOCATION)/Xusage.txt: $(SHARE_SRC)/javavm/include/Xusage.txt
	@$(RM) $@
	mkdir -p $(LIB_LOCATION)
	sed "s/by ;/by :/" $< > $@

#
# Extra cleanups.
#
clean:: FORCE
	$(RM) invokers.c *.class
	$(RM) ExecuteJavaStructOffsets.include ExecuteJavaPadding.include \
	      executeJava_sparc_no_padding.o executeJava_sparc_no_padding.s
	$(RM) opcodes.wide make_struct_offsets*
	$(RM) lexer.c parser.c *.o *.asm *.s masm2as
	$(RM) y.output y.tab.h fjconst.inc fjtables.inc
	$(RM) includes_p5 new.ExecuteJavaStructOffsets.include
	$(RM) .install.generated.includes
	$(RM) $(LIBDIR)/$(ARCH)/Xusage.txt

#
# Workaround for 4098037: add -xO1 to lower the optimization level
#
ifneq ($(CC_VERSION), gcc)
ifeq ($(ARCH),i386)
$(OBJDIR)/jvm.o: jvm.c
    ifdef VARIANT
	$(COMPILE.c) -xO1 -o $@ $<
	@$(CC) -xM1 $(CPPFLAGS) $< 2> /dev/null | \
	sed 's!$*\.o!$(dir $@)&!g' | sort | uniq > $(@:.o=.d)
    else
	$(MAKE) $@ VARIANT=OPT
    endif
endif
endif

#
# Special rule for compiling jni.c without inlining (Sun C compiler only).
# Has large effect on the size of jni.o on SPARC, none on x86.
#
ifneq ($(CC_VERSION), gcc)
$(OBJDIR)/jni.o: jni.c
    ifdef VARIANT
	$(COMPILE.c) -xinline= -o $@ $<
	@$(CC) -xM1 $(CPPFLAGS) $< 2> /dev/null | \
	sed 's!$*\.o!$(dir $@)&!g' | sort | uniq > $(@:.o=.d)
    else
	$(MAKE) $@ VARIANT=OPT
    endif
endif

#
# If using GNU m4, we need to pass additional flags.
#
ifdef USE_GNU_M4
GNUM4FLAG = --traditional
endif
M4FLAGS = $(GNUM4FLAG)

ifdef QUANTIFY
executeJava_$(ARCH).c: executeJava.c
	ln -s $? $@

$(OBJDIR)/executeJava_$(ARCH).o: executeJava_$(ARCH).c
	$(COMPILE.c) -UBREAKPTS -o $@ $<

else

#
# Rules for building SPARC-specific executeJava.
#
$(OBJDIR)/executeJava_sparc.o: \
		$(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s \
		ExecuteJavaPadding.include ExecuteJavaStructOffsets.include \
		opcodes.wide
	$(AS) -m -o $(OBJDIR)/executeJava_sparc.o \
		$(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s
	nawk -f check_offsets.nawk < $(SHARE_SRC)/javavm/include/opcodes.list \
		| adb $(OBJDIR)/executeJava_sparc.o -

ExecuteJavaPadding.include: \
		$(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s \
		ExecuteJavaStructOffsets.include opcodes.wide
	m4 $(M4FLAGS) -DEXTRACT_TABLE_PADDING \
		$(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s \
	      > executeJava_sparc_no_padding.s
	$(AS) executeJava_sparc_no_padding.s
	nm -h executeJava_sparc_no_padding.o | egrep "pad[0-9]+" \
		| sort "-t|" +7.3n \
		| nawk -F "|" '/./{print "define( " $$8 ", " $$2")"}' \
	      > ExecuteJavaPadding.include

ExecuteJavaStructOffsets.include: $(OBJDIR)/make_struct_offsets.o
	$(CC) $(CFLAGS_COMMON) -o make_struct_offsets \
		$(OBJDIR)/make_struct_offsets.o
	./make_struct_offsets > new.ExecuteJavaStructOffsets.include
	-cmp -s new.ExecuteJavaStructOffsets.include \
		ExecuteJavaStructOffsets.include \
	     || mv new.ExecuteJavaStructOffsets.include \
		ExecuteJavaStructOffsets.include

make_struct_offsets.c: $(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s 
make_struct_offsets.c: extract_offsets.nawk opcodes.wide
	m4 $(M4FLAGS) -DEXTRACT_OFFSETS \
		$(PLATFORM_SRC)/javavm/runtime/executeJava_sparc.s \
		| sort -u | nawk -f extract_offsets.nawk \
	      > make_struct_offsets.c

executeJava_p5.s: executeJava_p5.asm masm2as
	./masm2as -gcc < executeJava_p5.asm > executeJava_p5.s

executeJava_p5.asm: includes_p5 \
		$(SHARE_SRC)/javavm/runtime/executeJava_p5.m4 \
		$(SHARE_SRC)/javavm/runtime/executeJava_p5.inc
	$(RM) fjconst.inc
	$(RM) fjtables.inc
	$(RM) executeJava_p5.asm
	./includes_p5  .
	m4 $(M4FLAGS) -B 8192 -DSOLARIS -DCPU=5 \
		$(SHARE_SRC)/javavm/runtime/executeJava_p5.m4 > \
		executeJava_p5.asm
	m4 $(M4FLAGS) -B 8192 -DSOLARIS -DCPU=6 \
		$(SHARE_SRC)/javavm/runtime/executeJava_p5.m4 >> \
		executeJava_p5.asm
	chmod a=rx executeJava_p5.asm
	chmod a=rx fjconst.inc
	chmod a=rx fjtables.inc

opcodes.wide: $(SHARE_SRC)/javavm/include/opcodes.wide
	$(install-file)

endif

includes_p5: $(shell pwd)/opcodes.c $(OBJDIR)/includes_p5.o 
	$(CC) -o $@ $(OBJDIR)/includes_p5.o 

$(shell pwd)/opcodes.c: $(SHARE_SRC)/javavm/runtime/opcodes.c
	$(install-file)

YFLAGS = -d -v
LFLAGS = -n

#
# Define this to -lfl if you are using flex.
#
ifndef LEX_LIBRARY
LEX_LIBRARY="-ll"
endif

masm2as: parser.o lexer.o
	$(CC) parser.o lexer.o $(LEX_LIBRARY) -o masm2as

#
# We can't use the normal cc flags because it generates warnings
#
lexer.o: lexer.c   
	$(CC) -c lexer.c

parser.o: parser.c
	$(CC) -c parser.c

#
# Rules to create a mapfile, privatizing symbols. We exclude:
#	- JVM_ and JVMDI_ symbols
#       - and things from jvmexp.lcf, because that includes symbols
#         for the JNI invocation API and also those symbols that are
#         thought of as support for the old NMI.
#
# Note: This mapfile with scoping rules might not work on certain
# configurations of Solaris 2.4.  We believe you will need patch
# 102303-05.  However we notice that a Solaris 2.4 without this patch
# also appears to work -- the possible cause being 102049-03, but we
# can not confirm this.
#
$(LIBRARY)$(SUFFIX).$(ARCH).mapfile: $(FILES_o)
	@echo Generating $@ ...
	@echo '{' > $@
	@echo '  local: ' >> $@
	@echo '          *;' >> $@
	@echo '  global: ' >> $@
	@nm $(FILES_o) | \
	    awk -F\| '($$5 == "GLOB " && $$7 != "UNDEF  ") { print $$8; }' | \
	    egrep '^JVMDI_|^JVM_' > $@.tmp
	@sed 's/^#.*//g;s/^-export://g' $(MINCLUDES)/jvmexp.lcf >> $@.tmp
	@uniq -u $@.tmp | grep -v '^$$' | sed 's/^/          /g;s/$$/;/g' >> $@
	@echo '};' >> $@
	@$(RM) $@.tmp

clean::
	$(RM) $(LIBRARY).$(ARCH).mapfile
	$(RM) $(LIBRARY)$(DBG_SUFFIX).$(ARCH).mapfile

#
# Make the directories of include files shipped with the JDK.
#

#
# Regular header files.
#
FILES_h = $(INCLUDEDIR)/jni.h 			\
	  $(INCLUDEDIR)/$(PLATFORM)/jni_md.h	\
	  $(INCLUDEDIR)/jvmdi.h			\
	  $(INCLUDEDIR)/jvmpi.h

$(INCLUDEDIR)/%.h: $(SHARE_SRC)/javavm/export/%.h
	$(install-file)
$(INCLUDEDIR)/$(PLATFORM)/%.h: $(PLATFORM_SRC)/javavm/export/%.h
	$(install-file)

#
# Old NMI header files.  Note that not all header files are required for
# the old native method interface, but since the header files are not
# properly organized at this time, we ship the whole wad.
#
OINCLUDEDIR = $(INCLUDEDIR)-old

DIRS   = javavm/include javavm/export hpi/export
S_DIRS = $(patsubst %,$(SHARE_SRC)/%, $(DIRS))
P_DIRS = $(patsubst %,$(PLATFORM_SRC)/%, $(DIRS))

OLDFILES_h = $(foreach d, $(S_DIRS),				   	   \
	      $(subst $d, $(OINCLUDEDIR), $(shell ls $d/*.h)))	   	   \
	     $(foreach d, $(P_DIRS),					   \
	      $(subst $d, $(OINCLUDEDIR)/$(PLATFORM), $(shell ls $d/*.h))) \
	     $(OINCLUDEDIR)/java_lang_String.h 				   \
	     $(OINCLUDEDIR)/java_lang_ClassLoader.h			   \
	     $(OINCLUDEDIR)/java_lang_Thread.h				   \
	     $(OINCLUDEDIR)/java_lang_ThreadGroup.h

$(OINCLUDEDIR)/$(PLATFORM)/%.h: $(PLATFORM_SRC)/hpi/export/%.h
	$(install-file)
$(OINCLUDEDIR)/$(PLATFORM)/%.h: $(PLATFORM_SRC)/javavm/include/%.h
	$(install-file)
$(OINCLUDEDIR)/%.h: $(SHARE_SRC)/javavm/include/%.h
	$(install-file)
$(OINCLUDEDIR)/%.h: $(SHARE_SRC)/hpi/export/%.h
	$(install-file)
$(OINCLUDEDIR)/$(PLATFORM)/%.h: $(PLATFORM_SRC)/javavm/export/%.h
	$(install-file)
$(OINCLUDEDIR)/%.h: $(SHARE_SRC)/javavm/export/%.h
	$(install-file)
$(OINCLUDEDIR)/java_lang_String.h: $(CLASSHDRDIR)/java_lang_String.h
	$(install-file)
$(OINCLUDEDIR)/java_lang_ClassLoader.h: $(CLASSHDRDIR)/java_lang_ClassLoader.h
	$(install-file)
$(OINCLUDEDIR)/java_lang_Thread.h: $(CLASSHDRDIR)/java_lang_Thread.h
	$(install-file)
$(OINCLUDEDIR)/java_lang_ThreadGroup.h: $(CLASSHDRDIR)/java_lang_ThreadGroup.h
	$(install-file)

#
# Rules to install the wads defined above.
#
ifndef JAE_ONLY
$(OPTIMIZED) $(DEBUG):: $(FILES_h) $(OLDFILES_h)

clobber:: FORCE
	$(RM) -r $(INCLUDEDIR) $(OINCLUDEDIR)
endif

JAVAHFLAGS += -old
