Skip to content

Commit

Permalink
Refactor the native builds.
Browse files Browse the repository at this point in the history
This reorganizes the makefile used to produce the native libraries. The
rules are now more product-oriented, and the rules for all target
platforms rely on the same core build/link targets. This makes it way
easier to see at a glance what the configuration is for a given platform,
and how it differs from any other platform. It also, IMHO, makes the
makefile much more readable, and the non-comment portion is much shorter.
  • Loading branch information
MrDOS committed Jun 17, 2020
1 parent 4058756 commit fa12f66
Show file tree
Hide file tree
Showing 12 changed files with 516 additions and 583 deletions.
53 changes: 15 additions & 38 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
all:
echo "Please specify a system: windows wine linux osx"
./gradlew build
windows:
mingw32-make -C .\src\main\c windowsLocal
./gradlew.bat build
wine:
make -C src/main/c windows
./gradlew build
linux:
make -C src/main/c linux
./gradlew build
linux32:
sudo apt-get install libc6-dev-i386 linux-libc-dev
make -C src/main/c linux32
./gradlew build
linux64:
make -C src/main/c linux64
./gradlew build
freebsd:
gmake -C src/main/c freebsd
./gradlew build
freebsd32:
gmake -C src/main/c freebsd32
./gradlew build
freebsd64:
gmake -C src/main/c freebsd64
./gradlew build
arm:
sudo apt-get install g++-arm-linux-gnueabihf g++-arm-linux-gnueabi g++-aarch64-linux-gnu
make -C src/main/c arm
./gradlew build
ppc:
make -C src/main/c ppc
./gradlew build
osx:
make -C src/main/c osx
./gradlew build
include src/main/c/platform.mk

define ONLY_GRADLE
You haven't specified a platform to build the native library, so I'm only going
to build the Java portion of the project. To build natives, specify a platform:

make linux|osx|freebsd|windows

endef

only-gradle:
$(info $(ONLY_GRADLE))
$(call gradlew-build)
%:
$(MAKE) -C src/main/c $@
$(call gradlew-build)
73 changes: 46 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,53 +66,72 @@ ease of use and embeddability in other libraries.
2. Build with Gradle.

$ cd nrjavaserial
$ gradle build
$ ./gradlew build

The resulting JAR will be found in the `build/libs/` directory.

# Building Native Code

Native code is built using the Makefile found in the root of the repository.
After the native code is built, the JAR is rebuilt.
# Building the native libraries

The native libraries are written in C,
and are built with Make.
The source,
including the master makefile,
lives in `src/main/c`.
The makefile in the project root
will delegate to this makefile,
and rebuild the JAR afterwards.

You'll also need a copy of the JNI development headers
for your system.
The easiest way to get these is to install a copy of the JDK.
The headers are located in `JAVA_HOME/include`.
The build process will attempt to automatically determine
the location of your Java installation;
however, to ensure a predictable build process,
you should set the `JAVA_HOME` environment variable
to the path of your Java installation directory.

# Install cross-compilation toolchains for all of the supported Linux
# architectures and Windows onto an amd64 Linux build host running
# Debian 10 or a modern derivative.
$ sudo make -C src/main/c crosstools

# Build both the 32- and 64-bit Windows binaries.
$ mingw32-make windows

# Build the windows binaries on Linux via Wine.
$ make wine
$ make windows

# Build both the 32- and 64-bit Linux x86 binaries.
$make linux
# Build Linux binaries for 32- and 64-bit x86, 32-bit ARMv5/v6/v7/v8,
# 64-bit ARMv8, and 32-bit PPC.
$ make linux

# Build 32- or 64-bit Linux binaries, respectively.
# Build only 32- or 64-bit x86 Linux binaries, respectively.
$ make linux32
$ make linux64

# Build the binaries for all the supported ARM flavors (requires arm-linux-geabi-* packages)
# Build binaries for all the supported ARM flavors.
$ make arm

# Build the OSX binaries.
$ make osx

# Build the PPC binaries.
$ make ppc

# Build the FreeBSD binaries.

# Build 64-bit x86 macOS binaries. This requires a macOS build host.
$ make osx

# Build 32- and 64-bit x86 FreeBSD binaries, or just for 32/64-bit,
# respectively. This requires a FreeBSD build host.
$ make freebsd
$ make freebsd32
$ make freebsd64


## Building on Windows

