include(libjs_generators) set(SOURCES Bytecode/AsmInterpreter/AsmInterpreter.cpp Bytecode/BasicBlock.cpp Bytecode/Executable.cpp Bytecode/IdentifierTable.cpp Bytecode/Instruction.cpp Bytecode/Interpreter.cpp Bytecode/Label.cpp Bytecode/PropertyNameIterator.cpp Bytecode/PropertyKeyTable.cpp Bytecode/RegexTable.cpp Bytecode/StringTable.cpp Bytecode/Validator.cpp Console.cpp Contrib/Test262/262Object.cpp Contrib/Test262/AgentObject.cpp Contrib/Test262/GlobalObject.cpp Contrib/Test262/IsHTMLDDA.cpp CyclicModule.cpp Heap/Cell.cpp Module.cpp ParserError.cpp Print.cpp RustIntegration.cpp Runtime/AbstractOperations.cpp Runtime/Accessor.cpp Runtime/Agent.cpp Runtime/AggregateError.cpp Runtime/AggregateErrorConstructor.cpp Runtime/AggregateErrorPrototype.cpp Runtime/ArgumentsObject.cpp Runtime/Array.cpp Runtime/ArrayBuffer.cpp Runtime/ArrayBufferConstructor.cpp Runtime/ArrayBufferPrototype.cpp Runtime/ArrayConstructor.cpp Runtime/ArrayIterator.cpp Runtime/ArrayIteratorPrototype.cpp Runtime/ArrayPrototype.cpp Runtime/AsyncDisposableStack.cpp Runtime/AsyncDisposableStackConstructor.cpp Runtime/AsyncDisposableStackPrototype.cpp Runtime/AsyncFromSyncIterator.cpp Runtime/AsyncFromSyncIteratorPrototype.cpp Runtime/AsyncFunctionConstructor.cpp Runtime/AsyncFunctionDriverWrapper.cpp Runtime/AsyncFunctionPrototype.cpp Runtime/AsyncGenerator.cpp Runtime/AsyncGeneratorFunctionConstructor.cpp Runtime/AsyncGeneratorFunctionPrototype.cpp Runtime/AsyncGeneratorPrototype.cpp Runtime/AsyncIteratorPrototype.cpp Runtime/AtomicsObject.cpp Runtime/BigInt.cpp Runtime/BigIntConstructor.cpp Runtime/BigIntObject.cpp Runtime/BigIntPrototype.cpp Runtime/BooleanConstructor.cpp Runtime/BooleanObject.cpp Runtime/BooleanPrototype.cpp Runtime/BoundFunction.cpp Runtime/ClassConstruction.cpp Runtime/ClassFieldDefinition.cpp Runtime/Completion.cpp Runtime/ConsoleObjectPrototype.cpp Runtime/ConsoleObject.cpp Runtime/DataView.cpp Runtime/DataViewConstructor.cpp Runtime/DataViewPrototype.cpp Runtime/DescriptorArray.cpp Runtime/Date.cpp Runtime/DateConstructor.cpp Runtime/DatePrototype.cpp Runtime/DeclarativeEnvironment.cpp Runtime/DisposableStack.cpp Runtime/DisposableStackConstructor.cpp Runtime/DisposableStackPrototype.cpp Runtime/ECMAScriptFunctionObject.cpp Runtime/Environment.cpp Runtime/Error.cpp Runtime/ErrorConstructor.cpp Runtime/ErrorData.cpp Runtime/ErrorPrototype.cpp Runtime/ErrorTypes.cpp Runtime/ExecutionContext.cpp Runtime/InterpreterStack.cpp Runtime/FinalizationRegistry.cpp Runtime/FinalizationRegistryConstructor.cpp Runtime/FinalizationRegistryPrototype.cpp Runtime/FunctionConstructor.cpp Runtime/FunctionEnvironment.cpp Runtime/FunctionObject.cpp Runtime/FunctionPrototype.cpp Runtime/GeneratorFunctionConstructor.cpp Runtime/GeneratorFunctionPrototype.cpp Runtime/GeneratorObject.cpp Runtime/GeneratorPrototype.cpp Runtime/GlobalEnvironment.cpp Runtime/GlobalObject.cpp Runtime/IndexedProperties.cpp Runtime/Intl/AbstractOperations.cpp Runtime/Intl/Collator.cpp Runtime/Intl/CollatorCompareFunction.cpp Runtime/Intl/CollatorConstructor.cpp Runtime/Intl/CollatorPrototype.cpp Runtime/Intl/DateTimeFormat.cpp Runtime/Intl/DateTimeFormatConstructor.cpp Runtime/Intl/DateTimeFormatFunction.cpp Runtime/Intl/DateTimeFormatPrototype.cpp Runtime/Intl/DisplayNames.cpp Runtime/Intl/DisplayNamesConstructor.cpp Runtime/Intl/DisplayNamesPrototype.cpp Runtime/Intl/DurationFormat.cpp Runtime/Intl/DurationFormatConstructor.cpp Runtime/Intl/DurationFormatPrototype.cpp Runtime/Intl/Intl.cpp Runtime/Intl/ListFormat.cpp Runtime/Intl/ListFormatConstructor.cpp Runtime/Intl/ListFormatPrototype.cpp Runtime/Intl/Locale.cpp Runtime/Intl/LocaleConstructor.cpp Runtime/Intl/LocalePrototype.cpp Runtime/Intl/MathematicalValue.cpp Runtime/Intl/NumberFormat.cpp Runtime/Intl/NumberFormatConstructor.cpp Runtime/Intl/NumberFormatFunction.cpp Runtime/Intl/NumberFormatPrototype.cpp Runtime/Intl/PluralRules.cpp Runtime/Intl/PluralRulesConstructor.cpp Runtime/Intl/PluralRulesPrototype.cpp Runtime/Intl/RelativeTimeFormat.cpp Runtime/Intl/RelativeTimeFormatConstructor.cpp Runtime/Intl/RelativeTimeFormatPrototype.cpp Runtime/Intl/Segmenter.cpp Runtime/Intl/SegmenterConstructor.cpp Runtime/Intl/SegmenterPrototype.cpp Runtime/Intl/Segments.cpp Runtime/Intl/SegmentIterator.cpp Runtime/Intl/SegmentIteratorPrototype.cpp Runtime/Intl/SegmentsPrototype.cpp Runtime/Intrinsics.cpp Runtime/Iterator.cpp Runtime/IteratorConstructor.cpp Runtime/IteratorHelper.cpp Runtime/IteratorHelperPrototype.cpp Runtime/IteratorPrototype.cpp Runtime/JSONObject.cpp Runtime/JobCallback.cpp Runtime/KeyedCollections.cpp Runtime/Map.cpp Runtime/MapConstructor.cpp Runtime/MapIterator.cpp Runtime/MapIteratorPrototype.cpp Runtime/MapPrototype.cpp Runtime/MathObject.cpp Runtime/ModuleEnvironment.cpp Runtime/ModuleNamespaceObject.cpp Runtime/NativeFunction.cpp Runtime/NativeJavaScriptBackedFunction.cpp Runtime/NumberConstructor.cpp Runtime/NumberObject.cpp Runtime/NumberPrototype.cpp Runtime/Object.cpp Runtime/ObjectConstructor.cpp Runtime/ObjectEnvironment.cpp Runtime/ObjectPrototype.cpp Runtime/PrimitiveString.cpp Runtime/PrivateEnvironment.cpp Runtime/Promise.cpp Runtime/PromiseCapability.cpp Runtime/PromiseConstructor.cpp Runtime/PromiseJobs.cpp Runtime/PromisePrototype.cpp Runtime/PromiseReaction.cpp Runtime/PromiseResolvingElementFunctions.cpp Runtime/PromiseResolvingFunction.cpp Runtime/PropertyDescriptor.cpp Runtime/ProxyConstructor.cpp Runtime/ProxyObject.cpp Runtime/RawJSONObject.cpp Runtime/Realm.cpp Runtime/Reference.cpp Runtime/ReflectObject.cpp Runtime/RegExpConstructor.cpp Runtime/RegExpLegacyStaticProperties.cpp Runtime/RegExpObject.cpp Runtime/RegExpPrototype.cpp Runtime/RegExpStringIterator.cpp Runtime/RegExpStringIteratorPrototype.cpp Runtime/Set.cpp Runtime/SetConstructor.cpp Runtime/SetIterator.cpp Runtime/SetIteratorPrototype.cpp Runtime/SetPrototype.cpp Runtime/Shape.cpp Runtime/SharedArrayBufferConstructor.cpp Runtime/SharedArrayBufferPrototype.cpp Runtime/SharedFunctionInstanceData.cpp Runtime/StringConstructor.cpp Runtime/StringIterator.cpp Runtime/StringIteratorPrototype.cpp Runtime/StringObject.cpp Runtime/StringPrototype.cpp Runtime/SuppressedError.cpp Runtime/SuppressedErrorConstructor.cpp Runtime/SuppressedErrorPrototype.cpp Runtime/Symbol.cpp Runtime/SymbolConstructor.cpp Runtime/SymbolObject.cpp Runtime/SymbolPrototype.cpp Runtime/Temporal/AbstractOperations.cpp Runtime/Temporal/Calendar.cpp Runtime/Temporal/DateEquations.cpp Runtime/Temporal/Duration.cpp Runtime/Temporal/DurationConstructor.cpp Runtime/Temporal/DurationPrototype.cpp Runtime/Temporal/Instant.cpp Runtime/Temporal/InstantConstructor.cpp Runtime/Temporal/InstantPrototype.cpp Runtime/Temporal/ISO8601.cpp Runtime/Temporal/Now.cpp Runtime/Temporal/PlainDate.cpp Runtime/Temporal/PlainDateConstructor.cpp Runtime/Temporal/PlainDatePrototype.cpp Runtime/Temporal/PlainDateTime.cpp Runtime/Temporal/PlainDateTimeConstructor.cpp Runtime/Temporal/PlainDateTimePrototype.cpp Runtime/Temporal/PlainMonthDay.cpp Runtime/Temporal/PlainMonthDayConstructor.cpp Runtime/Temporal/PlainMonthDayPrototype.cpp Runtime/Temporal/PlainTime.cpp Runtime/Temporal/PlainTimeConstructor.cpp Runtime/Temporal/PlainTimePrototype.cpp Runtime/Temporal/PlainYearMonth.cpp Runtime/Temporal/PlainYearMonthConstructor.cpp Runtime/Temporal/PlainYearMonthPrototype.cpp Runtime/Temporal/Temporal.cpp Runtime/Temporal/TimeZone.cpp Runtime/Temporal/ZonedDateTime.cpp Runtime/Temporal/ZonedDateTimeConstructor.cpp Runtime/Temporal/ZonedDateTimePrototype.cpp Runtime/TypedArray.cpp Runtime/TypedArrayConstructor.cpp Runtime/TypedArrayPrototype.cpp Runtime/Uint8Array.cpp Runtime/Value.cpp Runtime/VM.cpp Runtime/WeakMap.cpp Runtime/WeakMapConstructor.cpp Runtime/WeakMapPrototype.cpp Runtime/WeakRef.cpp Runtime/WeakRefConstructor.cpp Runtime/WeakRefPrototype.cpp Runtime/WeakSet.cpp Runtime/WeakSetConstructor.cpp Runtime/WeakSetPrototype.cpp Runtime/WrapForValidIteratorPrototype.cpp Script.cpp SourceCode.cpp SourceTextModule.cpp SyntaxHighlighter.cpp SyntheticModule.cpp ) generate_bytecode_def_derived() set(GENERATED_SOURCES Bytecode/Op.cpp) ladybird_lib(LibJS js EXPLICIT_SYMBOL_EXPORT) target_link_libraries(LibJS PRIVATE LibCore LibCrypto LibFileSystem LibRegex LibSyntax LibGC simdjson::simdjson) # Link LibUnicode publicly to ensure ICU data (which is in libicudata.a) is available in any process using LibJS. target_link_libraries(LibJS PUBLIC LibUnicode) # TODO: This is probably also needed on RISC-V. if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i.86.*") target_link_libraries(LibJS PRIVATE atomic) endif() if (WIN32) # FIXME: Windows on ARM target_link_libraries(LibJS PRIVATE clang_rt.builtins-x86_64.lib kernel32 ntdll Ws2_32 userenv) else() # This flag has no effect on Windows target_compile_options(LibJS PRIVATE -fno-omit-frame-pointer) endif() target_link_libraries(LibJS PUBLIC JSClangPlugin) import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libjs_rust FFI_HEADER RustFFI.h) target_link_libraries(LibJS PRIVATE libjs_rust) if ((LINUX OR BSD) AND NOT BUILD_SHARED_LIBS) # Rust staticlibs each carry the same allocator shim symbols. LibJS can # pull in multiple crates' copies in static ELF links, but they all # forward to the same ladybird_rust_* entry points in AK/kmalloc.cpp. target_link_options(LibJS INTERFACE LINKER:--allow-multiple-definition) endif() # The Rust library and LibJS have a circular dependency (C++ calls Rust # entry points, Rust calls C++ callbacks). For static builds, merge the # Rust archive into the LibJS archive so all symbols are in one place. if(NOT BUILD_SHARED_LIBS) add_custom_command(TARGET LibJS POST_BUILD COMMAND ${CMAKE_AR} -x $ COMMAND ${CMAKE_AR} -qS $ *.o COMMAND ${CMAKE_RANLIB} $ COMMAND ${CMAKE_COMMAND} -E remove -f *.o WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/rust_merge_tmp COMMENT "Merging Rust archive into LibJS" ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/rust_merge_tmp) # POST_BUILD steps don't track inputs, so when libjs_rust.a changes ninja # leaves liblagom-js.a alone and the merged archive ends up with stale # Rust objects. Force the C++ FFI bridge file to depend on the Rust # archive: when it changes, RustIntegration.cpp recompiles, LibJS gets # re-archived, and POST_BUILD re-merges the fresh Rust objects. get_target_property(_libjs_rust_lib libjs_rust IMPORTED_LOCATION) set_property(SOURCE RustIntegration.cpp APPEND PROPERTY OBJECT_DEPENDS ${_libjs_rust_lib}) endif() # AsmInterpreter: generate platform-specific assembly from DSL # NB: Win64 uses a different ABI (shadow space, different arg registers) # from SysV AMD64, and the x86_64 backend only supports SysV for now. if (NOT WIN32 AND ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(x86_64|amd64|AMD64)$")) set(ASMINT_ARCH "x86_64") elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64|arm64)$") set(ASMINT_ARCH "aarch64") endif() if (DEFINED ASMINT_ARCH) enable_language(ASM) set(ASMINTGEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/AsmIntGen") set(ASMINTGEN_BIN "${ASMINTGEN_DIR}/target/release/asmintgen") set(ASMINT_DSL "${CMAKE_CURRENT_SOURCE_DIR}/Bytecode/AsmInterpreter/asmint.asm") set(ASMINT_GENERATED_S "${CMAKE_CURRENT_BINARY_DIR}/Bytecode/AsmInterpreter/asmint_${ASMINT_ARCH}.S") set(ASM_OFFSETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/Bytecode/AsmInterpreter/asm_offsets.conf") # Build-time offset generator: compiles a small C++ program that uses # offsetof() to emit struct field offsets as DSL constants. add_executable(gen_asm_offsets "${CMAKE_CURRENT_SOURCE_DIR}/Bytecode/AsmInterpreter/gen_asm_offsets.cpp") target_link_libraries(gen_asm_offsets PRIVATE AK) target_compile_definitions(gen_asm_offsets PRIVATE private=public protected=public) # NB: Strip fuzzer sanitizer flags so gen_asm_offsets can define its own main(). if (ENABLE_FUZZERS_LIBFUZZER) target_compile_options(gen_asm_offsets PRIVATE -fno-sanitize=fuzzer) target_link_options(gen_asm_offsets PRIVATE -fno-sanitize=fuzzer) endif() # NB: gen_asm_offsets no longer depends on Op.h since opcode field # offsets are now computed from Bytecode.def by asmintgen directly. add_custom_command( OUTPUT "${ASM_OFFSETS_FILE}" COMMAND "$" > "${ASM_OFFSETS_FILE}" DEPENDS gen_asm_offsets COMMENT "Generating asm struct offsets" ) file(GLOB ASMINTGEN_RUST_SOURCES CONFIGURE_DEPENDS "${ASMINTGEN_DIR}/src/*.rs") file(GLOB ASMINTGEN_BYTECODE_DEF_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/BytecodeDef/src/*.rs") set(ASMINTGEN_SOURCES "${ASMINTGEN_DIR}/Cargo.toml" "${ASMINTGEN_DIR}/Cargo.lock" "${CMAKE_CURRENT_SOURCE_DIR}/BytecodeDef/Cargo.toml" ${ASMINTGEN_RUST_SOURCES} ${ASMINTGEN_BYTECODE_DEF_SOURCES} ) # NB: Clear linker-related env vars so cargo uses the default host # linker. The CI may set CC/CXX or CARGO_TARGET_*_LINKER to a # compiler that isn't available in all build configurations (e.g. # clang-21 in GNU builds). asmintgen is a pure Rust host tool. add_custom_command( OUTPUT "${ASMINTGEN_BIN}" COMMAND ${CMAKE_COMMAND} -E env --unset=CC --unset=CXX --unset=CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER --unset=CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER cargo build --release WORKING_DIRECTORY "${ASMINTGEN_DIR}" DEPENDS ${ASMINTGEN_SOURCES} COMMENT "Building asmintgen" ) set(BYTECODE_DEF "${CMAKE_CURRENT_SOURCE_DIR}/Bytecode/Bytecode.def") if (APPLE) set(ASMINT_OBJ_FORMAT "macho") else() set(ASMINT_OBJ_FORMAT "elf") endif() set(ASMINT_EXTRA_FLAGS "") if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR ENABLE_ADDRESS_SANITIZER OR ENABLE_MEMORY_SANITIZER OR ENABLE_UNDEFINED_SANITIZER) list(APPEND ASMINT_EXTRA_FLAGS "--enable-assertions") endif() # All Apple Silicon chips are ARMv8.5+ which includes FEAT_JSCVT. if ("${ASMINT_ARCH}" STREQUAL "aarch64" AND APPLE) list(APPEND ASMINT_EXTRA_FLAGS "--has-jscvt") endif() add_custom_command( OUTPUT "${ASMINT_GENERATED_S}" COMMAND "${ASMINTGEN_BIN}" --arch ${ASMINT_ARCH} --object-format ${ASMINT_OBJ_FORMAT} --constants "${ASM_OFFSETS_FILE}" --bytecode-def "${BYTECODE_DEF}" --input "${ASMINT_DSL}" --output "${ASMINT_GENERATED_S}" ${ASMINT_EXTRA_FLAGS} DEPENDS "${ASMINTGEN_BIN}" "${ASMINT_DSL}" "${ASM_OFFSETS_FILE}" "${BYTECODE_DEF}" COMMENT "Generating asmint_${ASMINT_ARCH}.S from DSL" ) target_sources(LibJS PRIVATE "${ASMINT_GENERATED_S}") endif()