Skip to content

Commit

Permalink
Use internal fork of LLVM
Browse files Browse the repository at this point in the history
Summary:
Place a fork of LLVM git rev c179d7b006348005d2da228aed4c3c251590baa3
under `external/llvh`(1) and modify the CMake build to use it.

I am calling it a "fork", because it is not all of LLVM. Only the parts
that are used by Hermes are included, which at this time is only parts
of `libLLVMSupporrt`. Most(2) of LLVM build scripts are removed, and it
is treated just as another ordinary library.

(1) Why `llvh`? To be able to coexist with instances of the "real" LLVM,
we must change the namespace, all public symbols containing the `llvm`
string and the include directory name. `llvh` seemed as good a name as
any. I also considered `llvm-h` and `h-llvm`, but the problem is that
they are a superstring of `llvm` so it becomes harder to search for the
`llvm` string.

Note that the actual rename will happen in a follow up diff. It would be
a massive patch.

(2) libLLVMSupport relies on pretty elaborate feature detection scripts,
which would be painful to duplicate, so for now I have preserved them
under external/llvh/cmake.

Unfortunately turning LLVM into an ordinary library is not enough, since
we were implicitly relying on a lot of functionality provided by the
LLVM build scripts. Things like setting default warning flags, easily
turning exceptions on and off, etc.

I attempted to replace it with Hermes equivalents, which are now
provided by `cmake/Hermes.cmake`:
- `add_llvm_library/tool()` is replaced by `add_hermes_library/tool()`.
- Several `LLVM_xxx` variables are replaced my similar `HERMES_xxx`
  ones.

As a result, building Hermes now requires only checking it out, and
running CMake and Ninja. It is a vastly simpler process than before.

== Limitations
- CMake LTO and ASAN builds aren't supported yet.
- The JIT requires the "real" LLVM for disassembly.

Reviewed By: avp

Differential Revision: D19658656

fbshipit-source-id: 5094d2af45e343973b1aab02c550a18b2bf93a06
  • Loading branch information
tmikov authored and facebook-github-bot committed Feb 6, 2020
1 parent b187729 commit 611cac5
Show file tree
Hide file tree
Showing 83 changed files with 3,785 additions and 691 deletions.
4 changes: 2 additions & 2 deletions API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)
set(HERMES_ENABLE_EH ON)
set(HERMES_ENABLE_RTTI ON)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${HERMES_JSI_DIR})
Expand Down
21 changes: 9 additions & 12 deletions API/hermes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

