chakra-core / ChakraCore

ChakraCore is an open source Javascript engine with a C API.
MIT License
9.1k stars 1.19k forks source link

Feature Request: Enable ChakraCore embedding using CMake. #1616

Open kphillisjr opened 7 years ago

kphillisjr commented 7 years ago

I noticed that the current system for integrating ChakraCore using CMake is not exactly one of the most friendly. All this really boils down to is simplifying the auto-detection for CMake to where all of the platform dependent configuration is handled easily, and build options are easily configured by ChakraCore. In general this can be broken down into several tasks.

[1] CMake Wiki: How To Write Platform Checks [2] CMake Wiki: How To Find Libraries [3] CPack is highly useful for when users want to generate installable packages using for chakra. [3] CMake Wiki: Packaging With CPack [4] GLFW: Building Applications [5] For Simplicity's sake, this target will create the folder ${CMAKE_BINARY_DIR}/include, and then proceed to copy these headers to the newly created folder during configuration. [6] Most developers on windows will probably never use this option, but this should be a fairly straight forward fix.

obastemur commented 7 years ago

@kphillisjr Thanks for the issue but can't say we are missing any important item from this list already.

Could you be more specific on friendly part? See ./build.sh --help

kphillisjr commented 7 years ago

The friendly part is to reduce the amount of work a developer requires to get ChakraCore working using cmake. An example of this uses the Hello World example in Chakra-Samples.

Example CMakeLists.txt file that will automatically compile and embed ChakraCore into the project:

cmake_minimum_required(VERSION 3.2)

project(ChakraCoreHelloWorld)

# in general, this will be at the top level of the source tree.
# Many developers will use src/lib/ChakraCore or libs/ChakraCore.
add_subdirectory(path/to/ChakraCore)

if(UNIX)
    set(ChakraCoreHelloWorldSources 
            "ChakraCore Samples/Hello World/Linux_OSX/sample.cpp"
        )
elseif(WIN32)
    set(ChakraCoreHelloWorldSources
        "ChakraCore Samples/Hello World/Windows/C++/HelloWorld/HelloWorld.cpp"
    )
endif(WIN32)

add_executable(ChakraCoreHelloWorld ${ChakraCoreHelloWorldSources})

set_target_properties(ChakraCoreHelloWorld
  PROPERTIES
  POSITION_INDEPENDENT_CODE True
)

target_include_directories(ChakraCoreHelloWorld ${CMAKE_BINARY_DIR}/include)
# Tell CMake to use the ChakraCore Library.
target_link_libraries(ChakraCoreHelloWorld ChakraCore)
# TODO: Tell CMake to link to the ChakraCore Dependencies for the platform.
target_link_libraries(ChakraCoreHelloWorld ${CHAKRACORE_LIBS})

The Cmake Command to build this project ( on linux):

cmake path/to/project
make -j4
obastemur commented 7 years ago

Sorry, I guess, I didn't understand.

Do you mean that we are missing a CMake sample (or simple sample) for API users on xplat? Can't argue on that and say nothing but appreciate a PR to https://github.com/Microsoft/Chakra-Samples repo.

kphillisjr commented 7 years ago

No, This bug report is not about missing CMake examples in the Chakra-Samples repository. I just used the HelloWorld example from that git repository to illustrate how someone would go about handling a friendly method of building chakracore using nothing but cmake internally.

This bug report is to enable users to embed ChakraCore with trivial work, and expect cmake to be able to get the project working on windows/linux/osx without many problems. Here's another example where two other projects with embed-able cmake build files.

cmake_minimum_required(VERSION 3.2)

project(ChakraCoreOpenGLEngine)

find_package(OpenGL REQUIRED)

# Configure and add GLFW subdirectory.
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
# NOTE: Default build options on GLFW is static.
add_subdirectory(libs/glfw)

# Configure GLEW:
set(BUILD_UTILS OFF CACHE BOOL "" FORCE)
set(GLEW_OSMESA OFF CACHE BOOL "" FORCE)
set(GLEW_REGAL  OFF CACHE BOOL "" FORCE)
add_subdirectory(libs/glew/cmake)

# This expects the ChakraCore epository to be located in libs/ChakraCore.
add_subdirectory(libs/ChakraCore)

set(ChakraCoreOpenGLEngineSources 
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.cpp"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Canvas.h"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.cpp"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/ChakraCoreHost.h"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Shape.cpp"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Shape.h"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Task.cpp"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/Task.h"
    "ChakraCore Samples/OpenGL Engine/OpenGLEngine/main.cpp" 
)

# TODO: Copy app.js to an appropriate location.

add_executable(ChakraCoreOpenGLEngine ${ChakraCoreOpenGLEngineSources })

set_target_properties(ChakraCoreOpenGLEngine
  PROPERTIES
  POSITION_INDEPENDENT_CODE True
)

