1 option(BUILD_HACK "True if we should build the Hack typechecker." ON)
3 include(CMakeParseArguments)
6 message(STATUS "Skipping hack")
10 message(STATUS "Building hack")
15 # native_libraries: values for `-l` flags
16 # lib_paths: values for `-L` flags (directories)
17 # extra_link_opts: opaque options passed to the linker
19 # We need extra_link_opts for:
21 # - anything built from third-party: cmake gives us the link flags
22 unset(extra_include_paths)
23 unset(extra_native_libraries)
24 unset(extra_lib_paths)
25 unset(extra_link_opts)
28 # Allows '#include "hphp/path/to/library/"' paths to start from hphp
29 # project directory which is consistent with fbmake's include paths.
30 list(APPEND extra_include_paths ${HPHP_HOME})
31 list(APPEND extra_cc_flags -pthread)
33 # Xcode/Ninja generators undefined MAKE
38 if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
39 set(DUNE_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/_build")
40 set(OPAM_STAMP_FILE "_build/opam.stamp")
41 set(RUST_FFI_BUILD_ROOT "${DUNE_BUILD_DIR}/rust_ffi")
42 set(CARGO_HOME "${DUNE_BUILD_DIR}/cargo_home")
44 set(DUNE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}")
45 set(RUST_FFI_BUILD_ROOT "${CMAKE_BINARY_DIR}")
46 set(CARGO_HOME "${CMAKE_CURRENT_BINARY_DIR}/cargo_home")
47 set(OPAM_STAMP_FILE "opam.stamp")
49 set(HACK_BUILD_ROOT "${DUNE_BUILD_DIR}/default")
51 get_target_property(OPAM_EXECUTABLE opam IMPORTED_LOCATION)
54 OUTPUT "${OPAM_STAMP_FILE}"
55 DEPENDS opam opam_setup.sh
57 ${CMAKE_CURRENT_SOURCE_DIR}/opam_setup.sh
60 && cmake -E touch "${OPAM_STAMP_FILE}"
62 add_custom_target(opam_setup DEPENDS "${OPAM_STAMP_FILE}" opam_setup.sh)
65 set(OPAMROOT "~/.opam")
67 set(OPAMROOT "${DUNE_BUILD_DIR}/opam")
71 list(APPEND extra_include_paths ${LZ4_INCLUDE_DIR})
72 get_filename_component(pth ${LZ4_LIBRARY} DIRECTORY)
73 list(APPEND extra_lib_paths ${pth})
74 list(APPEND extra_native_libraries "lz4")
76 get_target_property(LZ4_INCLUDE_DIRS lz4 INTERFACE_INCLUDE_DIRECTORIES)
77 list(APPEND extra_include_paths ${LZ4_INCLUDE_DIRS})
78 # If LZ4_FOUND is false either we didn't find lz4 or we found it but it's the
79 # wrong version. We can't just add the new path and a native_lib because we
80 # can't control the order (and -l won't accept the raw path to the lib). By
81 # doing it this way we specify the path explicitly.
82 get_target_property(LZ4_LIBS lz4 INTERFACE_LINK_LIBRARIES)
83 list(APPEND extra_link_opts ${LZ4_LIBS})
86 get_target_property(ZSTD_INCLUDE_DIRS zstd INTERFACE_INCLUDE_DIRECTORIES)
87 list(APPEND extra_include_paths ${ZSTD_INCLUDE_DIRS})
88 get_target_property(ZSTD_LIBS zstd INTERFACE_LINK_LIBRARIES)
89 list(APPEND extra_link_opts ${ZSTD_LIBS})
91 list(APPEND extra_include_paths ${LIBSQLITE3_INCLUDE_DIR})
92 get_filename_component(pth ${LIBSQLITE3_LIBRARY} DIRECTORY)
93 list(APPEND extra_lib_paths ${pth})
94 list(APPEND extra_native_libraries "sqlite3")
96 get_target_property(RUSTC_EXE rustc LOCATION)
97 get_target_property(CARGO_EXE cargo LOCATION)
98 get_filename_component(RUSTC_BIN_DIR "${RUSTC_EXE}" DIRECTORY)
99 get_filename_component(CARGO_BIN_DIR "${CARGO_EXE}" DIRECTORY)
101 function(invoke_dune name target)
105 . "${CMAKE_CURRENT_BINARY_DIR}/dev_env.sh" &&
107 $(MAKE) --makefile=Makefile.dune ${target}
108 BYTECODE="${EMIT_OCAML_BYTECODE}"
109 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
112 add_dependencies(${name} rustc cargo zstd)
114 add_dependencies(${name} opam_setup)
118 invoke_dune(hack_dune_debug debug)
119 invoke_dune(hack_dune_test test)
120 invoke_dune(hack_dune all)
122 set(INVOKE_CARGO "${CMAKE_SOURCE_DIR}/hphp/hack/scripts/invoke_cargo.sh")
124 if(DEFINED ENV{HACKDEBUG})
127 set(PROFILE "release")
130 set(RUST_OPCODES_DIR "${CMAKE_BINARY_DIR}/hphp/hack/src/hackc")
131 set(RUST_OPCODES "${RUST_OPCODES_DIR}/opcodes.rs")
133 set(HHBC_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc")
135 "${HHBC_PREFIX}/hhbc/adata.rs"
136 "${HHBC_PREFIX}/hhbc/attribute.rs"
137 "${HHBC_PREFIX}/hhbc/body.rs"
138 "${HHBC_PREFIX}/hhbc/class.rs"
139 "${HHBC_PREFIX}/hhbc/coeffects.rs"
140 "${HHBC_PREFIX}/hhbc/constant.rs"
141 "${HHBC_PREFIX}/hhbc/function.rs"
142 "${HHBC_PREFIX}/hhbc/id.rs"
143 "${HHBC_PREFIX}/hhbc/instruct.rs"
144 "${HHBC_PREFIX}/hhbc/method.rs"
145 "${HHBC_PREFIX}/hhbc/module.rs"
146 "${HHBC_PREFIX}/hhbc/param.rs"
147 "${HHBC_PREFIX}/hhbc/pos.rs"
148 "${HHBC_PREFIX}/hhbc/property.rs"
149 "${HHBC_PREFIX}/hhbc/symbol_refs.rs"
150 "${HHBC_PREFIX}/hhbc/types.rs"
151 "${HHBC_PREFIX}/hhbc/type_const.rs"
152 "${HHBC_PREFIX}/hhbc/typedef.rs"
153 "${HHBC_PREFIX}/hhbc/typed_value.rs"
154 "${HHBC_PREFIX}/hhbc/unit.rs"
155 "${HHBC_PREFIX}/hhbc/unit_cbindgen.rs" # Not in a crate.
159 set(NAMING_SPECIAL_NAMES_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/src/naming")
160 set(NAMING_SPECIAL_NAMES_SRCS
161 "${NAMING_SPECIAL_NAMES_PREFIX}/naming_special_names.rs"
162 "${NAMING_SPECIAL_NAMES_PREFIX}/naming_special_names_ffi_cbindgen.rs"
165 set(FFI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ffi")
167 "${FFI_PREFIX}/ffi.rs"
168 "${FFI_PREFIX}/ffi_ffi_cbindgen.rs"
172 OUTPUT ${RUST_OPCODES}
174 ${CMAKE_COMMAND} -E make_directory "${RUST_OPCODES_DIR}" &&
175 . "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" &&
176 ${INVOKE_CARGO} dump-opcodes dump-opcodes --exe &&
177 ${INVOKE_CARGO} dump-opcodes dump-opcodes --bin dump_opcodes
179 COMMENT "Generating Rust opcode struct for cbindgen to use to generate hhbc-ast.h"
180 DEPENDS "${OPCODE_DATA}"
183 set(HHBC_AST_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/hackc/hhbc-ast.h")
184 set(FFI_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/utils/ffi.h")
185 set(NAMING_SPECIAL_NAMES_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/naming/naming-special-names.h")
186 set(TYPE_CONSTRAINT_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/type-constraint-flags.h")
187 set(FCALL_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/fcall-args-flags.h")
188 set(HHBC_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/hhbc-shared.h")
189 set(ATTR_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/base/attr.h")
190 set(FFI_EXTRA_HEADER "${CMAKE_SOURCE_DIR}/hphp/hack/src/utils/ffi/ffi_extra.h")
193 OUTPUT ${HHBC_AST_HEADER}
195 . "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" &&
196 ${INVOKE_CARGO} ffi_cbindgen ffi_cbindgen --exe &&
197 ${INVOKE_CARGO} ffi_cbindgen ffi_cbindgen --bin ffi_cbindgen
198 --header "${FFI_HEADER}" --namespaces "HPHP,hackc"
199 --includes "${FFI_EXTRA_HEADER}"
201 ${INVOKE_CARGO} ffi_cbindgen ffi_cbindgen --bin ffi_cbindgen
202 --header "${NAMING_SPECIAL_NAMES_HEADER}" --namespaces "HPHP,hackc,hhbc"
203 ${NAMING_SPECIAL_NAMES_SRCS} &&
204 ${INVOKE_CARGO} ffi_cbindgen ffi_cbindgen --bin ffi_cbindgen
205 --header "${HHBC_AST_HEADER}" --namespaces "HPHP,hackc,hhbc"
206 --includes "${FFI_HEADER},${NAMING_SPECIAL_NAMES_HEADER},${TYPE_CONSTRAINT_HEADER},${ATTR_HEADER},${FCALL_HEADER},${HHBC_HEADER}"
208 DEPENDS rustc cargo "${RUST_OPCODES}"
209 COMMENT "Generating hhbc-ast.h"
214 DEPENDS ${HHBC_AST_HEADER}
217 add_library("hhbc_ast_header" INTERFACE)
218 add_dependencies("hhbc_ast_header" "hhbc_ast_cbindgen")
220 add_custom_target(hack_rust_ffi_bridge_targets)
222 # Compiling cxx entrypoints for hhvm
228 # [EXTRA_SRCS src [src ...]]
229 # [LINK_LIBS lib [lib ...]]
233 # `name` is the target name of the cxx_bridge.
234 # `directory` is the required directory of the cxx_bridge sources.
235 # `src` are extra source files to include in the bridge.
236 # `lib` are extra link libraries to include in the bridge.
238 function(build_cxx_bridge NAME)
239 cmake_parse_arguments(CXX_BRIDGE "" "DIR" "EXTRA_SRCS;LINK_LIBS" ${ARGN})
241 if ("${CXX_BRIDGE_DIR}" STREQUAL "")
242 message(FATAL_ERROR "Missing DIR parameter")
244 if (NOT "${CXX_BRIDGE_UNPARSED_ARGUMENTS}" STREQUAL "")
245 message(FATAL_ERROR "Unexpected parameters: ${CXX_BRIDGE_UNPARSED_ARGUMENTS}")
248 set(FFI_BRIDGE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${CXX_BRIDGE_DIR}")
249 set(FFI_BRIDGE_BIN "${RUST_FFI_BUILD_ROOT}/hphp/hack/${CXX_BRIDGE_DIR}")
251 set(RUST_PART_LIB "${FFI_BRIDGE_BIN}/${PROFILE}/${CMAKE_STATIC_LIBRARY_PREFIX}${NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
252 set(RUST_PART_CXX "${FFI_BRIDGE_BIN}/${NAME}.cpp")
253 set(RUST_PART_HEADER "${FFI_BRIDGE_BIN}/${NAME}.rs.h")
254 set(GENERATED "${FFI_BRIDGE_BIN}/cxxbridge/${NAME}/${NAME}")
255 set(GENERATED_CXXBRIDGE "${FFI_BRIDGE_BIN}/cxxbridge")
262 ${GENERATED_CXXBRIDGE}
264 ${CMAKE_COMMAND} -E make_directory "${FFI_BRIDGE_BIN}" &&
265 . "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" &&
266 ${INVOKE_CARGO} "${NAME}" "${NAME}" --target-dir "${FFI_BRIDGE_BIN}" &&
267 ${CMAKE_COMMAND} -E copy "${GENERATED}.rs.cc" "${RUST_PART_CXX}" &&
268 ${CMAKE_COMMAND} -E copy "${GENERATED}.rs.h" "${RUST_PART_HEADER}"
269 WORKING_DIRECTORY ${FFI_BRIDGE_SRC}
270 DEPENDS rustc cargo "${OPCODE_DATA}"
274 DEPENDS ${RUST_PART_LIB}
276 add_library("${NAME}" STATIC ${RUST_PART_CXX} ${CXX_BRIDGE_EXTRA_SRCS} )
277 add_dependencies(hack_rust_ffi_bridge_targets "${NAME}")
278 add_library("${NAME}_rust_part" STATIC IMPORTED)
279 add_dependencies("${NAME}_rust_part" "${NAME}_cxx")
281 # Intentionally create link-time cyclic dependency between ${NAME}_rust_part
282 # and ${NAME} so that CMake will automatically construct the link line so
283 # that the linker will scan through involved static libraries multiple times.
284 set_target_properties(
287 IMPORTED_LOCATION ${RUST_PART_LIB}
288 IMPORTED_LINK_DEPENDENT_LIBRARIES "${NAME}"
290 target_link_libraries(
294 ${CXX_BRIDGE_LINK_LIBS}
296 target_include_directories("${NAME}" INTERFACE "${RUST_FFI_BUILD_ROOT}")
297 target_include_directories("${NAME}" PRIVATE "${GENERATED_CXXBRIDGE}")
302 DIR "src/parser/ffi_bridge"
306 DIR "src/hackc/ffi_bridge"
307 EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/ffi_bridge/external_decl_provider.cpp"
313 EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/utils/hdf/hdf-wrap.cpp"
318 DIR "src/hackc/hhvm_cxx/hhvm_types"
319 EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_types/as-base-ffi.cpp"
323 DIR "src/hackc/hhvm_cxx/hhvm_hhbc_defs"
324 EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_hhbc_defs/as-hhbc-ffi.cpp"
328 add_dependencies(hack_dune lz4)
329 add_dependencies(hack_dune_debug lz4)
330 add_dependencies(hack_dune_test lz4)
333 # Intentionally not using `hack_dune_debug` as it generates output files of a
334 # different format (bytecode instead of raw executables, which is useful if
335 # you're working with Hack. Keep it around, but require it to be explicitly used
336 add_custom_target(hack ALL DEPENDS hack_dune "${OPCODE_DATA}")
337 add_custom_target(hack_test DEPENDS hack_dune_test "${OPCODE_DATA}")
339 configure_file(dev_env.sh.in dev_env.sh ESCAPE_QUOTES @ONLY)
340 configure_file(dev_env_common.sh.in dev_env_common.sh ESCAPE_QUOTES @ONLY)
341 configure_file(dev_env_rust_only.sh.in dev_env_rust_only.sh ESCAPE_QUOTES @ONLY)
343 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hh_client
347 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hh_server
351 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hackfmt
355 install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hh_parse