set(LLVM_OPTIONAL_SOURCES
set(HERMES_OPTIONAL_SOURCES
hermes.cpp
hermes_tracing.cpp
hermes_tracing_compat.cpp
Expand All @@ -21,7 +21,7 @@ set(api_sources
hermes_tracing_compat.cpp
)

add_llvm_library(hermesapi
add_hermes_library(hermesapi
${api_sources}
LINK_LIBS jsi hermesVMRuntime)

Expand All @@ -38,22 +38,19 @@ set_property(TARGET hermesapi APPEND_STRING PROPERTY
set_property(TARGET hermesapi APPEND_STRING PROPERTY
COMPILE_DEFINITIONS "JSI_CREATE_SHARED_LIBRARY")

set(LLVM_LINK_COMPONENTS
Core
Support
)
set(HERMES_LINK_COMPONENTS LLVHSupport)

# Disable EH and RTTI for compileJS
set(LLVM_REQUIRES_EH OFF)
set(LLVM_REQUIRES_RTTI OFF)
set(HERMES_ENABLE_EH OFF)
set(HERMES_ENABLE_RTTI OFF)

add_llvm_library(compileJS STATIC CompileJS.cpp)
add_hermes_library(compileJS STATIC CompileJS.cpp)

# Restore EH and RTTI (Note: At the time of writing, there is no usage of
# add_llvm_library either after this line in this file or in a sub directory.
# add_hermes_library either after this line in this file or in a sub directory.
# However, the values are restored anyways for the sake of sanity.)
set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)
set(HERMES_ENABLE_EH ON)
set(HERMES_ENABLE_RTTI ON)

add_library(libhermes SHARED ${api_sources})
target_link_libraries(libhermes
Expand Down
2 changes: 1 addition & 1 deletion API/hermes/synthtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

# Dummy CMakeLists to avoid a test failure

add_llvm_library(synth_test
add_hermes_library(synth_test
Driver.cpp
)
175 changes: 77 additions & 98 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,53 @@ if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()

# find_package uses <PackageName>_ROOT variables.
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
# Include file check macros honor CMAKE_REQUIRED_LIBRARIES.
if (POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()

# Only interpret if() arguments as variables or keywords when unquoted.
# CMake emits a warning if this is not set.
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()

# Pick up a workaround for a CMake problem from LLVM r282552.
if(POLICY CMP0057)
cmake_policy(SET CMP0057 NEW)
endif()

# Enable transitive library dependencies
if(POLICY CMP0022)
cmake_policy(SET CMP0022 NEW)
endif()

# Don't complain about mixing plain and keyword target_link_libraries commands.
# Keyword style is when you specify whether library symbols are re-exported,
# e.g. target_link_libraries(target PRIVATE lib).
# LLVM currently uses plain-style target_link_libraries calls so we must
# allow mixing.
if (POLICY CMP0023)
cmake_policy(SET CMP0023 OLD)
endif()


# This must be consistent with the release_version in
# android/build.gradle and npm/package.json
project(Hermes
VERSION 0.4.0
LANGUAGES C CXX)

include(CheckCXXCompilerFlag)
include(CheckCXXSourceCompiles)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")

set(LLVH_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/llvh)

include(Hermes)
include(Lit)

set(HERMES_RELEASE_VERSION ${PROJECT_VERSION})

Expand Down Expand Up @@ -126,11 +160,7 @@ set(ANDROID_LINUX_PERF_PATH ""
set(HERMES_MSVC_MP ON CACHE STRING
"Enable /MP in MSVC for parallel builds")

# On Android we need an ABI specific version of LLVM.
# Unfortunately, the build system doesn't allow setting the
# LLVM_BUILD_DIR per ABI, so we do it here instead.
if (HERMES_IS_ANDROID)
set(LLVM_BUILD_DIR "${LLVM_BUILD_BASE}-${ANDROID_ABI}")
add_definitions(-DHERMES_PLATFORM_UNICODE=HERMES_PLATFORM_UNICODE_JAVA)

# The toolchain passes -Wa,--noexecstack which is valid for compiling
Expand All @@ -151,15 +181,6 @@ if (HERMES_IS_ANDROID)
endif()
endif()

# The hermes project is built using CMake and the LLVM's build system.
# It expects LLVM_SRC_DIR and LLVM_BUILD_DIR to be set. For example:
#
# cmake -G Ninja -DLLVM_BUILD_DIR=$XXX -DLLVM_SRC_DIR=$YYY
#
file(TO_CMAKE_PATH "${LLVM_BUILD_DIR}" LLVM_BUILD_DIR)
file(TO_CMAKE_PATH "${LLVM_SRC_DIR}" LLVM_SRC_DIR)
list(APPEND CMAKE_MODULE_PATH "${LLVM_BUILD_DIR}/lib/cmake/llvm/")

# Enable debug mode by default
if ((NOT GENERATOR_IS_MULTI_CONFIG) AND CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
Expand Down Expand Up @@ -256,49 +277,16 @@ if (NOT (ANDROID_LINUX_PERF_PATH STREQUAL ""))
add_definitions(-DANDROID_LINUX_PERF_PATH="${ANDROID_LINUX_PERF_PATH}")
endif()

# Build the hermes compiler by default.
set(LLVM_BUILD_TOOLS ON)
# Enable warnings.
set(LLVM_ENABLE_WARNINGS ON)

# Only interpret if() arguments as variables or keywords when unquoted.
# CMake emits a warning if this is not set.
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()

if (HERMES_ENABLE_WERROR)
# Turn all warnings into errors on some compilers:
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(LLVM_ENABLE_WERROR ON)
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(LLVM_ENABLE_WERROR ON)
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
# Warn.
# Turn all warnings into errors on GCC-compatible compilers.
if (GCC_COMPATIBLE)
append("-Werror" CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
endif()
endif()

# Collect all header files and add them to the IDE.
file(GLOB_RECURSE ALL_HEADER_FILES "*.h")

# Pick up a workaround for a CMake problem from LLVM r282552.
if(POLICY CMP0057)
cmake_policy(SET CMP0057 NEW)
endif()
# Enable transitive library dependencies
if(POLICY CMP0022)
cmake_policy(SET CMP0022 NEW)
endif()

# Don't complain about mixing plain and keyword target_link_libraries commands.
# Keyword style is when you specify whether library symbols are re-exported,
# e.g. target_link_libraries(target PRIVATE lib).
# LLVM currently uses plain-style target_link_libraries calls so we must
# allow mixing.
if (POLICY CMP0023)
cmake_policy(SET CMP0023 OLD)
endif()

if(HERMES_SLOW_DEBUG)
# Enable HERMES_SLOW_DEBUG in Debug mode
set_property(DIRECTORY APPEND PROPERTY
Expand All @@ -315,17 +303,13 @@ if (NOT (GENERATOR_IS_MULTI_CONFIG OR CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_C
# Enable LTO if we are not multi config generator and not a DEBUG build
# and not GCC
# GCC currently fails to link Hermes with LTO (see t16557748)
option(LLVM_ENABLE_LTO "Build Hermes with LTO" ON)
option(HERMES_ENABLE_LTO "Build Hermes with LTO" ON)
endif()

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR
"${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
# Supress warnings about unknown warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
# Suppress an uninteresting warning about C++17 name mangling changes.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-noexcept-type")
if (GCC_COMPATIBLE)
# Suppress uninteresting warnings about initializing ArrayRef from initializer lists.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-init-list-lifetime")
check_cxx_compiler_flag("-Winit-list-lifetime" INIT_LIST_LIFETIME_FLAG)
append_if(INIT_LIST_LIFETIME_FLAG "-Wno-init-list-lifetime" CMAKE_CXX_FLAGS)
# Don't export symbols unless we explicitly say so
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
Expand All @@ -335,6 +319,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4200")
# C4201 nonstandard extension used: nameless struct/union
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4201")
# C4530 C++ exception handler used, but unwind semantics are not enabled
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4530")
# Parallelize build
if (HERMES_MSVC_MP)
add_definitions( /MP )
Expand All @@ -345,17 +331,6 @@ endif()
# to analyze the source code of the project.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(LLVM_MAIN_SRC_DIR ${LLVM_SRC_DIR})
include(LLVMConfig)
include(AddLLVM)
include(HandleLLVMOptions)

include_directories("${LLVM_SRC_DIR}/include"
"${LLVM_BUILD_DIR}/include")

link_directories("${LLVM_SRC_DIR}/lib"
"${LLVM_BUILD_DIR}/${CMAKE_CFG_INTDIR}/lib")

# Attempt to use system ICU first, if none specified.
# Don't need ICU on Apple systems.
if (APPLE)
Expand All @@ -374,7 +349,7 @@ if (NOT ICU_FOUND)

# FindICU uses ICU_ROOT variable as a hint
# Include 'uc' twice for static libraries that depend on each other.
find_package(ICU 52 COMPONENTS uc i18n data uc)
find_global_package(ICU 52 COMPONENTS uc i18n data uc)

if (ICU_FOUND)
foreach(LIB_FILE ${ICU_LIBRARIES})
Expand Down Expand Up @@ -431,9 +406,9 @@ else()
set(CORE_FOUNDATION "")
endif()

if (CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT LLVM_BUILD_32_BITS)
if (CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT HERMES_BUILD_32_BITS)
set(LIBFLOWPARSER ${CMAKE_CURRENT_SOURCE_DIR}/external/flowparser/libflowparser-mac.a)
elseif (CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT LLVM_BUILD_32_BITS)
elseif (CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT HERMES_BUILD_32_BITS)
set(LIBFLOWPARSER ${CMAKE_CURRENT_SOURCE_DIR}/external/flowparser/libflowparser-linux.a)
else()
set(LIBFLOWPARSER "")
Expand All @@ -453,14 +428,6 @@ set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
set(HERMES_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(HERMES_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

# Tell LLVM where to place the compiled binaries.
#
# NOTE: LLVM also uses this variable to find its own binaries, which can create
# problems. For now the only LLVM tool we need is llvm-lit, so our short term
# solution is to just hack that special case (the long term solution would be
# to stop using add_llvm_tool() for our own tools).
set(LLVM_RUNTIME_OUTPUT_INTDIR ${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)

if(EXISTS ${HERMES_SOURCE_DIR}/API/jsi)
set(HERMES_JSI_DIR ${HERMES_SOURCE_DIR}/API/jsi)
elseif(EXISTS ${FBSOURCE_DIR}/xplat/jsi)
Expand All @@ -471,6 +438,12 @@ else()
message(FATAL_ERROR "Unable to find jsi.")
endif()

include_directories(
external/llvh/include
external/llvh/gen/include
${CMAKE_CURRENT_BINARY_DIR}/external/llvh/include
)

include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/include
Expand All @@ -485,7 +458,7 @@ if(HERMES_IS_ANDROID)
elseif(EXISTS ${FBSOURCE_DIR}/fbandroid/libraries/fbjni/cxx)
set(FBJNI_PATH ${FBSOURCE_DIR}/fbandroid/libraries/fbjni)
elseif(EXISTS ${HERMES_SOURCE_DIR}/../../fbandroid/libraries/fbjni/cxx)
set(FBJNI_PATH ${HERMES_SOURCE_DIR}/../../fbandroid/libraries/fbjni/cxx)
set(FBJNI_PATH ${HERMES_SOURCE_DIR}/../../fbandroid/libraries/fbjni)
else()
message(FATAL_ERROR "Unable to find fbjni.")
endif()
Expand All @@ -496,14 +469,25 @@ if(HERMES_IS_ANDROID)
set(OPTIONAL_JNI_ONLOAD "-Wl,--undefined=JNI_OnLoad")
endif()

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_subdirectory(external/llvh)
add_subdirectory(utils/hermes-lit)
add_subdirectory(tools)
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(external)
add_subdirectory(unittests)
add_subdirectory(${HERMES_JSI_DIR}/jsi ${CMAKE_CURRENT_BINARY_DIR}/jsi)
add_subdirectory(API)

# Make sure JSI is compiled with PIC
set(save_CMAKE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE})
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${HERMES_JSI_DIR}/jsi ${CMAKE_CURRENT_BINARY_DIR}/jsi)
set(CMAKE_POSITION_INDEPENDENT_CODE ${save_CMAKE_POSITION_INDEPENDENT_CODE})

if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/facebook)
add_subdirectory(facebook)
endif()
Expand All @@ -522,7 +506,6 @@ list(APPEND HERMES_TEST_DEPS
hbc-attribute
hbc-deltaprep
hbc-diff
llvm-config
)

set(HERMES_LIT_TEST_PARAMS
Expand All @@ -532,15 +515,15 @@ set(HERMES_LIT_TEST_PARAMS
use_flowparser=${HERMES_USE_FLOWPARSER}
jit_enabled=${HERMESVM_JIT}
jit_disassembler_enabled=${HERMESVM_JIT_DISASSEMBLER}
hbc_deltaprep=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hbc-deltaprep
FileCheck=${LLVM_BUILD_DIR}/${CMAKE_CFG_INTDIR}/bin/FileCheck
hermes=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hermes
hermesc=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hermesc
hdb=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hdb
hbcdump=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hbcdump
repl=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hermes-repl
hbc-deltaprep=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hbc-deltaprep
hbc_diff=${HERMES_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/hbc-diff
hbc_deltaprep=${HERMES_TOOLS_OUTPUT_DIR}/hbc-deltaprep
FileCheck=${HERMES_TOOLS_OUTPUT_DIR}//FileCheck
hermes=${HERMES_TOOLS_OUTPUT_DIR}/hermes
hermesc=${HERMES_TOOLS_OUTPUT_DIR}/hermesc
hdb=${HERMES_TOOLS_OUTPUT_DIR}/hdb
hbcdump=${HERMES_TOOLS_OUTPUT_DIR}/hbcdump
repl=${HERMES_TOOLS_OUTPUT_DIR}/hermes-repl
hbc-deltaprep=${HERMES_TOOLS_OUTPUT_DIR}/hbc-deltaprep
hbc_diff=${HERMES_TOOLS_OUTPUT_DIR}/hbc-diff
build_mode=${HERMES_ASSUMED_BUILD_MODE_IN_LIT_TEST}
exception_on_oom_enabled=${HERMESVM_EXCEPTION_ON_OOM}
serialize_enabled=${HERMESVM_SERIALIZE}
Expand All @@ -551,11 +534,7 @@ set(HERMES_LIT_TEST_PARAMS
ubsan=OFF
)

set(LLVM_LIT_ARGS "-sv")

# This is a hack to help LLVM find its own llvm-lit tool, since we had to set
# LLVM_RUNTIME_OUTPUT_INTDIR to our own build dir.
set(LLVM_LIT_OUTPUT_DIR ${LLVM_BUILD_DIR}/${CMAKE_CFG_INTDIR}/bin)
set(LLVH_LIT_ARGS "-sv")

add_lit_testsuite(check-hermes "Running the Hermes regression tests"
${HERMES_SOURCE_DIR}/test
Expand Down
Loading

0 comments on commit 611cac5

Please sign in to comment.