Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
JSyphon/native_src/JSyphon.xcodeproj/project.xcworkspace/xcuserdata
JSyphon/native_src/JSyphon.xcodeproj/xcuserdata
JSyphon/native_src/build_universal
JSyphon/native_src/tests/vao_test
JSyphon/native_src/tests/Syphon
Binary file modified JSyphon/jar/jsyphon.jar
Binary file not shown.
Binary file modified JSyphon/native_libs/Syphon
Binary file not shown.
Binary file modified JSyphon/native_libs/libJSyphon.jnilib
Binary file not shown.
100 changes: 100 additions & 0 deletions JSyphon/native_src/build_universal.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash -e
#
# Builds universal (x86_64 + arm64) versions of the Syphon framework binary
# and the JSyphon JNI library, without requiring Xcode (Command Line Tools
# plus a JDK for the JNI headers is enough).
#
# JavaNativeFoundation is no longer shipped with the macOS SDK, so the
# sources vendored under native_src/jnf (from apple/openjdk,
# xcodejdk14-release branch, APSL 2.0) are compiled statically into
# libJSyphon.jnilib.
#
# Requires: macOS Command Line Tools, a JDK (JAVA_HOME or Homebrew openjdk).
#
# Usage: ./build_universal.sh [output-dir] (default: ../native_libs)

set -o pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
JSYPHON_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
JAVA_DIR="$(cd "$JSYPHON_DIR/.." && pwd)"
SYPHON_FW_DIR="$JAVA_DIR/Syphon-Framework"
SHARED_DIR="$JAVA_DIR/Shared"
JNF_DIR="$SCRIPT_DIR/jnf"
BUILD_DIR="$SCRIPT_DIR/build_universal"
OUT_DIR="$(cd "${1:-$JSYPHON_DIR/native_libs}" && pwd)"

if [ ! -f "${JAVA_HOME:-}/include/jni.h" ]; then
if [ -d /opt/homebrew/opt/openjdk@17/include ]; then
JAVA_HOME=/opt/homebrew/opt/openjdk@17
else
JAVA_HOME="$(dirname "$(dirname "$(command -v javac)")")"
fi
fi
if [ ! -f "$JAVA_HOME/include/jni.h" ]; then
echo "error: jni.h not found under JAVA_HOME=$JAVA_HOME (set JAVA_HOME to a full JDK)" >&2
exit 1
fi

ARCHS="x86_64 arm64"
DEPLOY_TARGET_x86_64=10.13
DEPLOY_TARGET_arm64=11.0

OBJCFLAGS="-fblocks -Wno-deprecated-declarations -Wno-unused-function -g0 -Os"

rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR/include/JavaNativeFoundation" "$BUILD_DIR/include/Syphon"

cp "$JNF_DIR"/*.h "$BUILD_DIR/include/JavaNativeFoundation/"
cp "$SYPHON_FW_DIR"/*.h "$BUILD_DIR/include/Syphon/"

grep -v '^[[:space:]]*//' "$SYPHON_FW_DIR/Exported_Symbols.exp" | grep -v '^[[:space:]]*$' > "$BUILD_DIR/Exported_Symbols.exp"

INCLUDES=(-I "$BUILD_DIR/include" -I "$SYPHON_FW_DIR" -I "$SHARED_DIR" -I "$SCRIPT_DIR" -I "$JAVA_HOME/include" -I "$JAVA_HOME/include/darwin")

