Hi,
Recently I've been trying out some massive code reorganizations in DRLVM
code in order to improve its modularity (especially concerning
interpreter vs. JIT issue), and that involved mass moving of source
files between components and frequent recompilations, as I am trying
to use resulting compiler and linker errors as a guidance on what else
needs to be done.
Unfortunately, this kind of exercise proves the current ant-based build
system highly inconvenient, as it has following problems:
* It neither cleans up stale object files, nor uses object file lists,
so in case .cpp file was moved, the subsequent rebuild will link the
stale object file.
The obvious workaround is to do a 'build.sh clean', but this is very
time consuming (~5 min on my machine)
* Even in case of simple changes to several .cpp files, the compilation
process takes unacceptably long time. In the extreme, the 'build.sh'
command with no changes at all takes about 51 seconds on my machine.
* Ant does not support parallel builds (and my machine is dual-core)
In order to make the workflow more effcient (so as not to spend too much
time on recompilation), I've created a build system using GNU Make from
scratch. It uses a little bit of makefile generation on-the-fly, but
it is relatively simple:
(a) dependencies are tracked using 'makedepend'
(b) individual file compilation rules are generated from source lists by
a very simple shell script, which generates output like the following:
$ gen-sources-make *.cpp
OBJECTS :=
DEPENDS :=
OBJECTS := $(OBJ)/a.o
$(OBJ)/a.o: a.c
makedepend $(CPPFLAGS) $< > a.d
$(CC) -c -o $@ $<
... (repeat the above for each source file)
The end result is included into the makefile. This is needed for two
reasons: (1) flatten object file directory (i.e. source files from a
deep tree will have a flat list of corresponding object files)
(2) to get the list of object files explicitly, in order to prevent
erroneous linking of stale object files.
The resulting build system has the following advantages over current
ant-based system:
+ No-recompilation run is fast: 3 sec (with hot cache) vs. 51 sec with
current system
+ Stale object files are not linked, even without cleaning
+ Parallel make is supported
+ The output is nice and clean, without noise
+ The configuration files (e.g. vm/em/Makefile) are shorter, and the whole
build process is far easier to understand (to me anyway)
However, it also has some disadvantages, compared to the ant system
* It only covers building of the native targets (libraries and
executables), so testing and class/jar building is not covered.
If this system is accepted, it will probably be called from ant.
* It does not support multiple file compilation with a single compiler
invocation, and executes compiler once for each source file, which
may be a real performance problem for some platforms
(e.g. Windows/Intel compiler). While some hacks to alleviate this
issue exist for initial compilation, I am not aware of any general
Make-based solution.
The result is an attached patch. I do not file a JIRA with patch because
it is obviously not (yet) suitable for inclusion.
I would like to hear the comments on the approach and general view on
whether DRLVM needs yet another one build system.
build/Makefile | 58 +++++++++
build/gen-sources-make | 55 +++++++++
build/makerules.inc | 263 ++++++++++++++++++++++++++++++++++++++++++
vm/em/Makefile | 25 ++++
vm/gc_cc/Makefile | 21 ++++
vm/gc_gen/Makefile | 19 +++
vm/interpreter/Makefile | 26 ++++
vm/jitrino/Makefile | 47 ++++++++
vm/port/Makefile | 28 +++++
vm/port/src/encoder/Makefile | 11 ++
vm/thread/Makefile | 30 +++++
vm/thread/jthread/Makefile | 21 ++++
vm/vmcore/Makefile | 62 ++++++++++
vm/vmi/Makefile | 22 ++++
14 files changed, 688 insertions(+), 0 deletions(-)
In addition to disadvantages mentioned above, it is not complete, and
misses following items, though these can be implemented easily
provided there is enough interest (as the system already does everything
I personally need).
* Configuration is currently written for Linux/ia32/gcc/debug only.
* Deployment of built targets is currently rather crude (using cp -u)
* I've just noticed that some changes happened after the I started doing this,
so the Makefiles with source lists will need some update too.
Comments are welcome.
diff --git build/Makefile build/Makefile
new file mode 100644
index 0000000..3b59a6b
--- /dev/null
+++ build/Makefile
@@ -0,0 +1,58 @@
+#
+# Run 'make help' for help on using build system
+#
+# List of submodules in the dependency order
+
+SUBDIRS := \
+ ../vm/port \
+ ../vm/port/src/encoder \
+ ../vm/thread \
+ ../vm/thread/jthread \
+ ../vm/vmcore \
+ ../vm/em \
+ ../vm/gc_cc \
+ ../vm/gc_gen \
+ ../vm/interpreter \
+ ../vm/jitrino \
+ ../vm/vmi \
+
+#-----------------
+export TOP := $(abspath ..)
+
+.PHONY: all clean distclean
+all:
+ $(Q)set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done
+ # FIXME: deploy
+ $(Q)cp -uv lnx_ia32_gcc_debug/semis/bin/*
lnx_ia32_gcc_debug/deploy/jdk/jre/bin/default
+
+clean distclean:
+ $(Q)set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done
+
+help:
+ # Make system requires GNU Make, sed, coreutils (cp, uname etc.),
+ # makedepend, /bin/sh
+ #
+ # Supported targets
+ # make all - build all libraries and executables
+ # make clean - clean object files and libraries
+ # make distclean - clean all make artifacts (configuration)
+ #
+ # make -j2 - parallel make is supported
+ # make V=1 - verbose make mode, prints full commands
+
+#-----------------
+# fix dependencies for parallel make
+ifneq ($(filter clean,$(MAKECMDGOALS)),)
+all: clean
+endif
+ifneq ($(filter distclean,$(MAKECMDGOALS)),)
+all: distclean
+endif
+
+# provide silent mode unless user runs 'make V=1'
+ifeq ($(findstring s,$(MAKEFLAGS)),)
+ifndef V
+ MAKEFLAGS += --no-print-directory
+ Q = @
+endif
+endif
diff --git build/gen-sources-make build/gen-sources-make
new file mode 100755
index 0000000..2b210aa
--- /dev/null
+++ build/gen-sources-make
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+#
+# Generates includable makefile with compilation rules
+# for C, C++ and assembler sources
+#
+# Usage:
+# gen-sources-make <source-files> ...
+#
+# Notes on the constructed make file:
+# * object files are placed in flat $(OBJ) directory
+# * $(OBJ) directory creating via $(OBJ)/.stamp dependency
+# * it collects object file list suitable for linker in $(OBJECTS)
+# * it collects dependencies list suitable for '-include' in $(DEPENDS)
+#
+
+die () {
+ echo "$@" >&2
+ exit 1
+}
+
+echo "OBJECTS :="
+echo "DEPENDS :="
+
+for i in "$@"; do
+ case "$i" in
+ *.c)
+ o='$(OBJ)/'`basename "$i" .c`.o
+ d='$(OBJ)/'`basename "$i" .c`.d
+ echo "OBJECTS += $o"
+ echo "DEPENDS += $d"
+ echo "$o: $i" '$(OBJ)/.stamp'
+ echo ' $(Q)makedepend -f - -Y $(CPPFLAGS) $< 2>/dev/null | sed
-r' "'"'s#^(.*).o:#$(OBJ)/\1.d $(OBJ)/\1.o:#; s#: (.*)$$#: $$(wildcard \1)#'"'"
'> $(subst .o,.d,$@)'
+ echo ' $(QUIET_CC)$(CC) -c -o $@ $(CFLAGS) $(CPPFLAGS) $<'
+ ;;
+ *.cpp)
+ o='$(OBJ)/'`basename "$i" .cpp`.o
+ d='$(OBJ)/'`basename "$i" .cpp`.d
+ echo "OBJECTS += $o"
+ echo "DEPENDS += $d"
+ echo "$o: $i" '$(OBJ)/.stamp'
+ echo ' $(Q)makedepend -f - -Y $(CPPFLAGS) $< 2>/dev/null | sed
-r' "'"'s#^(.*).o:#$(OBJ)/\1.d $(OBJ)/\1.o:#; s#: (.*)$$#: $$(wildcard \1)#'"'"
'> $(subst .o,.d,$@)'
+ echo ' $(QUIET_CXX)$(CXX) -c -o $@ $(CXXFLAGS) $(CPPFLAGS) $<'
+ ;;
+ *.asm)
+ o='$(OBJ)/'`basename "$i" .asm`.o
+ echo "OBJECTS += $o"
+ echo "$o: $i" '$(OBJ)/.stamp'
+ echo ' $(QUIET_AS)$(AS) -o $@ $(ASFLAGS) $<'
+ ;;
+ *)
+ die "Error: unsupported source file: $i"
+ ;;
+ esac
+done
diff --git build/makerules.inc build/makerules.inc
new file mode 100644
index 0000000..9dc014e
--- /dev/null
+++ build/makerules.inc
@@ -0,0 +1,263 @@
+#-------------
+#
+# Author: [EMAIL PROTECTED]
+# Credits: some tricks stolen from prior work
+# by John GrahamCumming and Tom Tromey.
+#
+# Main make rules for inclusion.
+#
+# Usage:
+#
+# 0) Each buildable artifact (shared or static library, or executable)
+# needs to have its own dedicated Makefile in a separate directory.
+#
+# 1) Makefile should define following variables
+#
+# TYPE = executable | library | shared - type of the target
+# NAME - base name of the target file
+# SOURCES - list of source files
+#
+# 2) optionally define following compilation variables
+# (all lists space-separated)
+#
+# INCLUDES - list of include directories, it will end up in
+# to $(CPPFLAGS) with -I added automatically
+# DEFINES - list of macros, it will end up in $(CPPFLAGS),
+# with -D added automatically
+#
+# 3) Link time dependencies (space separated list of non-decorated names,
+# i.e. without 'lib' prefix or '.so' suffix)
+#
+# Dependencies on libraries built earlier
+# (as they were specified in NAME variable in respective Makefile):
+# LIBDEPENDS - list of static libraries this target depends on (built by
+# this make system, supposed to be in $(LIB))
+# SODEPENDS - list of shared libraries this target depends on (built by
+# this make system, supposed to be in $(BIN))
+#
+# Dependencies on system or 3rd-party libraries
+# LIBS - list of 3rd-party libraries to link
+# LIBDIRS - list of directories to search 3rd-party libraries
+#
+# Note, that you need not put -l or -L either, as it will be added
+# by the makefile automatically.
+#
+# 4) include rules.inc at the end of Makefile
+#
+# The following targets are available:
+#
+# make all - build the target
+# make clean - clean the compilation artifacts (object files and target)
+# make distclean - clean all build artifacts, including build system
+# configuration
+#
+# The following variables, defined below in this file, control the
+# placement of build artifacts:
+# $(BIN) - a place for executables and shared libraries
+# $(LIB) - a place for static libraries
+# $(OBJ) - a place for object files
+#
+# * Note: both $(BIN) and $(LIB) are supposed to be the same for all
+# targets built by this system, while $(OBJ) is target-specific
+# in order to prevent conflicts of object files with the same name.
+#
+# This file also defines some DEFINES and compilation flags common for the
+# DRLVM project
+#
+
+#-------------
+# Build variables setup
+
+# some predefined build flags
+# NB Using '+=' is important, as this file is included)
+DEFINES += _DEBUG VM_STATS _IA32_ PLATFORM_POSIX LINUX __SMP__ _REENTRANT \
+ LINUX_TLS_OPT _LARGEFILE64_SOURCE
+
+lnx_CXXFLAGS += -fpic
+lnx_CFLAGS += -fpic
+
+# skip shell commands if we already have the identifiers
+ifndef OSTAG
+# platform identifiers
+OS := $(shell uname -s)
+OSTAG := $(shell echo $(OS) | sed 's/Linux/lnx/; s/Cygwin.*/win/i;
s/Windows.*/win/i;')
+ARCH := $(shell uname -m)
+ARCHTAG := $(shell echo $(ARCH) | sed 's/x86_64/em64t/; s/ia64/ipf/;
s/i686/ia32/;')
+endif
+
+ifndef TOP
+# this is a guess, using knowledge on the directory layout,
+# if somehow TOP was not defined (e.g. component Makefile run
+# directly rather than from top-level Makefile)
+TOP := $(abspath $(wildcard ../../vm/vmcore \
+ ../../../vm/vmcore \
+ ../../../../vm/vmcore)/../..)
+endif
+
+# configuration
+CC := gcc
+CFG := debug
+
+# common paths
+VM := $(TOP)/vm
+BUILD := $(TOP)/build
+SEMIS := $(BUILD)/$(OSTAG)_$(ARCHTAG)_$(CC)_$(CFG)/semis
+DEPLOY:= $(BUILD)/$(OSTAG)_$(ARCHTAG)_$(CC)_$(CFG)/deploy
+CLASSLIB := $(abspath $(TOP)/../classlib)
+
+# build directories
+#
+# NB: $(BIN) and $(LIB) should be the same for all components
+# in order to component interdependencies to function
+BIN := $(SEMIS)/bin
+LIB := $(SEMIS)/lib
+# $(OBJ) is advisably separate for components to reduce the probablity
+# for object file name conflict, so include /$(NAME)/ path component
+OBJ := $(SEMIS)/vm/$(NAME)/_obj
+
+ifndef NAME
+$(error Makefile must define NAME, see makerules.inc for instruction)
+endif
+
+#-------------
+# (variable names based off unix conventions)
+
+ifeq ($(OS),Linux)
+# .exe suffix (with dot)
+exe :=
+# library prefix
+lib := lib
+# shared library suffix (without dot)
+so := so
+# static library suffix (without dot)
+a := a
+else
+# not linux supposed to be windows
+exe := .exe
+lib :=
+so := dll
+a := lib
+endif
+
+#-------------
+# platform and configuration specific amendments
+
+DEFINES += $($(OSTAG)_DEFINES) $($(ARCH)_DEFINES) $($(CFG)_DEFINES)
+INCLUDES += $($(OSTAG)_INCLUDES) $($(ARCH)_INCLUDES)
+CFLAGS += $($(OSTAG)_CFLAGS)
+CXXFLAGS += $($(OSTAG)_CXXFLAGS)
+
+#-------------
+# main target
+
+ifeq ($(TYPE),executable)
+PROGRAM := $(NAME)$(exe)
+TARGET := $(BIN)/$(PROGRAM)
+else ifeq ($(TYPE),shared)
+SHARED := $(lib)$(NAME).$(so)
+TARGET := $(BIN)/$(SHARED)
+else ifeq ($(TYPE),library)
+LIBRARY := $(lib)$(NAME).$(a)
+TARGET := $(LIB)/$(LIBRARY)
+endif
+
+ifndef TYPE
+$(error Makefile must define TYPE = executable | library | shared)
+endif
+
+.PHONY: all
+all:
+ $(Q)$(MAKE) $(TARGET)
+
+#-------------
+# silent rules
+ifeq ($(findstring s,$(MAKEFLAGS)),)
+ifndef V
+ QUIET_CC = @echo 'CC ' $(@F);
+ QUIET_CXX = @echo 'CXX ' $(@F);
+ QUIET_LD = @echo 'LD ' $(@F);
+ QUIET_AS = @echo 'AS ' $(@F);
+ QUIET_AR = @echo 'AR ' $(@F);
+ Q = @
+endif
+endif
+
+#-------------
+# target dependencies on other targets (static or shared libraries)
+ifdef LIBDEPENDS
+$(TARGET): $(addprefix $(LIB)/$(lib),$(addsuffix .$(a),$(LIBDEPENDS)))
+LIBDIRS += $(LIB)
+endif
+ifdef SODEPENDS
+$(TARGET): $(addprefix $(BIN)/$(lib),$(addsuffix .$(so),$(SODEPENDS)))
+LIBDIRS += $(BIN)
+endif
+# order is important, system libs should be last, static libraries next,
+# and shared libraries first, meaning the least priority (last has highest
priority)
+LIBS := $(SODEPENDS) $(LIBDEPENDS) $(LIBS)
+LDLIBS += $(addprefix -l,$(LIBS)) $(addprefix -L,$(LIBDIRS))
+#-------------
+# compilation flags
+
+CPPFLAGS := $(addprefix -D,$(DEFINES)) $(addprefix -I,$(INCLUDES))
+
+#-------------
+# include stored configuration
+SOURCES_MAKE := $(OBJ)/sources.make
+-include $(SOURCES_MAKE)
+-include $(DEPENDS)
+
+#-------------
+# sources.make generation
+
+# detect the changes in sources by storing a fingerprint (may use hash)
+CONFIG := $(SOURCES)
+ifneq ($(CONFIG),$(OLD_CONFIG))
+$(TARGET): $(SOURCES_MAKE)
+endif
+
+$(SOURCES_MAKE): Makefile $(BUILD)/gen-sources-make $(OBJ)/.stamp
+ $(Q)echo "OLD_CONFIG = $(CONFIG)" > $@
+ $(Q)$(BUILD)/gen-sources-make $(SOURCES) >> $@
+
+#-------------
+# build rules
+
+ifeq ($(TYPE),executable)
+$(TARGET): $(OBJECTS) $(dir $(TARGET))/.stamp
+ $(QUIET_LD)$(CC) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
+else ifeq ($(TYPE),shared)
+$(TARGET): $(OBJECTS) $(dir $(TARGET))/.stamp
+ $(QUIET_LD)$(CC) -shared -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
+else ifeq ($(TYPE),library)
+$(TARGET): $(OBJECTS) $(dir $(TARGET))/.stamp
+ $(QUIET_AR)$(AR) rcs $@ $(OBJECTS)
+endif
+
+#-------------
+# directory and stamp creation rules
+%.stamp:
+ $(Q)mkdir -p $(@D) && touch $@
+
+#-------------
+# clean and distclean rules
+
+# make sure compilation does not start before clean is complete
+# 'all: ; make $(TARGET)' comes in handy for this trick,
+# as it ensures no compilation target will start simultaneously with clean
+ifneq ($(filter $(MAKECMDGOALS),clean),)
+all: clean
+endif
+.PHONY: clean
+clean:
+ $(RM) $(TARGET) $(OBJECTS)
+
+ifneq ($(filter $(MAKECMDGOALS),distclean),)
+all: distclean
+endif
+.PHONY: distclean
+distclean:
+ $(RM) -r $(BIN) $(OBJ)
+
+#-------------
+# vim:ft=make
diff --git vm/em/Makefile vm/em/Makefile
new file mode 100644
index 0000000..64f7ed2
--- /dev/null
+++ vm/em/Makefile
@@ -0,0 +1,25 @@
+NAME = em
+TYPE = shared
+
+DEFINES = BUILDING_EM
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/port/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ src \
+ $(VM)/vmcore/src/util/linux/include \
+
+SOURCES = $(wildcard src/*.cpp)
+
+CXXFLAGS += -Wno-deprecated -fno-exceptions -fpic
+
+LDFLAGS += -Wl,--export-dynamic
+SODEPENDS = harmonyvm hythr
+LIBDEPENDS = encoder
+LIBS = apr-1 m dl stdc++ z xml2 pthread
+LIBDIRS = \
+ $(SEMIS)/extra/apr/_bin \
+
+include ../../build/makerules.inc
diff --git vm/gc_cc/Makefile vm/gc_cc/Makefile
new file mode 100644
index 0000000..c4b8243
--- /dev/null
+++ vm/gc_cc/Makefile
@@ -0,0 +1,21 @@
+NAME = gc_cc
+TYPE = shared
+
+DEFINES = BUILDING_GC
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/port/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ $(VM)/vmcore/src/util/linux/include \
+
+SOURCES = $(wildcard src/*.cpp)
+
+LDFLAGS = -Wl,-Bsymbolic
+SODEPENDS = hythr
+LIBS = apr-1
+LIBDIRS = \
+ $(SEMIS)/extra/apr/_bin \
+
+include ../../build/makerules.inc
diff --git vm/gc_gen/Makefile vm/gc_gen/Makefile
new file mode 100644
index 0000000..44e9cb5
--- /dev/null
+++ vm/gc_gen/Makefile
@@ -0,0 +1,19 @@
+NAME = gc_gen
+TYPE = shared
+
+DEFINES = BUILDING_GC
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/port/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ $(VM)/vmcore/src/util/linux/include \
+
+SOURCES := \
+ $(shell find -name '*.cpp')
+
+LDFLAGS = -Wl,-Bsymbolic
+SODEPENDS = hythr
+
+include ../../build/makerules.inc
diff --git vm/interpreter/Makefile vm/interpreter/Makefile
new file mode 100644
index 0000000..ddb70c8
--- /dev/null
+++ vm/interpreter/Makefile
@@ -0,0 +1,26 @@
+NAME = interpreter
+TYPE = shared
+
+DEFINES = USE_DLL_JIT BUILDING_JIT
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/port/include \
+ $(VM)/port/src/encoder/ia32_em64t \
+ $(VM)/port/src/lil/ia32/pim/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ $(VM)/vmcore/src/util/linux/include \
+ $(VM)/vmcore/src/util/ia32/base_natives \
+
+SOURCES := \
+ $(wildcard src/*.cpp) \
+ src/invokeJNI_ia32.asm
+
+SOURCES := $(filter-out %_em64t.cpp,$(SOURCES))
+SOURCES := $(filter-out %_ipf.cpp,$(SOURCES))
+
+LDFLAGS = -Wl,--export-dynamic
+SODEPENDS = hythr harmonyvm
+
+include ../../build/makerules.inc
diff --git vm/jitrino/Makefile vm/jitrino/Makefile
new file mode 100644
index 0000000..b45da94
--- /dev/null
+++ vm/jitrino/Makefile
@@ -0,0 +1,47 @@
+NAME = jitrino
+TYPE = shared
+
+DEFINES = BUILDING_JIT PROJECT_JITRINO
+CXXFLAGS = -fmessage-length=0 -Wall -Werror -x c++ -fPIC -fno-exceptions
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/port/src/encoder/ia32_em64t \
+ $(VM)/port/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ $(VM)/vmcore/src/util/linux/include \
+ src/dynopt \
+ src/main \
+ src/shared \
+ src/optimizer \
+ src/optimizer/ssa \
+ src/optimizer/abcd \
+ src/translator \
+ src/translator/java \
+ src/vm \
+ src/vm/drl \
+ src/codegenerator \
+ src/codegenerator/ia32 \
+ src/jet \
+
+SOURCES = \
+ $(wildcard src/dynopt/*.cpp) \
+ $(wildcard src/main/*.cpp) \
+ $(wildcard src/shared/*.cpp) \
+ $(wildcard src/optimizer/*.cpp) \
+ $(wildcard src/optimizer/ssa/*.cpp) \
+ $(wildcard src/optimizer/abcd/*.cpp) \
+ $(wildcard src/translator/*.cpp) \
+ $(wildcard src/translator/java/*.cpp) \
+ $(wildcard src/vm/*.cpp) \
+ $(wildcard src/vm/drl/*.cpp) \
+ $(wildcard src/codegenerator/*.cpp) \
+ $(wildcard src/codegenerator/ia32/*.cpp) \
+ $(wildcard src/jet/*.cpp) \
+
+LIBDEPENDS = encoder
+SODEPENDS = harmonyvm hythr
+LIBS = dl m
+
+include ../../build/makerules.inc
diff --git vm/port/Makefile vm/port/Makefile
new file mode 100644
index 0000000..a8bdcce
--- /dev/null
+++ vm/port/Makefile
@@ -0,0 +1,28 @@
+NAME = port
+TYPE = library
+
+
+DEFINES = APR_DECLARE_EXPORT BUILDING_PORTLIB BUILDING_VM
+CXXFLAGS += -fexceptions
+CFLAGS += -fexceptions
+
+INCLUDES = \
+ $(VM)/include \
+ $(VM)/port/include \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(SEMIS)/extra/log4cxx/src/include \
+ $(CLASSLIB)/deploy/include \
+
+SOURCES := $(wildcard \
+ src/disasm/linux/*.c \
+ src/file_io/linux/*.c \
+ src/misc/linux/*.c \
+ src/vmem/linux/*.c \
+ src/thread/linux/*.c \
+ src/atomic/linux/*.c \
+ src/logger/*.cpp \
+ src/tl/*.cpp \
+ src/time/*.cpp \
+)
+
+include ../../build/makerules.inc
diff --git vm/port/src/encoder/Makefile vm/port/src/encoder/Makefile
new file mode 100644
index 0000000..eb37acd
--- /dev/null
+++ vm/port/src/encoder/Makefile
@@ -0,0 +1,11 @@
+NAME = encoder
+TYPE = library
+
+DEFINES = APR_DECLARE_EXPORT NO_EBCODER_INLINE
+
+INCLUDES = \
+ $(VM)/include \
+
+SOURCES = $(wildcard ia32_em64t/*.cpp)
+
+include ../../../../build/makerules.inc
diff --git vm/thread/Makefile vm/thread/Makefile
new file mode 100644
index 0000000..0ae3c61
--- /dev/null
+++ vm/thread/Makefile
@@ -0,0 +1,30 @@
+NAME = hythr
+TYPE = shared
+
+DEFINES = APR_DECLARE_STATIC
+CFLAGS += -fpic
+CXXFLAGS += -fpic
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/include \
+ $(VM)/thread/src \
+ $(VM)/port/include \
+ $(VM)/port/src/encoder/ia32_em64t \
+
+SOURCES = \
+ $(wildcard src/*native*.c) \
+ src/thread_init.c \
+ $(wildcard src/linux/*.c) \
+
+LDFLAGS = -Wl,-init -Wl,hythread_library_init
-Wl,--version-script,src/hythr.exp
+# dependencies on other built libraries
+LIBDEPENDS = port
+# 3rd-party libraries
+LIBS = apr-1 aprutil-1 log4cxx stdc++ rt
+LIBDIRS = \
+ $(SEMIS)/extra/apr/_bin \
+ $(SEMIS)/extra/aprutil/_bin \
+ $(SEMIS)/extra/log4cxx/_bin \
+
+include ../../build/makerules.inc
diff --git vm/thread/jthread/Makefile vm/thread/jthread/Makefile
new file mode 100644
index 0000000..f6b54b8
--- /dev/null
+++ vm/thread/jthread/Makefile
@@ -0,0 +1,21 @@
+NAME = jthread
+TYPE = library
+
+DEFINES = BUILDING_VM APR_DECLARE_STATIC
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(VM)/include \
+ $(VM)/thread/src \
+ $(VM)/port/include \
+ $(VM)/port/src/encoder/ia32_em64t \
+
+SOURCES = \
+ $(wildcard ../src/*java*.c) \
+ $(wildcard ../src/thread_ti*.c) \
+ $(wildcard ../src/*_lnx.c) \
+ $(wildcard ../src/*.cpp) \
+
+CXXFLAGS = -fno-exceptions -Wno-deprecated
+
+include ../../../build/makerules.inc
diff --git vm/vmcore/Makefile vm/vmcore/Makefile
new file mode 100644
index 0000000..0f88461
--- /dev/null
+++ vm/vmcore/Makefile
@@ -0,0 +1,62 @@
+NAME = harmonyvm
+TYPE = shared
+
+DEFINES = BUILDING_VM USE_DLL_JIT APR_DECLARE_STATIC
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(SEMIS)/extra/log4cxx/src/include \
+ $(CLASSLIB)/deploy/include/icu4c \
+ $(VM)/include \
+ $(VM)/thread/src \
+ $(VM)/port/include \
+ $(VM)/port/src/encoder/ia32_em64t \
+ $(VM)/port/src/lil/ia32/pim/include \
+ src/util/linux/include \
+ src/util/ia32/base_natives \
+ include \
+
+SOURCES := \
+ $(wildcard src/class_support/*.cpp) \
+ $(wildcard src/exception/*.cpp) \
+ $(wildcard src/init/*.cpp) \
+ $(wildcard src/gc/*.cpp) \
+ $(wildcard src/interpreter/*.cpp) \
+ $(wildcard src/jit/*.cpp) \
+ $(wildcard src/jni/*.cpp) \
+ $(wildcard src/jvmti/*.cpp) \
+ $(wildcard src/object/*.cpp) \
+ $(wildcard src/reflection/*.cpp) \
+ $(wildcard src/stack/*.cpp) \
+ $(wildcard src/thread/*.cpp) \
+ $(wildcard src/util/*.cpp) \
+ $(wildcard src/verifier/*.cpp) \
+ $(wildcard src/kernel_classes/native/*.cpp) \
+ $(wildcard ../port/src/lil/*.cpp) \
+ $(wildcard ../port/src/lil/pim/*.cpp) \
+ $(wildcard ../port/src/lil/ia32/pim/*.cpp) \
+ $(wildcard ../vmstart/src/compmgr/*.cpp) \
+ $(wildcard src/util/ia32/base/*.cpp) \
+ $(wildcard src/util/ia32/base_natives/*.cpp) \
+ $(wildcard src/thread/linux/*.cpp) \
+ $(wildcard src/util/linux/os_wrapper.cpp) \
+ $(wildcard src/util/linux/stubs.cpp) \
+ $(wildcard src/util/linux/crash_handler.cpp) \
+ $(wildcard src/util/linux/native_modules.cpp) \
+ $(wildcard src/util/linux/signals_ia32.cpp) \
+ $(wildcard src/util/linux/native_modules_ia32.cpp) \
+ $(wildcard src/util/ia32/base/*.asm) \
+
+SOURCES := $(filter-out %_ipf.cpp %_ipf.asm %_em64t.cpp %_win.cpp,$(SOURCES))
+
+LDFLAGS = -Wl,--export-dynamic -Wl,-Bdynamic
+LIBDEPENDS = jthread port encoder
+SODEPENDS = hythr
+LIBS = log4cxx aprutil-1 apr-1 icuuc stdc++ rt m dl z xml2 pthread gcc_s
+LIBDIRS = \
+ $(SEMIS)/extra/apr/_bin \
+ $(SEMIS)/extra/aprutil/_bin \
+ $(SEMIS)/extra/log4cxx/_bin \
+ $(CLASSLIB)/depends/libs/linux.x86 \
+
+include ../../build/makerules.inc
diff --git vm/vmi/Makefile vm/vmi/Makefile
new file mode 100644
index 0000000..de4b1b9
--- /dev/null
+++ vm/vmi/Makefile
@@ -0,0 +1,22 @@
+NAME = vmi
+TYPE = shared
+
+DEFINES =
+
+INCLUDES = \
+ $(SEMIS)/extra/apr/include/apr-1 \
+ $(CLASSLIB)/deploy/include \
+ $(VM)/port/include \
+ $(VM)/include \
+ $(VM)/vmcore/include \
+ $(VM)/vmcore/src/util/linux/include \
+
+SOURCES = \
+ $(wildcard src/*.cpp) \
+
+LDFLAGS = -Wl,--version-script,src/vmi.exp
+SODEPENDS = harmonyvm
+LIBS = hyzip hypool hyprt
+LIBDIRS = $(CLASSLIB)/deploy/lib
+
+include ../../build/makerules.inc