You'll need some installation of GCC. We recommend the
[TDM-GCC](http://tdm-gcc.tdragon.net/) distribution of mingw64-w64.
To get the build working you need both mingw32, and ming64 installed in separate directories.
Please modify JDKDIR to your installation of JDK.


Compile against Java
You'll need some installation of GCC.
We recommend the [TDM-GCC] distribution of Mingw64-w64.
Following its default installation process
should result in its `bin/` directory being added to your path;
if you can pop open a command prompt and run `x86_64-w64-mingw32-gcc`,
you're good to go.

https://cdn.azul.com/zulu/bin/zulu8.44.0.13-ca-fx-jdk8.0.242-win_x64.zip
[TDM-GCC]: https://jmeubank.github.io/tdm-gcc/

## Building on OS X

Expand Down
3 changes: 1 addition & 2 deletions src/main/c/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/build
build/
.project
.cproject
/Default/
115 changes: 115 additions & 0 deletions src/main/c/JAVA_HOME.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# “Undefined JAVA_HOME” is a strong contender for the most hated error message
# in all of software development, so we'll take a shot at figuring it out
# before leaving the user to fend for themselves.
#
# The detection here tries to be failure-tollerant, but Make is not a very good
# environment for either resilient string manipulation or reliable
# cross-platform path operations. If you're reading this because you think the
# path detection contained herein is causing trouble, the easiest way to avoid
# this file altogether is to define the JAVA_HOME environment variable.

ifndef JAVA_HOME

define MISSING_JAVA
The JAVA_HOME environment variable has not been defined, and you don't have the
`java` binary on your PATH, so I can't determine the location of your Java
installation automatically. Please set the JAVA_HOME environment variable to
the location of your preferred Java installation
endef

define EXPLICITLY_SET
If that's not correct, or to suppress this message, explicitly set the
JAVA_HOME environment variable to the location of your preferred Java
installation.
endef

define DARWIN_GUESSED_JAVA_HOME
The JAVA_HOME environment variable has not been defined;
based on the output of `/usr/libexec/java_home`, I'm going to use:

$(JAVA_HOME)

$(EXPLICITLY_SET)
endef

define GUESSED_JAVA_HOME
The JAVA_HOME environment variable has not been defined.
Based on the location of the `java` binary, I've guessed it's:

$(JAVA_HOME)

$(EXPLICITLY_SET)
endef

# Windows will set the “OS” environment variable by default.
ifeq ($(OS),)
OS := $(shell uname)
endif

# On macOS, we can just ask where Java is.
ifeq ($(OS),Darwin)
JAVA_HOME=$(shell /usr/libexec/java_home)
$(warning $(DARWIN_GUESSED_JAVA_HOME))

else

# First, find java(1). On POSIX systems, we can use which(1); on Windows, we
# need to use WHERE.
WHICH=which
ifeq ($(OS),Windows_NT)
# Just checking whether we're on Windows isn't good enough: if we're running in
# a Cygwin or MinGW environment (e.g., Git Bash) which requires Unix-like
# absolute paths (e.g., “/c/foo/bar”, not “C:\foo\bar”), then we still need to
# use which(1) – WHERE will give us paths we can't use. TERM seems like a
# pretty safe environment variable to check; it's a Unix-ism not embraced by
# cmd.exe or PowerShell, but it should be set by emulation environments.
ifndef TERM
# This needs to explicitly include the “.exe” extension to disambiguate between
# the classic “WHERE” executable and the “Where” PowerShell cmdlet.
WHICH=where.exe
endif
endif

JAVA_PATH := $(shell $(WHICH) java)
ifeq ($(JAVA_PATH),)
$(error $(MISSING_JAVA))
endif

# Make's builtin filename operations, such as $(realpath ...) and $(dir ...),
# operate on space-separated lists of filenames, and Java is often installed to
# a path containing spaces on Windows (e.g., C:\Program Files\AdoptOpenJDK\
# jdk-8.x.y.z-hotspot), so we need to munge any spaces in the path to something
# which won't appear in legal path names, do our manipulations, then swap the
# spaces back into place.
empty :=
space := $(empty) $(empty)
JAVA_PATH := $(subst $(space),?,$(JAVA_PATH))

# Resolve any symlinks (e.g., /usr/bin/java → /etc/alternatives/java →
# /usr/lib/jvm/java-11-openjdk-amd64/bin/java.
JAVA_REALPATH := $(realpath $(JAVA_PATH))
ifneq ($(JAVA_REALPATH),)
# Of course, if there _were_ any spaces in the path (which have now been
# replaced with an invalid character), realpath will fall over. Let's hope we
# never have to deal with a situation where the path contains symlinks _and_
# spaces.
JAVA_PATH := $(JAVA_REALPATH)
endif

# JAVA_PATH should be JAVA_HOME/bin/java or maybe JAVA_HOME/jre/bin/java. To
# get JAVA_HOME, we want to traverse two or three levels up from JAVA_PATH.
# However, we can't just call $(dir $(dir $(JAVA_PATH)), because unlike
# dirname(1), $(dir ...) returns the given path untouched if it is already a
# directory, instead of always returning the parent (i.e., “$(dir foo/bar/)”
# returns “foo/bar/”, not “foo/”). And $(abspath ...) breaks the leading “/c/”
# in POSIX emulation shells on Windows. We'll just resort to to string
# manipulation.
JAVA_HOME := $(subst /jre/bin/java,,$(JAVA_PATH))
JAVA_HOME := $(subst /bin/java,,$(JAVA_HOME))
JAVA_HOME := $(subst \bin\java.exe,,$(JAVA_HOME))
# Now fix any spaces in the path.
JAVA_HOME := "$(subst ?,$(space),$(JAVA_HOME))"
$(warning $(GUESSED_JAVA_HOME))

endif # ifeq ($(OS),Darwin)
endif # ifndef JAVA_HOME
Loading

0 comments on commit fa12f66

Please sign in to comment.