# OpenGL Dependency.
target_link_libraries(ChakraCoreOpenGLEngine ${OPENGL_gl_LIBRARY})
target_include_directories(ChakraCoreOpenGLEngine ${OPENGL_INCLUDE_DIR})

# GLFW Dependency.
target_link_libraries(ChakraCoreOpenGLEngine glfw)

# GLEW Dependency.
target_link_libraries(ChakraCoreOpenGLEngine glew_s)

# Tell CMake to use the ChakraCore Library.
target_include_directories(ChakraCoreOpenGLEngine ${CMAKE_BINARY_DIR}/include)
target_link_libraries(ChakraCoreOpenGLEngine ChakraCore)
# TODO: Tell CMake to link to the ChakraCore Dependencies for the platform.
target_link_libraries(ChakraCoreOpenGLEngine ${CHAKRACORE_LIBS})
kphillisjr commented 7 years ago

A major update on this bug report... I have created the Initial example on how to build ChakraCore in an embedded scenario where the Chakra-Samples ( hello world only for now ) are the source tree... The two branches for this are located at: ChakraCore: https://github.com/kphillisjr/ChakraCore/tree/cmake_embed_v1 ChakraCore Samples: https://github.com/kphillisjr/Chakra-Samples/tree/samples_add_cmake

The example usage is as follows...

Source Download and prep:

git clone https://github.com/kphillisjr/Chakra-Samples.git
git checkout origin/samples_add_cmake

git clone https://github.com/kphillisjr/ChakraCore.git
git checkout origin/cmake_embed_v1

cd Chakra-Samples
# Create a symbolic link to the ChakraCore Source
ln -s ../ChakraCore

Building using build.sh:

# This assumes that you can already build ChakraCore using ninja.
./build.sh -n

Alternate Build example:

# This assumes that you can already build ChakraCore using ninja.
mkdir build
cd build
# Clang is currently the only way to compile ChakraCore on linux... so use it now.
cmake -G Ninja  -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
#wait for cmake to finish.

#build the example...
ninja
# if there is no errors, run the example...
./ChakraHelloWorld
kphillisjr commented 7 years ago

I think that it would not hurt to include @liminzhu in this bug report. This adds major feature changes to ChakraCore (and the ChakraCore samples) after all.

kphillisjr commented 7 years ago

I got a few more commits on the both trees... Anyways there is bugs in the debug build (for both the Hello World example and OpenGL Example ) where ChakraCore fails internally on Debug builds when linking to a shared library.

Edit 1: uploaded a new branch that has all code from master merged... https://github.com/kphillisjr/ChakraCore/tree/cmake_embed_v2 ... This still has issues with Shared Library debug build.

Edit 2: I created another issue about the Shared Debug library being broken. See issue #2052 )

bjconlan commented 7 years ago

Damn, I wish I had found this before the weekend was over (although now I have a better understanding of cmake which I urgently wish to forget ;). This is great stuff Mr Phillis I've been trying to get all this working seemlessly with my own project (went down the 'ExternalProject_Add' path but generally unsatisfied with it as it also includes some linux specific hacks/patch state to have the headers resolved and installed and include the conditional static/dynamic library).

In the end I just modified the build script to roll a 'libchakracore-dev' package with all the files (headers/binaries) hand rolled... hardly ideal but works for the moment. I'll now have to revisit this since this work overcomes many of the issue I was unsatisfied with (and it looks like you've actually considered osx).

Nice work.

kphillisjr commented 7 years ago

The changes I am making are not complete seeing as how the Chakracore shared library currently has broken shared library support ( see issue #1811 ). Also I have updated part of the task list. The tasks I have checked off are completed in the branch I created. (see: https://github.com/kphillisjr/ChakraCore/commits/cmake_embed_v2 )

dilijev commented 7 years ago

@kphillisjr Thanks for your work on this so far. We really appreciate it! We'll keep this on the radar as we continue work on cross-plat. We definitely want there to be a good experience for all of the scenarios we support.

kphillisjr commented 7 years ago

I added a few more updates and this time I believe I got most of the issues fixed involving Shared/Static Libraries. All this needs now is for @obastemur to review the change, and for @bjconlan to test things on his end to see If I missed anything.

The Changes to ChakraCore can be found here: https://github.com/kphillisjr/ChakraCore/commits/cmake_embed_v3

And example usage of the calls is in the following branch of the samples: https://github.com/kphillisjr/Chakra-Samples/tree/samples_add_cmake_v2

NOTE: I have not tested windows on this branch. I believe t he shared library for windows needs minor updates.

bjconlan commented 7 years ago

Oh absolutely I'd love to help test these changes (unfortunately I can only help on the linux/ubuntu front at this time). Will respond with any feedback over the next day or so.

Edit 1: Wow, this is looking much nicer. Literally checked out your branch as a git submodule to deps and copied the hello_world.cpp to src and created the appropriate CMakeLists.txt:

cmake_minimum_required(VERSION 3.2)
project(Samples)

add_subdirectory(deps/ChakraCore)

set(CMAKE_CXX_STANDARD 11)

add_executable(HelloWorld src/hello_world.cpp)
include_directories(ChakraCore)
target_link_libraries(HelloWorld ChakraCore)

and a basic cmake -DCC_AUTODETECT_CPU=1 and I have a working hello world example!

This is very nice. I'm sure getting this working even with an ExternalProject_add would be trivial. (mind you I've setup development using clang and all deps are installed so this might require a few more flags to be passed though for most users).

