diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..562559c --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Ignore ChakraCore subfolder Should it exist. +ChakraCore +ChakraCore/ + + +# Ignore build directories. +BuildLinux/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a22a21a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.2) + +project(ChakraCoreSamples) + +find_package(PkgConfig) + +pkg_check_modules(PC_ICU_UC icu-uc) +pkg_check_modules(PC_ICU_I18N icu-i18n) + +# Find Deps for OpenGL Example. +find_package(OpenGL) +pkg_check_modules(PC_GLFW glfw3) +pkg_check_modules(PC_GLEW glew) +#TODO: embed glew and glfw. + +if(EXISTS "${CMAKE_SOURCE_DIR}/ChakraCore/CMakeLists.txt") + SET(CC_AUTODETECT_CPU ON CACHE BOOL "" FORCE) + SET(CC_AUTODETECT_ICU ON CACHE BOOL "" FORCE) + add_subdirectory(ChakraCore) +else() + # TODO: Detect ChakraCore when installed as a System Package. + message(FATAL_ERROR "ChakraCore not found") +endif() + +if(NOT TARGET Chakra.Pal OR + NOT TARGET Chakra.Common.Core OR + NOT TARGET Chakra.Jsrt ) + message(FATAL_ERROR "ChakraCore not found") +endif() + + +add_custom_target(CopyChakraHeaders ALL + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/include" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/ChakraCore/lib/Jsrt/ChakraCore.h" + "${CMAKE_BINARY_DIR}/include" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/ChakraCore/lib/Jsrt/ChakraCommon.h" + "${CMAKE_BINARY_DIR}/include" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/ChakraCore/lib/Jsrt/ChakraCommonWindows.h" + "${CMAKE_BINARY_DIR}/include" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/ChakraCore/lib/Jsrt/ChakraDebug.h" + "${CMAKE_BINARY_DIR}/include" +) + +add_subdirectory("ChakraCore Samples/Hello World/Linux_OSX") + + +if(PC_GLFW_FOUND AND PC_GLEW_FOUND AND OpenGL_FOUND) + message(STATUS "Building OpenGL Example.") + add_subdirectory("ChakraCore Samples/OpenGL Engine/") +endif() diff --git a/ChakraCore Samples/Hello World/Linux_OSX/CMakeLists.txt b/ChakraCore Samples/Hello World/Linux_OSX/CMakeLists.txt new file mode 100644 index 0000000..c0de677 --- /dev/null +++ b/ChakraCore Samples/Hello World/Linux_OSX/CMakeLists.txt @@ -0,0 +1,67 @@ + +add_executable (ChakraHelloWorld sample.cpp) + +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(LINKER_START_GROUP -Wl,--start-group) + set(LINKER_END_GROUP -Wl,--end-group) +endif() + +if(CC_TARGETS_X86) + set(lib_target "-m32") +endif() + +if(TARGET ChakraCore) + # common link deps + set(lib_target "${lib_target}" + -Wl,-undefined,error + ${LINKER_START_GROUP} + ChakraCore + ${LINKER_END_GROUP} + ) +else() + #TODO: Fix Static Compile. + set(lib_target "${lib_target}" + -Wl,-undefined,error + ${LINKER_START_GROUP} + Chakra.Common.Core + Chakra.Jsrt + Chakra.Pal + ${LINKER_END_GROUP} + ) +endif() + +SET_TARGET_PROPERTIES(ChakraHelloWorld + PROPERTIES COMPILE_FLAGS "-std=c++11") + +target_link_libraries (ChakraHelloWorld ${lib_target}) + +if(NOT CC_XCODE_PROJECT) + set(CC_LIB_EXT "so") + # Post build step to copy the built shared library + # to BuildLinux (or whatever the CMakeBuildDir is) + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CC_LIB_EXT "dylib") + endif() + if(TARGET ChakraCore) + add_custom_command(TARGET ChakraHelloWorld POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_BINARY_DIR}/ChakraCore/libChakraCore.${CC_LIB_EXT}" + "${CMAKE_BINARY_DIR}/" + ) + endif() + add_custom_command(TARGET ChakraHelloWorld POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_BINARY_DIR}/ChakraCore Samples/Hello World/Linux_OSX/ChakraHelloWorld" + ${CMAKE_BINARY_DIR}/ + ) +endif() + +add_dependencies(ChakraHelloWorld CopyChakraHeaders) + + +if(PC_ICU_UC_FOUND AND PC_ICU_I18N_FOUND) + target_link_libraries(ChakraHelloWorld ${PC_ICU_UC_LIBRARIES} ${PC_ICU_I18N_LIBRARIES}) +endif() + +target_include_directories (ChakraHelloWorld + PUBLIC "${CMAKE_BINARY_DIR}/include") diff --git a/ChakraCore Samples/Hello World/Linux_OSX/sample.cpp b/ChakraCore Samples/Hello World/Linux_OSX/sample.cpp index 065110c..a586fce 100644 --- a/ChakraCore Samples/Hello World/Linux_OSX/sample.cpp +++ b/ChakraCore Samples/Hello World/Linux_OSX/sample.cpp @@ -33,6 +33,8 @@ int main() // Your script; try replace hello-world with something else const char* script = "(()=>{return \'Hello World!\';})()"; + FAIL_CHECK(JsInitializeRuntime(0, nullptr)); + // Create a runtime. FAIL_CHECK(JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime)); @@ -69,6 +71,7 @@ int main() // Dispose runtime FAIL_CHECK(JsSetCurrentContext(JS_INVALID_REFERENCE)); FAIL_CHECK(JsDisposeRuntime(runtime)); + FAIL_CHECK(JsFinalizeRuntime()); return 0; } diff --git a/ChakraCore Samples/OpenGL Engine/CMakeLists.txt b/ChakraCore Samples/OpenGL Engine/CMakeLists.txt new file mode 100644 index 0000000..d522522 --- /dev/null +++ b/ChakraCore Samples/OpenGL Engine/CMakeLists.txt @@ -0,0 +1,107 @@ + +add_executable (ChakraOpenGLEngine + OpenGLEngine/Canvas.cpp + OpenGLEngine/Task.cpp + OpenGLEngine/main.cpp + OpenGLEngine/ChakraCoreHost.cpp + OpenGLEngine/Shape.cpp +) + +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(LINKER_START_GROUP -Wl,--start-group) + set(LINKER_END_GROUP -Wl,--end-group) +endif() + +if(CC_TARGETS_X86) + set(lib_target "-m32") +endif() + + +# Link against OpenGL +target_include_directories (ChakraOpenGLEngine PUBLIC "${OPENGL_INCLUDE_DIR}") + +# Link against GLEW +if(PC_GLEW_FOUND) + # This should include internationalization. + target_include_directories (ChakraOpenGLEngine PUBLIC "${PC_GLEW_INCLUDE_DIRS}" ) +endif() + +# Link against GLFW. +if(PC_GLFW_FOUND) + # This should include internationalization. + target_include_directories (ChakraOpenGLEngine PUBLIC "${PC_GLFW_INCLUDE_DIRS}") +endif() + +# common link deps +if(TARGET ChakraCore) + #Use ChakraCore shared Library. + set(lib_target "${lib_target}" + -Wl,-undefined,error + ${LINKER_START_GROUP} + ChakraCore + ${LINKER_END_GROUP} + ${PC_GLEW_LDFLAGS} + ${PC_GLFW_LDFLAGS} + ${OPENGL_gl_LIBRARY} + ${PC_ICU_UC_LIBRARIES} + ${PC_ICU_I18N_LIBRARIES} + ) +else() + #Use ChakraCore Static Library. + set(lib_target "${lib_target}" + -Wl,-undefined,error + ${LINKER_START_GROUP} + Chakra.Common.Core + Chakra.Jsrt + Chakra.Pal + ${LINKER_END_GROUP} + ${PC_GLEW_LDFLAGS} + ${PC_GLFW_LDFLAGS} + ${OPENGL_gl_LIBRARY} + ${LINKER_END_GROUP} + ) +endif() + + + +target_link_libraries(ChakraOpenGLEngine ${lib_target} ) + +#use C++11 +SET_TARGET_PROPERTIES(ChakraOpenGLEngine PROPERTIES COMPILE_FLAGS + "-std=c++11 -Wno-pragma-once-outside-header" + ) + +add_dependencies(ChakraOpenGLEngine CopyChakraHeaders) +target_include_directories (ChakraOpenGLEngine PUBLIC "${CMAKE_BINARY_DIR}/include") + + + +if(NOT CC_XCODE_PROJECT) + set(CC_LIB_EXT "so") + # Post build step to copy the built shared library + # to BuildLinux (or whatever the CMakeBuildDir is) + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CC_LIB_EXT "dylib") + endif() + if(TARGET ChakraCore) + add_custom_command(TARGET ChakraOpenGLEngine POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_BINARY_DIR}/ChakraCore/libChakraCore.${CC_LIB_EXT}" + "${CMAKE_BINARY_DIR}/" + ) + endif() + # Copy ChakraOpenGLEngine to Binary Directory. + add_custom_command(TARGET ChakraOpenGLEngine POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_BINARY_DIR}/ChakraCore Samples/OpenGL Engine/ChakraOpenGLEngine" + "${CMAKE_BINARY_DIR}/" + ) + # Copy the Example Javascript file. + add_custom_command(TARGET ChakraOpenGLEngine POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/OpenGLEngine/app.js" + "${CMAKE_BINARY_DIR}/" + ) + +endif() + diff --git a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.cpp b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.cpp index 8f1c9f7..5129ba3 100644 --- a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.cpp +++ b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.cpp @@ -1,4 +1,6 @@ #pragma once +#include +#include #include "Canvas.h" Canvas::Canvas() @@ -75,4 +77,4 @@ void Canvas::render() Canvas::~Canvas() { glfwTerminate(); -} \ No newline at end of file +} diff --git a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.cpp b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.cpp index d933c5f..5d0e08d 100644 --- a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.cpp +++ b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.cpp @@ -1,9 +1,15 @@ #pragma once -#include "ChakraCoreHost.h" #include +#include +#include +#include #include #include +#include "ChakraCoreHost.h" + + + using namespace std; // ************************************************************ @@ -26,6 +32,10 @@ ChakraCoreHost::ChakraCoreHost() currentSourceContext = 0; JsContextRef context; + // Initialize the ChakraCore runtime Library. + if (JsInitializeRuntime(0, nullptr) != JsNoError) + throw "failed to Initialize runtime."; + // Create the runtime. We're only going to use one runtime for this host. if (JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime) != JsNoError) throw "failed to create runtime."; @@ -51,12 +61,23 @@ ChakraCoreHost::ChakraCoreHost() wstring ChakraCoreHost::loadScript(wstring fileName) { FILE *file; +#ifdef _WIN32 if (_wfopen_s(&file, fileName.c_str(), L"rb")) { fwprintf(stderr, L"chakrahost: unable to open file: %s.\n", fileName.c_str()); return wstring(); } - +#else + /* Most paths should fit in 4096 wide characters.*/ + char mbFilename[4096]; + snprintf(mbFilename,4096,"%S",fileName.c_str()); + file = fopen(mbFilename, "rb"); + if (file == NULL) + { + fwprintf(stderr, L"chakrahost: unable to open file: %s.\n", fileName.c_str()); + return wstring(); + } +#endif unsigned int current = ftell(file); fseek(file, 0, SEEK_END); unsigned int end = ftell(file); @@ -71,7 +92,7 @@ wstring ChakraCoreHost::loadScript(wstring fileName) } fread((void *)rawBytes, sizeof(char), lengthBytes, file); - +#ifdef _WIN32 wchar_t *contents = (wchar_t *)calloc(lengthBytes + 1, sizeof(wchar_t)); if (contents == nullptr) { @@ -87,13 +108,88 @@ wstring ChakraCoreHost::loadScript(wstring fileName) fwprintf(stderr, L"chakrahost: fatal error.\n"); return wstring(); } +#else + mbstate_t mbState; + memset(&mbState,0,sizeof(mbstate_t)); + mbrlen(NULL,0,&mbState); + /* Determine size of New Buffer */ + size_t wstringLen = mbsrtowcs((wchar_t*)nullptr,(const char **)&rawBytes,0,&mbState); + if(wstringLen == (size_t)-1) + { + /* Invalid Character Found */ + free(rawBytes); + fwprintf(stderr, L"chakrahost: fatal error.\n"); + return wstring(); + } + wstringLen++; + wchar_t *contents = (wchar_t *)calloc(wstringLen, sizeof(wchar_t)); + if (contents == nullptr) + { + free(rawBytes); + fwprintf(stderr, L"chakrahost: fatal error.\n"); + return wstring(); + } + mbsrtowcs(contents,(const char **)&rawBytes,wstringLen,&mbState); +#endif wstring result = contents; free(rawBytes); free(contents); return result; } +JsErrorCode ChakraCoreHost::getStringPointer(JsValueRef messageValue, wchar_t **result, size_t* resultLength) +{ +#if defined(_WIN32) + return JsStringToPointer(messageValue, result, resultLength) != JsNoError); +#else + JsErrorCode results; + wchar_t *contents = nullptr; + size_t contentsLen; + uint8_t *utf8String; + size_t utf8LenLength; + results = JsCopyStringUtf8(messageValue, nullptr,0, &utf8LenLength); + if(results != JsNoError) + { + return results; + } + utf8String = (uint8_t*)malloc(utf8LenLength+1); + JsCopyStringUtf8(messageValue, utf8String,utf8LenLength+1,nullptr); + if(results != JsNoError) + { + /* Failed to Copy String */ + free(utf8String); + return results; + } + utf8String[utf8LenLength] = 0; + mbstate_t mbState; + memset(&mbState,0,sizeof(mbstate_t)); + mbrlen(NULL,0,&mbState); + /* Determine size of New Buffer */ + contentsLen = mbsrtowcs((wchar_t*)nullptr,(const char **)&utf8String,0,&mbState); + if(contentsLen == (size_t)-1) + { + /* Invalid Character Found */ + free(utf8String); + // TODO: Temporary... need better result. + return JsErrorOutOfMemory; + } + contentsLen++; + contents = (wchar_t *)calloc(contentsLen, sizeof(wchar_t)); + if (contents == nullptr) + { + free(utf8String); + return JsErrorOutOfMemory; + } + + mbsrtowcs(contents,(const char **)&utf8String,contentsLen,&mbState); + free(utf8String); + *result=contents; + *resultLength=contentsLen; + return results; +#endif +} + // run script wstring ChakraCoreHost::runScript(wstring script) { @@ -101,28 +197,52 @@ wstring ChakraCoreHost::runScript(wstring script) { JsValueRef result; JsValueRef promiseResult; - +#if !defined(_WIN32) + mbstate_t mbState; + const wchar_t* scriptSrc = script.c_str(); + memset(&mbState,0,sizeof(mbstate_t)); + mbrlen(NULL,0,&mbState); + size_t wideStringLength = wcslen(scriptSrc); + size_t multiByteStringLength = wcsrtombs(nullptr,&scriptSrc,0,&mbState); + size_t conversionResult; + char* mbString = (char *)calloc(multiByteStringLength + 1, sizeof(char)); + conversionResult = wcsrtombs(mbString,&scriptSrc,multiByteStringLength,&mbState); + JsValueRef ScriptSource; + JsCreateStringUtf8((uint8_t*)mbString,multiByteStringLength,&ScriptSource); + JsValueRef ScriptName; + JsCreateStringUtf8((uint8_t*)"",1,&ScriptName); + // Run the script. + if (JsRun(ScriptSource, currentSourceContext++, ScriptName,JsParseScriptAttributeNone, &result) != JsNoError) + { +#else // Run the script. if (JsRunScript(script.c_str(), currentSourceContext++, L"", &result) != JsNoError) { +#endif // Get error message JsValueRef exception; if (JsGetAndClearException(&exception) != JsNoError) return L"failed to get and clear exception"; JsPropertyIdRef messageName; - if (JsGetPropertyIdFromName(L"message", &messageName) != JsNoError) + if (getPropertyID(L"message", &messageName) != JsNoError) return L"failed to get error message id"; JsValueRef messageValue; if (JsGetProperty(exception, messageName, &messageValue)) return L"failed to get error message"; +#if defined(_WIN32) const wchar_t *message; size_t length; if (JsStringToPointer(messageValue, &message, &length) != JsNoError) return L"failed to convert error message"; - +#else + wchar_t *message; + size_t length; + if (getStringPointer(messageValue, &message, &length) != JsNoError) + return L"failed to convert error message"; +#endif return message; } @@ -148,12 +268,21 @@ wstring ChakraCoreHost::runScript(wstring script) // Convert the return value to wstring. JsValueRef stringResult; - const wchar_t *returnValue; - size_t stringLength; + if (JsConvertValueToString(result, &stringResult) != JsNoError) return L"failed to convert value to string."; + +#if defined(_WIN32) + const wchar_t *returnValue; + size_t stringLength; if (JsStringToPointer(stringResult, &returnValue, &stringLength) != JsNoError) return L"failed to convert return value."; +#else + wchar_t *returnValue; + size_t stringLength; + if (getStringPointer(stringResult, &returnValue, &stringLength) != JsNoError) + return L"failed to convert return value."; +#endif return returnValue; } catch (...) @@ -162,9 +291,29 @@ wstring ChakraCoreHost::runScript(wstring script) } } +JsErrorCode ChakraCoreHost::getPropertyID(const wchar_t *propertyName, JsPropertyIdRef *propertyId) +{ +#if defined(_WIN32) + return JsGetPropertyIdFromName(propertyName, propertyId); +#else + mbstate_t mbState; + memset(&mbState,0,sizeof(mbstate_t)); + mbrlen(NULL,0,&mbState); + size_t wideStringLength = wcslen(propertyName); + size_t multiByteStringLength = wcsrtombs(nullptr,&propertyName,0,&mbState); + size_t conversionResult; + char* mbString = (char *)calloc(multiByteStringLength + 1, sizeof(char)); + conversionResult = wcsrtombs(mbString,&propertyName,multiByteStringLength,&mbState); + + return JsCreatePropertyIdUtf8(mbString, multiByteStringLength,propertyId); +#endif + +} + ChakraCoreHost::~ChakraCoreHost() { JsDisposeRuntime(runtime); + JsFinalizeRuntime(); } // ************************************************************ @@ -184,10 +333,30 @@ JsValueRef Binding::mouseCallbackThisArg; // Binding - Util functions // ****************************** +JsErrorCode Binding::getPropertyID(const wchar_t *propertyName, JsPropertyIdRef *propertyId) +{ +#if defined(_WIN32) + return JsGetPropertyIdFromName(propertyName, propertyId); +#else + mbstate_t mbState; + memset(&mbState,0,sizeof(mbstate_t)); + mbrlen(NULL,0,&mbState); + size_t wideStringLength = wcslen(propertyName); + size_t multiByteStringLength = wcsrtombs(nullptr,&propertyName,0,&mbState); + size_t conversionResult; + char* mbString = (char *)calloc(multiByteStringLength + 1, sizeof(char)); + conversionResult = wcsrtombs(mbString,&propertyName,multiByteStringLength,&mbState); + + return JsCreatePropertyIdUtf8(mbString, multiByteStringLength,propertyId); +#endif + +} + + void Binding::setCallback(JsValueRef object, const wchar_t *propertyName, JsNativeFunction callback, void *callbackState) { JsPropertyIdRef propertyId; - JsGetPropertyIdFromName(propertyName, &propertyId); + getPropertyID(propertyName, &propertyId); JsValueRef function; JsCreateFunction(callback, callbackState, &function); JsSetProperty(object, propertyId, function, true); @@ -196,7 +365,7 @@ void Binding::setCallback(JsValueRef object, const wchar_t *propertyName, JsNati void Binding::setProperty(JsValueRef object, const wchar_t *propertyName, JsValueRef property) { JsPropertyIdRef propertyId; - JsGetPropertyIdFromName(propertyName, &propertyId); + getPropertyID(propertyName, &propertyId); JsSetProperty(object, propertyId, property, true); } @@ -204,7 +373,7 @@ JsValueRef Binding::getProperty(JsValueRef object, const wchar_t *propertyName) { JsValueRef output; JsPropertyIdRef propertyId; - JsGetPropertyIdFromName(propertyName, &propertyId); + getPropertyID(propertyName, &propertyId); JsGetProperty(object, propertyId, &output); return output; } @@ -224,10 +393,20 @@ JsValueRef CALLBACK Binding::JSLog(JsValueRef callee, bool isConstructCall, JsVa } JsValueRef stringValue; JsConvertValueToString(arguments[index], &stringValue); +#if defined(_WIN32) const wchar_t *string; size_t length; JsStringToPointer(stringValue, &string, &length); wprintf(L"%s", string); +#else + uint8_t *utf8String; + size_t stringLength; + JsCopyStringUtf8(stringValue, nullptr,0, &stringLength); + utf8String = (uint8_t*)malloc(stringLength+1); + JsCopyStringUtf8(stringValue, utf8String,stringLength+1,nullptr); + utf8String[stringLength] = 0; + printf("%s", utf8String); +#endif } wprintf(L"\n"); return JS_INVALID_REFERENCE; diff --git a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.h b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.h index 0729c58..b690dfa 100644 --- a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.h +++ b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.h @@ -4,6 +4,11 @@ #include "ChakraCore.h" #include +#ifndef CALLBACK +#define CALLBACK +#endif + + using namespace std; // a JavaScript host powered by ChakraCore @@ -12,6 +17,9 @@ class ChakraCoreHost private: JsRuntimeHandle runtime; unsigned currentSourceContext; + JsErrorCode getPropertyID(const wchar_t *propertyName, JsPropertyIdRef *propertyId); + JsErrorCode getStringPointer(JsValueRef messageValue, wchar_t **result, size_t* length); + public: queue taskQueue; Canvas canvas; @@ -37,6 +45,7 @@ class Binding static JsValueRef mouseCallbackThisArg; static void setCallback(JsValueRef object, const wchar_t *propertyName, JsNativeFunction callback, void *callbackState); static void setProperty(JsValueRef object, const wchar_t *propertyName, JsValueRef property); + static JsErrorCode getPropertyID(const wchar_t *propertyName, JsPropertyIdRef *propID); static JsValueRef getProperty(JsValueRef object, const wchar_t *propertyName); static JsValueRef CALLBACK JSLog(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState); static JsValueRef CALLBACK JSSetTimeout(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState); diff --git a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/main.cpp b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/main.cpp index 1f21e0a..25b6bd0 100644 --- a/ChakraCore Samples/OpenGL Engine/OpenGLEngine/main.cpp +++ b/ChakraCore Samples/OpenGL Engine/OpenGLEngine/main.cpp @@ -1,3 +1,5 @@ + +#include #include "ChakraCoreHost.h" int main() diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..1ec44ff --- /dev/null +++ b/build.sh @@ -0,0 +1,358 @@ +#!/bin/bash +#------------------------------------------------------------------------------------------------------- +# Copyright (C) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +#------------------------------------------------------------------------------------------------------- + +SAFE_RUN() { + local SF_RETURN_VALUE=$($1 2>&1) + + if [[ $? != 0 ]]; then + >&2 echo $SF_RETURN_VALUE + exit 1 + fi + echo $SF_RETURN_VALUE +} + +ERROR_EXIT() { + if [[ $? != 0 ]]; then + echo $($1 2>&1) + exit 1; + fi +} + +PRINT_USAGE() { + echo "" + echo "[ChakraCore Build Script Help]" + echo "" + echo "build.sh [options]" + echo "" + echo "options:" + echo " --arch=[*] Set target arch (x86)" + echo " --cc=PATH Path to Clang (see example below)" + echo " --cxx=PATH Path to Clang++ (see example below)" + echo " -d, --debug Debug build (by default Release build)" + echo " --embed-icu Download and embed ICU-57 statically" + echo " -h, --help Show help" + echo " --icu=PATH Path to ICU include folder (see example below)" + echo " -j [N], --jobs[=N] Multicore build, allow N jobs at once" + echo " -n, --ninja Build with ninja instead of make" + echo " --no-icu Compile without unicode/icu support" + echo " --no-jit Disable JIT" + echo " --lto Enables LLVM Full LTO" + echo " --lto-thin Enables LLVM Thin LTO - xcode 8+ or clang 3.9+" + echo " --static Build as static library (by default shared library)" + echo " --sanitize=CHECKS Build with clang -fsanitize checks," + echo " e.g. undefined,signed-integer-overflow" + echo " -t, --test-build Test build (by default Release build)" + echo " --xcode Generate XCode project" + echo " --without=FEATURE,FEATURE,..." + echo " Disable FEATUREs from JSRT experimental" + echo " features." + echo " -v, --verbose Display verbose output including all options" + echo "" + echo "example:" + echo " ./build.sh --cxx=/path/to/clang++ --cc=/path/to/clang -j" + echo "with icu:" + echo " ./build.sh --icu=/usr/local/opt/icu4c/include" + echo "" +} + +CHAKRACORE_DIR=`dirname $0` +_CXX="" +_CC="" +_VERBOSE="" +BUILD_TYPE="Release" +CMAKE_GEN= +MAKE=make +MULTICORE_BUILD="" +NO_JIT= +ICU_PATH="-DICU_SETTINGS_RESET=1" +STATIC_LIBRARY="-DCC_BUILD_SHARED_LIBRARY=1" +SANITIZE= +WITHOUT_FEATURES="" +CREATE_DEB=0 +ARCH="-DCC_TARGETS_AMD64_SH=1" +OS_LINUX=0 +OS_APT_GET=0 +OS_UNIX=0 +LTO="" + +if [ -f "/proc/version" ]; then + OS_LINUX=1 + PROC_INFO=$(cat /proc/version) + if [[ $PROC_INFO =~ 'Ubuntu' || $PROC_INFO =~ 'Debian' + || $PROC_INFO =~ 'Linaro' ]]; then + OS_APT_GET=1 + fi +else + OS_UNIX=1 +fi + +while [[ $# -gt 0 ]]; do + case "$1" in + --arch=*) + ARCH=$1 + ARCH="${ARCH:7}" + ;; + + --cxx=*) + _CXX=$1 + _CXX=${_CXX:6} + ;; + + --cc=*) + _CC=$1 + _CC=${_CC:5} + ;; + + -h | --help) + PRINT_USAGE + exit + ;; + + -v | --verbose) + _VERBOSE="V=1" + ;; + + -d | --debug) + BUILD_TYPE="Debug" + ;; + + --embed-icu) + if [ ! -d "${CHAKRACORE_DIR}/deps/icu/source/output" ]; then + ICU_URL="http://source.icu-project.org/repos/icu/icu/tags/release-57-1" + echo -e "\n----------------------------------------------------------------" + echo -e "\nThis script will download ICU-LIB from\n${ICU_URL}\n" + echo "It is licensed to you by its publisher, not Microsoft." + echo "Microsoft is not responsible for the software." + echo "Your installation and use of ICU-LIB is subject to the publisher’s terms available here:" + echo -e "http://www.unicode.org/copyright.html#License\n" + echo -e "----------------------------------------------------------------\n" + echo "If you don't agree, press Ctrl+C to terminate" + read -t 10 -p "Hit ENTER to continue (or wait 10 seconds)" + SAFE_RUN `mkdir -p ${CHAKRACORE_DIR}/deps/` + cd "${CHAKRACORE_DIR}/deps/"; + ABS_DIR=`pwd` + if [ ! -d "${ABS_DIR}/icu/" ]; then + echo "Downloading ICU ${ICU_URL}" + if [ ! -f "/usr/bin/svn" ]; then + echo -e "\nYou should install 'svn' client in order to use this feature" + if [ $OS_APT_GET == 1 ]; then + echo "tip: Try 'sudo apt-get install subversion'" + fi + exit 1 + fi + svn export -q $ICU_URL icu + ERROR_EXIT "rm -rf ${ABS_DIR}/icu/" + fi + + cd "${ABS_DIR}/icu/source";./configure --with-data-packaging=static\ + --prefix="${ABS_DIR}/icu/source/output/"\ + --enable-static --disable-shared --with-library-bits=64\ + --disable-icuio --disable-layout\ + CXXFLAGS="-fPIC" CFLAGS="-fPIC" + + ERROR_EXIT "rm -rf ${ABS_DIR}/icu/source/output/" + make STATICCFLAGS="-fPIC" STATICCXXFLAGS="-fPIC" STATICCPPFLAGS="-DPIC" install + ERROR_EXIT "rm -rf ${ABS_DIR}/icu/source/output/" + cd "${ABS_DIR}/../" + fi + ICU_PATH="-DCC_EMBED_ICU_SH=1" + ;; + + + -t | --test-build) + BUILD_TYPE="Test" + ;; + + -j | --jobs) + if [[ "$1" == "-j" && "$2" =~ ^[^-] ]]; then + MULTICORE_BUILD="-j $2" + shift + else + MULTICORE_BUILD="-j $(nproc)" + fi + ;; + + -j=* | --jobs=*) # -j=N syntax used in CI + MULTICORE_BUILD=$1 + if [[ "$1" =~ ^-j= ]]; then + MULTICORE_BUILD="-j ${MULTICORE_BUILD:3}" + else + MULTICORE_BUILD="-j ${MULTICORE_BUILD:7}" + fi + ;; + + --icu=*) + ICU_PATH=$1 + ICU_PATH="-DICU_INCLUDE_PATH_SH=${ICU_PATH:6}" + ;; + + --lto) + LTO="-DCC_ENABLE_FULL_LTO=1" + ;; + + --lto-thin) + LTO="-DCC_ENABLE_THIN_LTO=1" + ;; + + -n | --ninja) + CMAKE_GEN="-G Ninja" + MAKE=ninja + ;; + + --no-icu) + ICU_PATH="-DNO_ICU_PATH_GIVEN_SH=1" + ;; + + --no-jit) + NO_JIT="-DCC_ENABLE_JIT=0" + ;; + + --xcode) + CMAKE_GEN="-G Xcode -DCC_XCODE_PROJECT=1" + MAKE=0 + ;; + + --create-deb=*) + CREATE_DEB=$1 + CREATE_DEB="${CREATE_DEB:13}" + ;; + + --static) + STATIC_LIBRARY="-DCC_BUILD_STATIC_LIBRARY=1" + ;; + + --sanitize=*) + SANITIZE=$1 + SANITIZE=${SANITIZE:11} # value after --sanitize= + SANITIZE="-DCLANG_SANITIZE_SH=${SANITIZE}" + ;; + + --without=*) + FEATURES=$1 + FEATURES=${FEATURES:10} # value after --without= + for x in ${FEATURES//,/ } # replace comma with space then split + do + if [[ "$WITHOUT_FEATURES" == "" ]]; then + WITHOUT_FEATURES="-DWITHOUT_FEATURES_SH=" + else + WITHOUT_FEATURES="$WITHOUT_FEATURES;" + fi + WITHOUT_FEATURES="${WITHOUT_FEATURES}-DCOMPILE_DISABLE_${x}=1" + done + ;; + + *) + echo "Unknown option $1" + PRINT_USAGE + exit -1 + ;; + esac + + shift +done + +if [[ ${#_VERBOSE} > 0 ]]; then + # echo options back to the user + echo "Printing command line options back to the user:" + echo "_CXX=${_CXX}" + echo "_CC=${_CC}" + echo "BUILD_TYPE=${BUILD_TYPE}" + echo "MULTICORE_BUILD=${MULTICORE_BUILD}" + echo "ICU_PATH=${ICU_PATH}" + echo "CMAKE_GEN=${CMAKE_GEN}" + echo "MAKE=${MAKE} $_VERBOSE" + echo "" +fi + +CLANG_PATH= +if [[ ${#_CXX} > 0 || ${#_CC} > 0 ]]; then + if [[ ${#_CXX} == 0 || ${#_CC} == 0 ]]; then + echo "ERROR: '-cxx' and '-cc' options must be used together." + exit 1 + fi + echo "Custom CXX ${_CXX}" + echo "Custom CC ${_CC}" + + if [[ ! -f $_CXX || ! -f $_CC ]]; then + echo "ERROR: Custom compiler not found on given path" + exit 1 + fi + CLANG_PATH=$_CXX +else + RET_VAL=$(SAFE_RUN 'c++ --version') + if [[ ! $RET_VAL =~ "clang" ]]; then + echo "Searching for Clang..." + if [[ -f /usr/bin/clang++ ]]; then + echo "Clang++ found at /usr/bin/clang++" + _CXX=/usr/bin/clang++ + _CC=/usr/bin/clang + CLANG_PATH=$_CXX + else + echo "ERROR: clang++ not found at /usr/bin/clang++" + echo "" + echo "You could use clang++ from a custom location." + PRINT_USAGE + exit 1 + fi + else + CLANG_PATH=c++ + fi +fi + +# check clang version (min required 3.7) +VERSION=$($CLANG_PATH --version | grep "version [0-9]*\.[0-9]*" --o -i | grep "[0-9]\.[0-9]*" --o) +VERSION=${VERSION/./} + +if [[ $VERSION -lt 37 ]]; then + echo "ERROR: Minimum required Clang version is 3.7" + exit 1 +fi + +CC_PREFIX="" +if [[ ${#_CXX} > 0 ]]; then + CC_PREFIX="-DCMAKE_CXX_COMPILER=$_CXX -DCMAKE_C_COMPILER=$_CC" +fi + +if [[ $STATIC_LIBRARY == "-DCC_BUILD_SHARED_LIBRARY=1" ]]; then + build_directory="$CHAKRACORE_DIR/BuildLinux/${BUILD_TYPE:0}" +else + build_directory="$CHAKRACORE_DIR/BuildLinux/Static${BUILD_TYPE:0}" +fi + + +if [ ! -d "$build_directory" ]; then + SAFE_RUN `mkdir -p $build_directory` +fi + +pushd $build_directory > /dev/null + +if [ $ARCH = "x86" ]; then + ARCH="-DCC_TARGETS_X86_SH=1" + echo "Compile Target : x86" +else + echo "Compile Target : amd64" +fi + +echo Generating $BUILD_TYPE makefiles +cmake $CMAKE_GEN $CC_PREFIX $ICU_PATH $LTO $STATIC_LIBRARY $ARCH \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SANITIZE $NO_JIT $WITHOUT_FEATURES ../.. + +_RET=$? +if [[ $? == 0 ]]; then + if [[ $MAKE != 0 ]]; then + $MAKE $MULTICORE_BUILD $_VERBOSE 2>&1 | tee build.log + _RET=${PIPESTATUS[0]} + else + echo "Visit given folder above for xcode project file ----^" + fi +fi + +if [[ $_RET != 0 ]]; then + echo "See error details above. Exit code was $_RET" +fi + +popd > /dev/null +exit $_RET