SYPHON_SOURCES=("$SYPHON_FW_DIR"/*.m "$SYPHON_FW_DIR"/*.c)
JSYPHON_SOURCES=("$SCRIPT_DIR"/jsyphon_JSyphon*.m "$JNF_DIR"/*.m "$SHARED_DIR/SyphonNameboundClient.m")

for ARCH in $ARCHS; do
case "$ARCH" in
x86_64) MIN=$DEPLOY_TARGET_x86_64 ;;
arm64) MIN=$DEPLOY_TARGET_arm64 ;;
esac
COMMON=(-arch "$ARCH" -mmacosx-version-min="$MIN" -fPIC $OBJCFLAGS "${INCLUDES[@]}")

echo "==> Building Syphon ($ARCH)"
clang -dynamiclib -o "$BUILD_DIR/Syphon-$ARCH" \
"${COMMON[@]}" -fobjc-arc \
-DSYPHON_CORE_RESTORE \
-include "$SYPHON_FW_DIR/Syphon_Prefix.pch" \
"${SYPHON_SOURCES[@]}" \
-install_name "@loader_path/Syphon" \
-current_version 1.0.0 -compatibility_version 1.0.0 \
-Wl,-exported_symbols_list,"$BUILD_DIR/Exported_Symbols.exp" \
-framework Cocoa -framework IOSurface -framework OpenGL -framework CoreVideo -framework Metal

echo "==> Building libJSyphon.jnilib ($ARCH)"
clang -dynamiclib -o "$BUILD_DIR/libJSyphon.jnilib-$ARCH" \
"${COMMON[@]}" -fno-objc-arc \
"${JSYPHON_SOURCES[@]}" \
-install_name "@rpath/libJSyphon.jnilib" \
-current_version 1.0.0 -compatibility_version 1.0.0 \
"$BUILD_DIR/Syphon-$ARCH" \
-Wl,-undefined,dynamic_lookup \
-framework Cocoa -framework OpenGL -framework CoreData
done

echo "==> Creating universal binaries"
lipo -create -output "$BUILD_DIR/Syphon" "$BUILD_DIR/Syphon-x86_64" "$BUILD_DIR/Syphon-arm64"
lipo -create -output "$BUILD_DIR/libJSyphon.jnilib" "$BUILD_DIR/libJSyphon.jnilib-x86_64" "$BUILD_DIR/libJSyphon.jnilib-arm64"

echo "==> Ad-hoc code signing"
codesign --force --sign - "$BUILD_DIR/Syphon"
codesign --force --sign - "$BUILD_DIR/libJSyphon.jnilib"

echo "==> Installing to $OUT_DIR"
cp "$BUILD_DIR/Syphon" "$OUT_DIR/Syphon"
cp "$BUILD_DIR/libJSyphon.jnilib" "$OUT_DIR/libJSyphon.jnilib"

lipo -info "$OUT_DIR/Syphon" "$OUT_DIR/libJSyphon.jnilib"
echo "Done."
108 changes: 108 additions & 0 deletions JSyphon/native_src/jnf/JNFAssert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#ifndef JNFASSERT_H
#define JNFASSERT_H
/*
* Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* --
*
* Assertions used by the JNF_COCOA_ENTER()/JNF_COCOA_EXIT() and class
* caching macros. When building debug builds, improper use of the caching
* macros will trigger warnings output to the console.
*/

#import <JavaNativeFoundation/JNFJNI.h>

#ifdef DEBUG
#define JAVA_ASSERTIONS_ON
#endif /* DEBUG */

// Use the WARN macro to send a message to stderr in the
// debug build. It gets removed from the optimized build
// during preprocessing.
#ifdef DEBUG
#define JNF_WARN JNFDebugWarning
#else
#define JNF_WARN if (0) JNFDebugWarning
#endif /* DEBUG */

__BEGIN_DECLS

JNF_EXPORT extern void JNFDebugWarning(const char *fmt, ...);

JNF_EXPORT extern void JNFAssertionFailure(const char *file, int line, const char *condition, const char *msg);

#ifdef JAVA_ASSERTIONS_ON

#define JNF_ASSERT_FAILURE(condition, msg) \
JNFAssertionFailure(__FILE__, __LINE__, condition, msg) \


#define JNF_ASSERT_MSG(condition, msg) \
do { \
if (!(condition)) { \
JNF_ASSERT_FAILURE(#condition, msg); \
} \
} while(0) \


#define JNF_ASSERT_COND(condition) \
JNF_ASSERT_MSG(condition, NULL) \


#define JNF_EXCEPTION_WARN(env, msg) \
do { \
(*(env))->ExceptionDescribe(env); \
JNF_ASSERT_FAILURE("Java exception thrown", msg); \
} while (0) \


#define JNF_ASSERT_NO_EXCEPTION_MSG(env, msg) \
if ((*(env))->ExceptionOccurred(env)) { \
JNF_EXCEPTION_WARN(env, msg); \
} \


#define JNF_ASSERT_NO_EXCEPTION(env) \
JNF_ASSERT_NO_EXCEPTION_MSG(env, NULL) \

#else

#define JNF_ASSERT_COND(condition)
#define JNF_ASSERT_MSG(condition, msg)
#define JNF_EXCEPTION_WARN(env, msg)
#define JNF_ASSERT_NO_EXCEPTION(env)
#define JNF_ASSERT_NO_EXCEPTION_MSG(env, msg)

#endif /* JAVA_ASSERTIONS_ON */

JNF_EXPORT extern void JNFDumpJavaStack(JNIEnv *env);

__END_DECLS

#endif /* JNFASSERT_H */
69 changes: 69 additions & 0 deletions JSyphon/native_src/jnf/JNFAssert.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#import "JNFJNI.h"
#import "JNFAssert.h"

#import "debug.h"

static void JNFDebugMessageV(const char *fmt, va_list args) {
// Prints a message and breaks into debugger.
fprintf(stderr, "JavaNativeFoundation: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
}

static void JNFDebugMessage(const char *fmt, ...) {
// Takes printf args and then calls DebugBreak
va_list args;
va_start(args, fmt);
JNFDebugMessageV(fmt, args);
va_end(args);
}

void JNFDebugWarning(const char *fmt, ...) {
// Takes printf args and then calls DebugBreak
va_list args;
va_start(args, fmt);
JNFDebugMessageV(fmt, args);
va_end(args);
}

void JNFAssertionFailure(const char *file, int line, const char *condition, const char *msg) {
JNFDebugMessage("Assertion failure: %s", condition);
if (msg) JNFDebugMessage(msg);
JNFDebugMessage("File %s; Line %d", file, line);
}

void JNFDumpJavaStack(JNIEnv *env) {
static JNF_CLASS_CACHE(jc_Thread, "java/lang/Thread");
static JNF_STATIC_MEMBER_CACHE(jsm_Thread_dumpStack, jc_Thread, "dumpStack", "()V");
JNFCallVoidMethod(env, jc_Thread.cls, jsm_Thread_dumpStack);
}
56 changes: 56 additions & 0 deletions JSyphon/native_src/jnf/JNFAutoreleasePool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef JNFAUTORELEASEPOOL_H
#define JNFAUTORELEASEPOOL_H
/*
* Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* --
*
* Utility class used by the JNF_COCOA_ENTER()/JNF_COCOA_EXIT() macros
* from JNFJNI.h. Do not use this class or releated functions directly.
*/

#import <Foundation/Foundation.h>

#import <JavaNativeFoundation/JNFJNI.h>

__BEGIN_DECLS

typedef void JNFAutoreleasePoolToken;

// JNFNativeMethodEnter - called on entry to each native method by the
// JNF_COCOA_ENTER(env) macro in JNFJNI.h
JNF_EXPORT extern JNFAutoreleasePoolToken *JNFNativeMethodEnter(void);

// JNFNativeMethodExit - called on exit from each native method by the
// JNF_COCOA_EXIT(env) macro in JNFJNI.h
JNF_EXPORT extern void JNFNativeMethodExit(JNFAutoreleasePoolToken *token);

__END_DECLS

#endif /* JNFAUTORELEASEPOOL_H */
Loading