New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cross-platform, cross-compile build toolchain #280
Changes from 23 commits
9686139
b57b921
d89202e
9c75430
45e487d
bf02e87
076ffe2
f3e69cc
6d2bbb8
1ff1de4
54fdc43
d0deb23
3954205
18c7b37
9cd7c6a
7f2e8cf
2f66df8
9e45f55
8297dab
63ac9d1
da5d322
de97277
80f16de
9359bb8
d339049
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
|
||
# NOTE: this works around the windows docker / msbuild bug, that causes the | ||
# VC++ linker to fail creating PDB debug files in a shared volume | ||
# (see: https://social.msdn.microsoft.com/Forums/en-US/bd281c61-8e04-4f56-aec2-5ad565271d7f/windowsservercorelatest-vc-2015-build-tools-throws-linker-error-lnk1318-unexpected-pdb?forum=windowscontainers) | ||
if(J2V8_CROSS_COMPILE AND J2V8_WIN32_PDB_DOCKER_FIX) | ||
#{ | ||
# TODO: remove this if the Win32 Docker PDB bug is fixed | ||
# see: https://stackoverflow.com/a/39109288 | ||
message("CMAKE-WARNING: applied workaround for windows docker PDB bug") | ||
message("see: https://social.msdn.microsoft.com/Forums/en-US/bd281c61-8e04-4f56-aec2-5ad565271d7f/windowsservercorelatest-vc-2015-build-tools-throws-linker-error-lnk1318-unexpected-pdb?forum=windowscontainers") | ||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) | ||
#} | ||
endif() | ||
|
||
cmake_minimum_required(VERSION 3.6) | ||
project(j2v8) | ||
|
||
# adding cmake directory for includes | ||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) | ||
|
||
# set up the module path | ||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) | ||
|
||
include(BuildUtils) | ||
include(NodeJsUtils) | ||
include(Policies) | ||
|
||
#----------------------------------------------------------------------- | ||
# BUILD PLATFORM SETUP & VARIABLES | ||
#----------------------------------------------------------------------- | ||
|
||
if(CMAKE_SYSTEM_NAME STREQUAL "Android") | ||
#{ | ||
set(JAVA_PLATFORM_NAME "android") | ||
|
||
# output library filename | ||
set(J2V8_LIB_PLATFORM_NAME "android") | ||
set(J2V8_LIB_PREFIX "") | ||
set(J2V8_LIB_ARCH_NAME ${CMAKE_ANDROID_ARCH_ABI}) | ||
#} | ||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||
#{ | ||
set(JAVA_PLATFORM_NAME "linux") | ||
|
||
# output library filename | ||
set(J2V8_LIB_PLATFORM_NAME "linux") | ||
set(J2V8_LIB_PREFIX "") | ||
set(J2V8_LIB_ARCH_NAME "x86") | ||
#} | ||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") | ||
#{ | ||
set(JAVA_PLATFORM_NAME "darwin") | ||
|
||
# output library filename | ||
set(J2V8_LIB_PLATFORM_NAME "macosx") | ||
set(J2V8_LIB_PREFIX "") | ||
set(J2V8_LIB_ARCH_NAME "x86") | ||
#} | ||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") | ||
#{ | ||
set(JAVA_PLATFORM_NAME "win32") | ||
|
||
# output library filename | ||
set(J2V8_LIB_PLATFORM_NAME "win32") | ||
set(J2V8_LIB_PREFIX "lib") | ||
set(J2V8_LIB_ARCH_NAME "x86") | ||
#} | ||
endif() | ||
|
||
#----------------------------------------------------------------------- | ||
# DEPENDENCY SETTINGS / CMAKE OPTIONS | ||
#----------------------------------------------------------------------- | ||
|
||
# look for dependencies | ||
find_package(Java) | ||
|
||
# j2v8 dependency options | ||
set(J2V8_JDK_DIR ${Java_ROOT} CACHE STRING "Path to the Java JDK dependency") | ||
set(J2V8_NODEJS_DIR "${CMAKE_SOURCE_DIR}/node" CACHE STRING "Path to the Node.js dependency") | ||
|
||
# get the required Node.js link libraries | ||
get_njs_libs(${J2V8_NODEJS_DIR} "Debug") | ||
get_njs_libs(${J2V8_NODEJS_DIR} "Release") | ||
|
||
# j2v8 build options | ||
option(J2V8_NODE_COMPATIBLE "Build the J2V8 native bridge with Node.js support enabled" ON) | ||
option(J2V8_BUILD_ONLY_DEBUG_RELEASE "Generate only Debug and Release configurations (exclude RelWithDebInfo and MinSizeRel)" ON) | ||
|
||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND MSVC) | ||
#{ | ||
option(J2V8_LINK_WITH_STATIC_MSVCRT "Link against the static version of the Microsoft Visual C++ Common Runtime (will link against the dynamic DLL version if this option is disabled)" ON) | ||
#} | ||
endif() | ||
|
||
#----------------------------------------------------------------------- | ||
# INCLUDE DIRECTORIES & SOURCE FILES | ||
#----------------------------------------------------------------------- | ||
|
||
# project include directories | ||
set(include_dirs | ||
${J2V8_NODEJS_DIR} | ||
${J2V8_NODEJS_DIR}/src | ||
${J2V8_NODEJS_DIR}/deps/v8 | ||
${J2V8_NODEJS_DIR}/deps/v8/include | ||
) | ||
|
||
# do not use JAVA_HOME for Java include files for Android | ||
# (instead the Android NDK toolchain will introduce them automatically) | ||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android") | ||
#{ | ||
set(include_dirs | ||
${include_dirs} | ||
${J2V8_JDK_DIR}/include | ||
${J2V8_JDK_DIR}/include/${JAVA_PLATFORM_NAME} | ||
) | ||
#} | ||
endif() | ||
|
||
# project source files | ||
set(src_files | ||
jni/com_eclipsesource_v8_V8Impl.cpp | ||
jni/com_eclipsesource_v8_V8Impl.h | ||
) | ||
|
||
source_group("" FILES ${src_files}) | ||
|
||
#----------------------------------------------------------------------- | ||
# BUILD SETTINGS & COMPILATION | ||
#----------------------------------------------------------------------- | ||
|
||
# tell gcc/clang to use the c++11 standard | ||
set(CMAKE_CXX_STANDARD 11) | ||
|
||
if(CMAKE_SYSTEM_NAME STREQUAL "Android") | ||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused-function -Wno-unused-variable -O3 -funroll-loops -ftree-vectorize -ffast-math -fpermissive -fPIC ") | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-function -Wno-unused-variable -O3 -funroll-loops -ftree-vectorize -ffast-math -fpermissive -fPIC ") | ||
endif() | ||
|
||
# remove the MinSizeRel and RelWithDebInfo configurations | ||
if(J2V8_BUILD_ONLY_DEBUG_RELEASE) | ||
#{ | ||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "limited configs" FORCE) | ||
#} | ||
endif() | ||
|
||
# link against the static MS C++ runtime libraries | ||
if(J2V8_LINK_WITH_STATIC_MSVCRT) | ||
link_static_crt() | ||
endif() | ||
|
||
# create the j2v8 library | ||
add_library(j2v8 SHARED ${src_files}) | ||
|
||
# enable Node.js if requested by the build options above | ||
if(J2V8_NODE_COMPATIBLE) | ||
#{ | ||
set_property(TARGET j2v8 PROPERTY COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS} NODE_COMPATIBLE=1) | ||
#} | ||
endif() | ||
|
||
# build output directory | ||
set(LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) | ||
|
||
# set the include directories | ||
include_directories(${include_dirs}) | ||
|
||
# link the necessary libraries | ||
target_link_libraries(j2v8 | ||
debug "${njs_Debug_libs}" | ||
optimized "${njs_Release_libs}" | ||
) | ||
|
||
#----------------------------------------------------------------------- | ||
# OUTPUT SETTINGS & POST-BUILD | ||
#----------------------------------------------------------------------- | ||
|
||
# apply lib suffix if building a 64 bit target | ||
if(CMAKE_CL_64 OR CMAKE_SIZEOF_VOID_P EQUAL 8) | ||
set(J2V8_LIB_ARCH_NAME "${J2V8_LIB_ARCH_NAME}_64") | ||
endif() | ||
|
||
# set library output filename | ||
set_target_properties(j2v8 PROPERTIES OUTPUT_NAME "${PROJECT_NAME}_${J2V8_LIB_PLATFORM_NAME}_${J2V8_LIB_ARCH_NAME}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,58 +10,35 @@ We developed J2V8 as a high performance engine for our multi-platform mobile too | |
|
||
Building J2V8 | ||
============= | ||
Building J2V8 requires building both the native parts and the Java library (.jar file). To build the native parts we first build node.js as a library and then statically link J2V8 to that. The Java parts are built with maven. | ||
|
||
Building on MacOS | ||
----------------- | ||
``` | ||
sh ./build-node.sh | ||
sh ./buildJ2V8_macos.sh | ||
mvn clean verify | ||
``` | ||
|
||
Building on Linux | ||
----------------- | ||
``` | ||
export CCFLAGS="${CCFLAGS} -fPIC" | ||
export CXXFLAGS="${CXXFLAGS} -fPIC" | ||
export CPPFLAGS="${CPPFLAGS} -fPIC" | ||
#sh ./build-node.sh | ||
cp -r /data/jenkins/node . | ||
cd jni | ||
g++ -I../node -I../node/deps/v8 -I../node/deps/v8/include \ | ||
-I../node/src -I /data/jenkins/tools/hudson.model.JDK/jdk-7/include/ \ | ||
-I /data/jenkins/tools/hudson.model.JDK/jdk-7/include/linux \ | ||
com_eclipsesource_v8_V8Impl.cpp -std=c++11 -fPIC -shared -o libj2v8_linux_x86_64.so \ | ||
-Wl,--whole-archive ../node/out/Release/libnode.a -Wl,--no-whole-archive \ | ||
-Wl,--start-group \ | ||
../node/out/Release/libv8_libbase.a \ | ||
../node/out/Release/libv8_libplatform.a \ | ||
../node/out/Release/libv8_base.a \ | ||
../node/out/Release/libv8_nosnapshot.a \ | ||
../node/out/Release/libuv.a \ | ||
../node/out/Release/libopenssl.a \ | ||
../node/out/Release/libhttp_parser.a \ | ||
../node/out/Release/libgtest.a \ | ||
../node/out/Release/libzlib.a \ | ||
../node/out/Release/libcares.a \ | ||
-Wl,--end-group \ | ||
-lrt -D NODE_COMPATIBLE=1 | ||
mvn clean verify | ||
``` | ||
|
||
This will build J2V8 with node.js support. To disable this support, remove the `-D NODE_COMPATIBLE=1` option. | ||
|
||
Building for Android | ||
----------------- | ||
Building J2V8 for Android requires Docker. | ||
|
||
``` | ||
./docker/build.sh | ||
./gradlew assembleRelease | ||
``` | ||
|
||
This will build J2V8 as an AAR for API 19 minimum with node.js support. | ||
Building J2V8 requires building both the native parts and the Java library (.jar/.aar file). To build the native parts we first build node.js as a library and then statically link J2V8 to that. The Java parts are built with maven/gradle. | ||
|
||
J2V8 uses a cross-platform, cross-compiling build-system written in Python. | ||
|
||
Follow these steps to build J2V8 from source: | ||
|
||
1) clone the Node.js source code | ||
- `python prepare_build.py` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is worth to mention that this works only for python2 (tried with python3 but doesn't work), was there any reason why you choose python over lets say bash scripts? I am just thinking out loud here that not everyone has python2 installed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also when I already had node folder checked out the build failed:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. even most simple build didn't work on my latest manjaro (arch) linux: most likely I ran into this issue: gcc7 doesn't compile:
this makes me think that perhaps docker should always be used... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There are several reasons why I would not use bash scripts for more complex scenarios
I targeted Python 2 primarily because you already need it if you want to build Node.js from source. But I will look into how much work it would take to make it compatible for Python 3 (but I don't think this will be a priority, since Python 2 is still very widely adopted) About the error you get from running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You did so much amazing work I have to say. I think you have a point here, I was just thinking from a scenario that one does git clone and invokes command to build, the rest would happen in docker container. One of biggest advantages of docker as I understood this is to eliminate various linux distrobution flavours, e.g. gcc version, kernel version, different packages versions, python2 vs python3. In that respect it would be perhaps better to fork of python2 invoking a build inside a docker container (in theory) -> that way probability that build would work is higher. On another hand, if this is intended to be used by Travis to create releases (as most people may not care to build snapshots), then it doesn't really matter. As long as maintainers of this project know how to run this, then it is fine. |
||
- This will download & prepare the latest compatible Node.js version for use in J2V8 | ||
- The Node.js source code will be cloned into the local `node` sub-directory, which is the expected default location for the J2V8 build | ||
2) build Node.js and the J2V8 library | ||
- `python build.py --target linux --arch x64 --node-enabled --cross-compile` | ||
- or shorthand | ||
- `python build.py -t linux -a x64 -ne -x` | ||
|
||
For all available options, supported platforms and architectures you can consult the build-script help: | ||
|
||
`python build.py --help` | ||
|
||
Cross-Compiling | ||
--------------- | ||
|
||
For cross-compiling J2V8 uses [Docker](https://www.docker.com/) (android, linux, windows) and [Vagrant](https://www.vagrantup.com/) (macos). | ||
The full source-code (of both J2V8 and Node.js) on the build-host are just shared via mounted volumes with the Docker / Vagrant machines, so you can quickly make changes and perform builds fast. | ||
|
||
To invoke a cross-compile build, simply invoke the `build.py` script as usual but add the `--cross-compile`, `-x` flag. | ||
This will automatically provision and run the necessary virtualization to run the requested build fully independent of your local environment. | ||
|
||
<b>Note:</b> using Docker / Vagrant for cross-compiliation requires many gigabytes of harddrive space as well as downloading the required images & tools. | ||
|
||
Tutorials | ||
========== | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ apply plugin: 'signing' | |
|
||
group = 'com.eclipsesource.j2v8' | ||
archivesBaseName = 'j2v8' | ||
version = '4.8.0-SNAPSHOT' | ||
version = System.env.J2V8_FULL_VERSION | ||
|
||
configurations { | ||
archives { | ||
|
@@ -28,25 +28,38 @@ repositories { | |
|
||
dependencies { | ||
testCompile 'junit:junit:4.12' | ||
testCompile 'org.mockito:mockito-all:1.9.5' | ||
// testCompile 'org.mockito:mockito-all:1.9.5' | ||
|
||
androidTestCompile 'junit:junit:4.12' | ||
// androidTestCompile 'org.mockito:mockito-core:1.9.5' | ||
androidTestCompile 'org.mockito:mockito-android:2.6.3' // https://jeroenmols.com/blog/2017/01/17/mockitoandroid/ | ||
androidTestCompile 'com.android.support:support-annotations:24.0.0' | ||
androidTestCompile 'com.android.support.test:runner:0.5' | ||
androidTestCompile 'com.android.support.test:rules:0.5' | ||
} | ||
|
||
android { | ||
compileSdkVersion 10 | ||
compileSdkVersion 19 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why 19? We should try to keep this as low as possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think at some point while I worked on how I could get the Android emulator testing integration working, it was required by some dependency that might now be gone. If the build & tests work fine with version 10 then we can safely revert it back |
||
buildToolsVersion '24.0.3' | ||
|
||
defaultConfig { | ||
minSdkVersion 10 | ||
targetSdkVersion 10 | ||
minSdkVersion 19 | ||
targetSdkVersion 19 | ||
|
||
ndk { | ||
abiFilters 'armeabi' | ||
} | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
lintOptions { | ||
abortOnError false | ||
} | ||
|
||
sourceSets { | ||
androidTest { | ||
java.srcDirs = ['src/test'] | ||
} | ||
|
||
// androidTest.setRoot('src/test') | ||
} | ||
} | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are curly braces commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use those just by convention to make it easier for the eye to quickly read where the scope of a if-elif-else block starts and ends. This being said, for the next PR I have removed those where only a single line is inside the branch scope. From now on they are only used for if-elif-else blocks that contain multiple lines in their respective blocks (which was the original intent). Thanks for the feedback