Edit 2: I've attempted the same thing, this time including -DCC_BUILD_STATIC_LIBRARY=1 and unfortunately it isn't quite as trivial (I'll look into this early next week).

kphillisjr commented 7 years ago

I added a different approach to fix the issue that is more likely to get accepted. The new approach is in pull request #2111. To use this approach you would have the following as a cmake example.

cmake_minimum_required(VERSION 3.2)
project(Samples)

include("deps/ChakraCore/ChakraAutoConfigure.cmake")
CHAKRACORE_AUTOCONFIGURE()
add_subdirectory(deps/ChakraCore)

set(CMAKE_CXX_STANDARD 11)

add_executable(HelloWorld src/hello_world.cpp)
include_directories(ChakraCore)
target_link_libraries(HelloWorld ChakraCore)

I forgot to mention this, but I have not completed support for the static library yet. The current approach for this is to link against what is shown in the Microsoft/Chakra-Samples: ChakraCore Samples/Hello World/Linux_OSX/Makefile... or to copy the libraries that ch uses.

edit: @bjconlan I think you may want to check out pull request #2124.

kphillisjr commented 7 years ago

I'm currently in the process of makeing a single static library on xplat for ChakraCore called ChakraCoreStatic. This simply makes it to where you link to libChakraCoreStatic.a instead of having to link to libChakra.Pal.a, libChakra.Common.Core.a, and libChakra.Jsrt.a to get all of the ChakraCore symbols.

Also as a quick note on this, I put this change as pull request #2138.

kphillisjr commented 7 years ago

@bjconlan - I finished merging all of the static libraries into a single library. With the latest commit in pull #2138 libChakraCoreStatic contains almost all relevant symbols. The only external dependencies are primarily libUUID, ICU libraries, and libunwind.

bjconlan commented 7 years ago

Great! Thanks for the heads up @kphillisjr. I'll give this a quick whirl today. (And thanks for the cmake snippet).

kphillisjr commented 7 years ago

I forgot to mention that the completion of this bug report ( except for fixing windows support ) is driven by 3 different pull requests. #2138, #2124 ( only needs these two commits... 68beb62a605efe253e23794da1d145a2e758d18c and 7d49290aa8f83bad4437f08dceaac37bdb1a327d), and #2129. The Headers patch just needs to have the ChakraCoreHeaders target added as a dependency to the ChakraCoreStatic target.

Once all of these changes are added I will add a subsequent change to introduce windows support to cmake where the libraries, GCStress, and ch get built using Visual Studio 2015.

bjconlan commented 7 years ago

Hey @kphillisjr, I gave this a whirl and works as advertised! I'm getting all the ch.dir failures on the static build but it doesn't concern the outcome. (and I'm sure its probably because I've just done as advertised with regards to just taking the xplat_static_lib_improvement_v3 branch and applying https://github.com/Microsoft/ChakraCore/commit/68beb62a605efe253e23794da1d145a2e758d18c to it.

Thanks for all your work @kphillisjr and keeping me abreast of this stuff. Its really made integration trivial.

kphillisjr commented 7 years ago

@bjconlan, The build errors are due to the lack of integration between the three pull requests. I plan on fixing all of these once the largest of the three is integrated ( #2138). If ya find this good, by all means post a comment on the pull request so that @obastemur can see it.

kphillisjr commented 7 years ago

@bjconlan, I went ahead and applied all required changes for this issue on the branch kphillisjr/ChakraCore at xplat_improvements_for_v2.

Just as a quick note, the headers are in the Cmake binary directory under the path "${CMAKE_BINARY_DIR}/include" with this branch, and I have updated the task listing.

bjconlan commented 7 years ago

Thanks again @kphillisjr (pardon the delay). I'll be sure to comment on the pull request also.

kphillisjr commented 7 years ago

@bjconlan - I got the static library ChakraCoreStatic building on Windows and placed the changes for this on kphillisjr/ChakraCore at xplat_improvements_for_v3. For the most part this library on windows is straight forward to use seeing as how I was able to get the OSX/Linux hello world example working on windows with only changing linker and code generation flags. The specifics on these changes are written in the commit message.

Also as a quick note, once all of these changes are added I should be able to get ChakraCore compiling using CMake and MSVC only with only minor changes.