diff options
Diffstat (limited to 'toolkit/library')
23 files changed, 1667 insertions, 0 deletions
diff --git a/toolkit/library/build/Makefile.in b/toolkit/library/build/Makefile.in new file mode 100644 index 0000000000..474c42518c --- /dev/null +++ b/toolkit/library/build/Makefile.in @@ -0,0 +1,20 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + +DUMP_SYMBOLS_FLAGS = --count-ctors + +ifdef CLANG_CL +ifdef MOZ_PROFILE_USE +ifeq (x86,$(CPU_ARCH)) +PGO_LDFLAGS += -ORDER:@$(topsrcdir)/build/win32/orderfile.txt +endif +ifeq (x86_64,$(CPU_ARCH)) +PGO_LDFLAGS += -ORDER:@$(topsrcdir)/build/win64/orderfile.txt +endif +endif +endif diff --git a/toolkit/library/build/dependentlibs.py b/toolkit/library/build/dependentlibs.py new file mode 100644 index 0000000000..d7559844d4 --- /dev/null +++ b/toolkit/library/build/dependentlibs.py @@ -0,0 +1,153 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +"""Given a library, dependentlibs.py prints the list of libraries it depends +upon that are in the same directory, followed by the library itself. +""" + +import os +import re +import subprocess +import sys +import mozpack.path as mozpath +from collections import OrderedDict +from mozpack.executables import ( + get_type, + ELF, + MACHO, +) +from buildconfig import substs + + +def dependentlibs_win32_objdump(lib): + proc = subprocess.Popen( + [substs["LLVM_OBJDUMP"], "--private-headers", lib], + stdout=subprocess.PIPE, + universal_newlines=True, + ) + deps = [] + for line in proc.stdout: + match = re.match("\s+DLL Name: (\S+)", line) + if match: + # The DLL Name found might be mixed-case or upper-case. When cross-compiling, + # the actual DLLs in dist/bin are all lowercase, whether they are produced + # by the build system or copied from WIN32_REDIST_DIR. By turning everything + # to lowercase, we ensure we always find the files. + # At runtime, when Firefox reads the dependentlibs.list file on Windows, the + # case doesn't matter. + deps.append(match.group(1).lower()) + proc.wait() + return deps + + +def dependentlibs_readelf(lib): + """Returns the list of dependencies declared in the given ELF .so""" + proc = subprocess.Popen( + [substs.get("READELF", "readelf"), "-d", lib], + stdout=subprocess.PIPE, + universal_newlines=True, + ) + deps = [] + for line in proc.stdout: + # Each line has the following format: + # tag (TYPE) value + # or with BSD readelf: + # tag TYPE value + # Looking for NEEDED type entries + tmp = line.strip().split(" ", 3) + if len(tmp) > 3 and "NEEDED" in tmp[1]: + # NEEDED lines look like: + # 0x00000001 (NEEDED) Shared library: [libname] + # or with BSD readelf: + # 0x00000001 NEEDED Shared library: [libname] + match = re.search("\[(.*)\]", tmp[3]) + if match: + deps.append(match.group(1)) + proc.wait() + return deps + + +def dependentlibs_mac_objdump(lib): + """Returns the list of dependencies declared in the given MACH-O dylib""" + proc = subprocess.Popen( + [substs["LLVM_OBJDUMP"], "--private-headers", lib], + stdout=subprocess.PIPE, + universal_newlines=True, + ) + deps = [] + cmd = None + for line in proc.stdout: + # llvm-objdump --private-headers output contains many different + # things. The interesting data + # is under "Load command n" sections, with the content: + # cmd LC_LOAD_DYLIB + # cmdsize 56 + # name libname (offset 24) + tmp = line.split() + if len(tmp) < 2: + continue + if tmp[0] == "cmd": + cmd = tmp[1] + elif cmd == "LC_LOAD_DYLIB" and tmp[0] == "name": + deps.append(re.sub("^@executable_path/", "", tmp[1])) + proc.wait() + return deps + + +def dependentlibs(lib, libpaths, func): + """For a given library, returns the list of recursive dependencies that can + be found in the given list of paths, followed by the library itself.""" + assert libpaths + assert isinstance(libpaths, list) + deps = OrderedDict() + for dep in func(lib): + if dep in deps or os.path.isabs(dep): + continue + for dir in libpaths: + deppath = os.path.join(dir, dep) + if os.path.exists(deppath): + deps.update(dependentlibs(deppath, libpaths, func)) + # Black list the ICU data DLL because preloading it at startup + # leads to startup performance problems because of its excessive + # size (around 10MB). Same thing with d3dcompiler_47.dll, but + # to a lesser extent, and we were going to dynamically load it + # anyway. + if not dep.startswith(("icu", "d3dcompiler_47")): + deps[dep] = deppath + break + + return deps + + +def gen_list(output, lib): + libpaths = [os.path.join(substs["DIST"], "bin")] + binary_type = get_type(lib) + if binary_type == ELF: + func = dependentlibs_readelf + elif binary_type == MACHO: + func = dependentlibs_mac_objdump + else: + ext = os.path.splitext(lib)[1] + assert ext == ".dll" + func = dependentlibs_win32_objdump + + deps = dependentlibs(lib, libpaths, func) + base_lib = mozpath.basename(lib) + deps[base_lib] = mozpath.join(libpaths[0], base_lib) + output.write("\n".join(deps.keys()) + "\n") + + with open(output.name + ".gtest", "w") as gtest_out: + libs = list(deps.keys()) + libs[-1] = "gtest/" + libs[-1] + gtest_out.write("\n".join(libs) + "\n") + + return set(deps.values()) + + +def main(): + gen_list(sys.stdout, sys.argv[1]) + + +if __name__ == "__main__": + main() diff --git a/toolkit/library/build/moz.build b/toolkit/library/build/moz.build new file mode 100644 index 0000000000..df0afaab84 --- /dev/null +++ b/toolkit/library/build/moz.build @@ -0,0 +1,42 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +USE_LIBS += [ + "static:xul", +] + +# This library is entirely composed of Rust code, and needs to come after +# all the C++ code so any possible C++ -> Rust calls can be resolved. +USE_LIBS += ["gkrust"] + +Libxul("xul-real") + +if CONFIG["COMPILE_ENVIRONMENT"]: + if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"): + full_libname = SHARED_LIBRARY_NAME + else: + full_libname = "%s%s%s" % ( + CONFIG["DLL_PREFIX"], + SHARED_LIBRARY_NAME, + CONFIG["DLL_SUFFIX"], + ) + GeneratedFile( + "dependentlibs.list", + "dependentlibs.list.gtest", + script="dependentlibs.py", + entry_point="gen_list", + inputs=["!%s" % full_libname], + ) + FINAL_TARGET_FILES += ["!dependentlibs.list", "!dependentlibs.list.gtest"] + +# Generate GDB pretty printer-autoload files only on Linux. OSX's GDB is +# too old to support Python pretty-printers; if this changes, we could +# make this 'ifdef __GNUC__'. +if CONFIG["OS_ARCH"] == "Linux": + # Create a GDB Python auto-load file alongside the libxul shared library + # in the build directory. + DEFINES["topsrcdir"] = TOPSRCDIR + OBJDIR_FILES.toolkit.library.build += ["../libxul.so-gdb.py"] diff --git a/toolkit/library/dummydll/dummydll.cpp b/toolkit/library/dummydll/dummydll.cpp new file mode 100644 index 0000000000..47605279e3 --- /dev/null +++ b/toolkit/library/dummydll/dummydll.cpp @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <windows.h> + +BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpvReserved) { + if (dwReason == DLL_PROCESS_ATTACH) { + ::DisableThreadLibraryCalls((HMODULE)hModule); + } + return TRUE; +} diff --git a/toolkit/library/dummydll/moz.build b/toolkit/library/dummydll/moz.build new file mode 100644 index 0000000000..4dd71bf38d --- /dev/null +++ b/toolkit/library/dummydll/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Bug 1294650 - populate our install with a shim dll to work around a +# 3rd party code injection crash. + +SOURCES += [ + "dummydll.cpp", +] + +if CONFIG["CPU_ARCH"] == "x86_64": + GeckoSharedLibrary("qipcap64") +else: + GeckoSharedLibrary("qipcap") + +NoVisibilityFlags() +NO_PGO = True diff --git a/toolkit/library/gecko.natvis b/toolkit/library/gecko.natvis new file mode 100644 index 0000000000..dfd1da6b04 --- /dev/null +++ b/toolkit/library/gecko.natvis @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="utf-8"?> +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <!-- Mozilla Gecko Visualizers --> + + <Type Name="mozilla::Maybe<*>"> + <DisplayString Condition="mIsSome == false">Nothing</DisplayString> + <DisplayString Condition="mIsSome == true">Some({*($T1 *)&mStorage.val})</DisplayString> + <Expand> + <ExpandedItem Condition="mIsSome == true">*($T1 *)&mStorage.val</ExpandedItem> + </Expand> + </Type> + + <Type Name="mozilla::Result<*,*>"> + <DisplayString>{mImpl}</DisplayString> + </Type> + + <Type Name="mozilla::detail::ResultImplementation<*,*,mozilla::detail::PackingStrategy::Variant>"> + <DisplayString Condition="mStorage.tag == false">ok: {*($T1 *)(mStorage.rawData)}</DisplayString> + <DisplayString Condition="mStorage.tag == true">err: {*($T2 *)(mStorage.rawData)}</DisplayString> + <DisplayString>%% invalid storage tag in variant %%</DisplayString> + <Expand> + <ExpandedItem Condition="mStorage.tag == false">*($T1 *)(mStorage.rawData)</ExpandedItem> + <ExpandedItem Condition="mStorage.tag == true">*($T2 *)(mStorage.rawData)</ExpandedItem> + </Expand> + </Type> + + <!-- nsTArray --> + <Type Name="nsTArray<*>"> + <DisplayString Condition="mHdr->mLength == 0 && mHdr->mCapacity == 0">empty</DisplayString> + <DisplayString Condition="mHdr->mLength == mHdr->mCapacity">size = {mHdr->mLength}</DisplayString> + <DisplayString>size = {mHdr->mLength}, capacity = {mHdr->mCapacity}</DisplayString> + <Expand> + <ArrayItems Condition="mHdr->mLength > 0"> + <Size>mHdr->mLength</Size> + <ValuePointer>($T1*)(mHdr + 1)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <!-- refcounts --> + <Type Name="nsAutoRefCnt"> + <DisplayString>{mValue}</DisplayString> + </Type> + + <Type Name="nsCycleCollectingAutoRefCnt"> + <!-- this value needs to be updated if NS_NUMBER_OF_FLAGS_IN_REFCNT in xpcom/glue/nsISupportsImpl.h changes --> + <DisplayString>{mValue >> 2}</DisplayString> + <Expand> + <Synthetic Name="In Purple Buffer"><DisplayString>{mValue & 1 != 0}</DisplayString></Synthetic> + <Synthetic Name="Is Purple"><DisplayString>{mValue & 2 != 0}</DisplayString></Synthetic> + </Expand> + </Type> + + <Type Name="mozilla::ThreadSafeAutoRefCnt"> + <DisplayString>{mValue.mValue._My_val}</DisplayString> + </Type> + + <!-- smart pointer/refcount pointer things --> + <Type Name="nsRefPtr<*>"> + <AlternativeType Name="nsCOMPtr<*>" /> + <AlternativeType Name="nsAutoPtr<*>" /> + <AlternativeType Name="mozilla::WebGLRefPtr<*>" /> + + <DisplayString Condition="mRawPtr == 0">NULL</DisplayString> + <DisplayString>{*($T1*)mRawPtr}</DisplayString> + <Expand> + <ExpandedItem>($T1*)mRawPtr</ExpandedItem> + </Expand> + </Type> + + <!-- strings --> + <Type Name="nsTString<char>"> + <AlternativeType Name="nsTLiteralString<char>" /> + <AlternativeType Name="mozilla::detail::nsTStringRepr<char>" /> + <AlternativeType Name="nsTSubstring<char>" /> + + <DisplayString>{mData,s}</DisplayString> + <StringView>mData,s</StringView> + <Expand> + <Item Name="Length">mLength</Item> + <Item Name="Flags">mDataFlags</Item> + </Expand> + </Type> + + <Type Name="nsTSubstringTuple<char>"> + <DisplayString Condition="mHead != nullptr">{mHead,na} {mFragB->mData,s}</DisplayString> + <DisplayString Condition="mHead == nullptr">{mFragA->mData,s} {mFragB->mData,s}</DisplayString> + </Type> + + <Type Name="nsTString<char16_t>"> + <AlternativeType Name="nsTLiteralString<char16_t>" /> + <AlternativeType Name="mozilla::detail::nsTStringRepr<char16_t>" /> + <AlternativeType Name="nsTSubstring<char16_t>" /> + + <DisplayString>{mData,su}</DisplayString> + <StringView>mData,su</StringView> + <Expand> + <Item Name="Length">mLength</Item> + <Item Name="Flags">mDataFlags</Item> + </Expand> + </Type> + + <Type Name="nsTSubstringTuple<char16_t>"> + <DisplayString Condition="mHead != nullptr">{mHead,na} {mFragB->mData,su}</DisplayString> + <DisplayString Condition="mHead == nullptr">{mFragA->mData,su} {mFragB->mData,su}</DisplayString> + </Type> + + <!-- rects, points, etc. --> + <Type Name="mozilla::gfx::BaseRect<*,*,*,*,*>"> + <AlternativeType Name="mozilla::gfx::Rect" /> + <DisplayString>x={x}, y={y}, width={width}, height={height}</DisplayString> + </Type> + + <Type Name="mozilla::gfx::BaseSize<*,*>"> + <AlternativeType Name="mozilla::gfx::Size" /> + <AlternativeType Name="nsIntSize" /> + <DisplayString>width={width}, height={height}</DisplayString> + </Type> + + <Type Name="mozilla::gfx::BasePoint<*,*>"> + <AlternativeType Name="mozilla::gfx::Point" /> + <DisplayString>x={x}, y={y}</DisplayString> + </Type> + + <Type Name="mozilla::gfx::Matrix4x4"> + <AlternativeType Name="gfx3DMatrix" /> + <DisplayString Condition="(_11==_22==_33==_44==1) && (_12==_13==_14==_21==_23==_24==_31==_32==_34==_41==_42==_43==0)">[Identity]</DisplayString> + <DisplayString Condition="(_11==_22==_33==_44==1) && (_12==_13==_14==_21==_23==_24==_31==_32==_34==0)">[Translate: ({_41}, {_42}, {_43})]</DisplayString> + <DisplayString Condition="_44==1 && (_12==_13==_14==_21==_23==_24==_31==_32==_34==_41==_42==_43==0)">[Scale: ({_11}, {_22}, {_33})]</DisplayString> + <DisplayString>[4x4 Matrix]</DisplayString> + + <Expand> + <Synthetic Name="R1"><DisplayString>[{_11}, {_12}, {_13}, {_14}]</DisplayString></Synthetic> + <Synthetic Name="R2"><DisplayString>[{_21}, {_22}, {_23}, {_24}]</DisplayString></Synthetic> + <Synthetic Name="R3"><DisplayString>[{_31}, {_32}, {_33}, {_34}]</DisplayString></Synthetic> + <Synthetic Name="R4"><DisplayString>[{_41}, {_42}, {_43}, {_44}]</DisplayString></Synthetic> + </Expand> + </Type> + + <!-- JS types --> + <Type Name="JS::Handle<*>"> + <DisplayString Condition="ptr == 0">NULL</DisplayString> + <DisplayString>{*($T1*)ptr}</DisplayString> + <Expand> + <ExpandedItem>($T1*)ptr</ExpandedItem> + </Expand> + </Type> + + +</AutoVisualizer> diff --git a/toolkit/library/gen_buildid.py b/toolkit/library/gen_buildid.py new file mode 100644 index 0000000000..9943ad2539 --- /dev/null +++ b/toolkit/library/gen_buildid.py @@ -0,0 +1,41 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distibuted with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +import os +from io import StringIO + +import buildconfig +from mozbuild.preprocessor import Preprocessor + + +def main(output, input_file): + with open(input_file) as fh: + if buildconfig.substs["EXPAND_LIBS_LIST_STYLE"] == "linkerscript": + + def cleanup(line): + assert line.startswith('INPUT("') + assert line.endswith('")') + return line[len('INPUT("') : -len('")')] + + objs = [cleanup(l.strip()) for l in fh.readlines()] + else: + objs = [l.strip() for l in fh.readlines()] + + pp = Preprocessor() + pp.out = StringIO() + pp.do_include(os.path.join(buildconfig.topobjdir, "buildid.h")) + buildid = pp.context["MOZ_BUILDID"] + output.write('extern const char gToolkitBuildID[] = "%s";' % buildid) + return set( + os.path.join("build", o) + for o in objs + if os.path.splitext(os.path.basename(o))[0] != "buildid" + ) diff --git a/toolkit/library/gtest/TestUCRTDepends.cpp b/toolkit/library/gtest/TestUCRTDepends.cpp new file mode 100644 index 0000000000..a2faaf5ce3 --- /dev/null +++ b/toolkit/library/gtest/TestUCRTDepends.cpp @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <windows.h> +#include <stdio.h> +#include <string.h> +#include "gtest/gtest.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/Unused.h" +#include "mozilla/WindowsVersion.h" +#include "nsDependentString.h" +#include "nsReadableUtils.h" +#include "nsUnicharUtils.h" +#include "nsWindowsHelpers.h" + +using namespace mozilla; + +constexpr const WCHAR pattern[] = L"\\api-*.dll"; + +static LPWSTR GetModuleFileDir(HMODULE module, LPWSTR path, DWORD size) { + DWORD chars = GetModuleFileNameW(module, path, size); + if (chars <= 0 || chars >= MAX_PATH) { + return nullptr; + } + + // Split the base name from the directory. + LPWSTR basename = wcsrchr(path, L'\\'); + if (!basename) { + return nullptr; // at least one path separator must be present + } + *basename++ = L'\0'; + return basename; +} + +// Make sure that Universal CRT forwarder DLLs are not in app directory if it +// is in Api Sets. +TEST(TestUCRTDepends, AppDir) +{ + WCHAR appdir[MAX_PATH]; + ASSERT_TRUE(GetModuleFileDir(nullptr, appdir, MAX_PATH)); + + WCHAR path[MAX_PATH + ArrayLength(pattern)]; + swprintf(path, L"%s%s", appdir, pattern); + + WIN32_FIND_DATAW wfd; + HANDLE hFind = FindFirstFileW(path, &wfd); +#if defined(_M_ARM64) // We do not ship Universal CRT DLLs on aarch64. + if (hFind == INVALID_HANDLE_VALUE) { + EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_FILE_NOT_FOUND)); + return; + } +#else + ASSERT_NE(hFind, INVALID_HANDLE_VALUE); +#endif + do { + nsModuleHandle module(LoadLibraryW(wfd.cFileName)); + EXPECT_TRUE(module); + if (!module) { + continue; + } + + // Get a full path of the loaded module. + LPWSTR basename = GetModuleFileDir(module, path, MAX_PATH); + ASSERT_TRUE(basename); + + // If the module is in Api Sets, GetModuleFileName returns the redirected + // DLL path, so filenames will not match. + bool inApiSets = wcsicmp(wfd.cFileName, basename); + if (IsWin10OrLater()) { + // All files must be in Api Sets on Windows 10. + EXPECT_TRUE(inApiSets); + continue; + } + if (IsWin8OrLater()) { + if (inApiSets) { + continue; // This file is in Api Sets, OK. + } + // Universal CRT files are not in Api Sets on Windows 8. + EXPECT_TRUE(StringBeginsWith(nsDependentString(wfd.cFileName), + u"api-ms-win-crt-"_ns, + nsCaseInsensitiveStringComparator)); + } else { // Windows 7 + // All files must not be in Api Sets on Windows 7. + EXPECT_FALSE(inApiSets); + } + // Files must be loaded from appdir + EXPECT_TRUE(!wcsicmp(path, appdir)); + } while (FindNextFileW(hFind, &wfd)); + EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_NO_MORE_FILES)); + BOOL ret = FindClose(hFind); + EXPECT_TRUE(ret); +} + +// Make sure that we do not depend on Universal CRT forwarder DLLs in the +// system directory. +TEST(TestUCRTDepends, SystemDir) +{ + WCHAR appdir[MAX_PATH]; + ASSERT_TRUE(GetModuleFileDir(nullptr, appdir, MAX_PATH)); + + WCHAR path[MAX_PATH + ArrayLength(pattern)]; + UINT chars = GetSystemDirectoryW(path, MAX_PATH); + ASSERT_TRUE(chars > 0 && chars < MAX_PATH); + wcscat(path, pattern); + + WIN32_FIND_DATAW wfd; + HANDLE hFind = FindFirstFileW(path, &wfd); + if (hFind == INVALID_HANDLE_VALUE) { + EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_FILE_NOT_FOUND)); + EXPECT_TRUE(IsWin8OrLater()); + return; // Not found in the system directory, OK. + } + // Api Sets forwarders must not be present on Windows 10. + EXPECT_FALSE(IsWin10OrLater()); + do { + HMODULE module = GetModuleHandleW(wfd.cFileName); + if (!module) { + continue; // We are not using this file, OK. + } + + // Get a full path of the loaded module. + LPWSTR basename = GetModuleFileDir(module, path, MAX_PATH); + ASSERT_TRUE(basename); + + // If the module is in Api Sets, GetModuleFileName returns the redirected + // DLL path, so filenames will not match. + if (wcsicmp(wfd.cFileName, basename)) { + // If this file is in Api Sets, it must not be present in appdir. + swprintf(path, L"%s\\%s", appdir, wfd.cFileName); + EXPECT_EQ(GetFileAttributesW(path), INVALID_FILE_ATTRIBUTES); + } else { + // If this file is not in Api Sets, it must be loaded from appdir. + EXPECT_TRUE(!wcsicmp(path, appdir)); + } + } while (FindNextFileW(hFind, &wfd)); + EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_NO_MORE_FILES)); + BOOL ret = FindClose(hFind); + EXPECT_TRUE(ret); +} diff --git a/toolkit/library/gtest/moz.build b/toolkit/library/gtest/moz.build new file mode 100644 index 0000000000..1a0f692bc7 --- /dev/null +++ b/toolkit/library/gtest/moz.build @@ -0,0 +1,26 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +FINAL_TARGET = "dist/bin/gtest" + +if CONFIG["ENABLE_TESTS"]: + USE_LIBS += [ + "gkrust-gtest", + ] + + if CONFIG["OS_ARCH"] == "WINNT": + UNIFIED_SOURCES += [ + "TestUCRTDepends.cpp", + ] + +USE_LIBS += [ + "static:xul", +] + +Libxul( + "xul-gtest", + output_category=None if CONFIG["LINK_GTEST_DURING_COMPILE"] else "gtest", +) diff --git a/toolkit/library/gtest/rust/Cargo.toml b/toolkit/library/gtest/rust/Cargo.toml new file mode 100644 index 0000000000..a97956ef7e --- /dev/null +++ b/toolkit/library/gtest/rust/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "gkrust-gtest" +version = "0.1.0" +authors = ["The Mozilla Project Developers"] +license = "MPL-2.0" +description = "Testing code for libgkrust" + +[dependencies] +bench-collections-gtest = { path = "../../../../xpcom/rust/gtest/bench-collections" } +l10nregistry-ffi-gtest = { path = "../../../../intl/l10n/rust/gtest" } +moz_task-gtest = { path = "../../../../xpcom/rust/gtest/moz_task" } +mp4parse-gtest = { path = "../../../../dom/media/gtest" } +nsstring-gtest = { path = "../../../../xpcom/rust/gtest/nsstring" } +xpcom-gtest = { path = "../../../../xpcom/rust/gtest/xpcom" } +gkrust-shared = { path = "../../rust/shared" } +gecko-fuzz-targets = { path = "../../../../tools/fuzzing/rust", optional = true } +fog-gtest = { path = "../../../components/glean/tests/gtest" } +dap_ffi-gtest = { path = "../../../components/telemetry/dap/ffi-gtest" } +dllservices-gtest = { path = "../../../xre/dllservices/tests/gtest/rust" } + +# Workarounds for https://github.com/rust-lang/rust/issues/58393 +mozglue-static = { path = "../../../../mozglue/static/rust" } +swgl = { path = "../../../../gfx/wr/swgl" } +lmdb-rkv-sys = "0.11" + +[lib] +path = "lib.rs" +crate-type = ["staticlib"] +test = false +doctest = false +bench = false +doc = false +plugin = false +harness = false diff --git a/toolkit/library/gtest/rust/lib.rs b/toolkit/library/gtest/rust/lib.rs new file mode 100644 index 0000000000..218353ee2e --- /dev/null +++ b/toolkit/library/gtest/rust/lib.rs @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extern crate bench_collections_gtest; +extern crate dap_ffi_gtest; +extern crate fog_gtest; +#[cfg(feature = "gecko-fuzz-targets")] +extern crate gecko_fuzz_targets; +extern crate gkrust_shared; +extern crate l10nregistry_ffi_gtest; +extern crate moz_task_gtest; +extern crate mp4parse_gtest; +extern crate nsstring_gtest; +extern crate xpcom_gtest; +extern crate dllservices_gtest; diff --git a/toolkit/library/gtest/rust/moz.build b/toolkit/library/gtest/rust/moz.build new file mode 100644 index 0000000000..8b98fbfda0 --- /dev/null +++ b/toolkit/library/gtest/rust/moz.build @@ -0,0 +1,16 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include("../../rust/gkrust-features.mozbuild") + +if CONFIG["LIBFUZZER"]: + gkrust_features += ["gecko-fuzz-targets"] + +RustLibrary( + "gkrust-gtest", + gkrust_features, + output_category=None if CONFIG["LINK_GTEST_DURING_COMPILE"] else "gtest", +) diff --git a/toolkit/library/libxul.so-gdb.py b/toolkit/library/libxul.so-gdb.py new file mode 100644 index 0000000000..d84aead1c3 --- /dev/null +++ b/toolkit/library/libxul.so-gdb.py @@ -0,0 +1,35 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +""" GDB Python customization auto-loader for libxul """ + +import re +from os.path import abspath, dirname, exists + +# Add the toplevel objdir to the gdb source search path. + +# In development builds, $objdir/dist/bin/libxul.so is a symlink to +# $objdir/toolkit/library/build/libxul.so, and the latter path is what gdb uses +# to search for gdb scripts. +# +# For artifact builds, libxul.so will be a regular file in $objdir/dist/bin. +# Look both places. + +libxul_dir = dirname(__file__) +objdir = None +for relpath in ("../../..", "../.."): + objdir = abspath(libxul_dir + "/" + relpath) + if exists(objdir + "/build/.gdbinit"): + break +else: + gdb.write("Warning: Gecko objdir not found\n") + +if objdir is not None: + m = re.search(r"[\w ]+: (.*)", gdb.execute("show dir", False, True)) + if m and objdir not in m.group(1).split(":"): + gdb.execute("set dir {}:{}".format(objdir, m.group(1))) + + # When running from a random directory, the toplevel Gecko .gdbinit may + # not have been loaded. Load it now. + gdb.execute("source -s build/.gdbinit.loader") diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build new file mode 100644 index 0000000000..0f9d7e95bf --- /dev/null +++ b/toolkit/library/moz.build @@ -0,0 +1,417 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +@template +def Libxul_defines(): + LIBRARY_DEFINES["MOZILLA_INTERNAL_API"] = True + LIBRARY_DEFINES["IMPL_LIBXUL"] = True + if not CONFIG["JS_SHARED_LIBRARY"]: + LIBRARY_DEFINES["STATIC_EXPORTABLE_JS_API"] = True + + +@template +def Libxul(name, output_category=None): + if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"): + # This is going to be a framework named "XUL", not an ordinary library named + # "libxul.dylib" + GeckoFramework(name, output_category=output_category, linkage=None) + SHARED_LIBRARY_NAME = "XUL" + else: + GeckoSharedLibrary(name, output_category=output_category, linkage=None) + SHARED_LIBRARY_NAME = "xul" + + DELAYLOAD_DLLS += [ + "avrt.dll", + "comdlg32.dll", + "credui.dll", + "d3d11.dll", + "D3DCompiler_47.dll", + "dhcpcsvc.dll", + "dnsapi.dll", + "dwmapi.dll", + "dxgi.dll", + "gdi32.dll", + "hid.dll", + "imm32.dll", + "iphlpapi.dll", + "msi.dll", + "msimg32.dll", + "netapi32.dll", + "ole32.dll", + "oleaut32.dll", + "secur32.dll", + "setupapi.dll", + "shell32.dll", + "shlwapi.dll", + "urlmon.dll", + "user32.dll", + "userenv.dll", + "usp10.dll", + "uxtheme.dll", + "wininet.dll", + "winmm.dll", + "winspool.drv", + "wtsapi32.dll", + ] + + if CONFIG["ACCESSIBILITY"]: + DELAYLOAD_DLLS += ["oleacc.dll"] + + if CONFIG["MOZ_WEBRTC"]: + DELAYLOAD_DLLS += ["msdmo.dll"] + + if CONFIG["OS_ARCH"] == "WINNT": + DELAYLOAD_DLLS += [ + "api-ms-win-core-winrt-l1-1-0.dll", + "api-ms-win-core-winrt-string-l1-1-0.dll", + ] + + if CONFIG["OS_ARCH"] == "WINNT" and CONFIG["ACCESSIBILITY"]: + LOCAL_INCLUDES += ["!/accessible/interfaces/gecko/"] + + if CONFIG["OS_ARCH"] == "WINNT": + LOCAL_INCLUDES += [ + "/widget/windows", + "/xpcom/base", + ] + RCINCLUDE = "/toolkit/library/xulrunner.rc" + + # Show a breakdown of linker time. (Too verbose for local builds.) + if CONFIG["CC_TYPE"] == "clang-cl" and not CONFIG["DEVELOPER_OPTIONS"]: + LDFLAGS += ["-time"] + + Libxul_defines() + + if CONFIG["MOZ_NEEDS_LIBATOMIC"]: + OS_LIBS += ["atomic"] + + # TouchBar-related classes are only available in the 10.12.2 SDK and later. + # We need to weak link these classes until we've upgraded our SDK to at + # least 10.12.2. + # We're also linking against libresolv to solve bug 1367932. + if CONFIG["OS_ARCH"] == "Darwin": + LDFLAGS += ["-Wl,-U,_OBJC_CLASS_$_NSTouchBar"] + LDFLAGS += ["-Wl,-U,_OBJC_CLASS_$_NSSharingServicePickerTouchBarItem"] + LDFLAGS += ["-Wl,-U,_OBJC_METACLASS_$_NSTouchBar"] + LDFLAGS += ["-Wl,-U,_OBJC_CLASS_$_NSCustomTouchBarItem"] + LDFLAGS += ["-Wl,-U,_OBJC_CLASS_$_NSPopoverTouchBarItem"] + LDFLAGS += ["-lresolv"] + + if CONFIG["MOZ_DEBUG_SYMBOLS"] and CONFIG["CC_TYPE"] == "clang-cl": + LDFLAGS += ["-NATVIS:%s/toolkit/library/gecko.natvis" % TOPSRCDIR] + if CONFIG["RUSTC_NATVIS_LDFLAGS"]: + LDFLAGS += CONFIG["RUSTC_NATVIS_LDFLAGS"] + + if CONFIG["OS_ARCH"] == "Linux" and CONFIG["OS_TARGET"] != "Android": + GeneratedFile( + "symverscript", + script="/build/gen_symverscript.py", + inputs=["../symverscript.in"], + flags=["xul%s" % CONFIG["MOZILLA_SYMBOLVERSION"]], + ) + SYMBOLS_FILE = "!symverscript" + + +# The real libxul definition is in ./build/moz.build, but we define a +# xul library here such that # FINAL_LIBRARY = 'xul' refers to here, which +# is then linked to both build/libxul and gtest/libxul. +Library("xul") + +STATIC_LIBRARY_NAME = "xul_s" + +# Use a FINAL_LIBRARY for Libxul_defines to propagate from there. They wouldn't +# propagate from here. +FINAL_LIBRARY = "xul-real" + +if CONFIG["OS_ARCH"] == "WINNT": + SOURCES += [ + "nsDllMain.cpp", + ] + +LOCAL_INCLUDES += [ + "/config", + # need widget/windows for resource.h (included from widget.rc) + "/widget/windows", +] + +if CONFIG["OS_ARCH"] == "WINNT" and CONFIG["CC_TYPE"] not in ("clang", "gcc"): + LOCAL_INCLUDES += [ + "/xpcom/base", + ] + +DIRS += [ + "build", + "gtest", +] + +if CONFIG["OS_ARCH"] == "WINNT": + DIRS += ["dummydll"] + +# js needs to come after xul for now, because it is an archive and its content +# is discarded when it comes first. +USE_LIBS += [ + "js", +] + +USE_LIBS += [ + "lgpllibs", + "nspr", + "nss", + "psshparser", + "sqlite", + "zlib", +] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + # The mozgtk library is a workaround that makes Gtk+ use libwayland-client + # instead of mozwayland. The reason it works is that by being a dependency + # of libxul, mozgtk appears in dependentlibs.list, preceding mozwayland + # (which is important and guaranteed by the USE_LIBS order in this file). + # That, in turn, makes firefox dlopen() mozgtk before mozwayland, which + # will trigger the loading of the Gtk+ libraries (mozgtk depending on them). + # Those libraries, if they depend on libwayland-client, will use the symbols + # from libwayland-client because mozwayland is not loaded yet. + # When eventually libxul is loaded after both mozgtk and mozwayland, it will + # get symbols from libwayland-client too. + # In the case where Gtk+ doesn't have wayland support, libwayland-client is + # not loaded, and libxul ends up using the mozwayland symbols. + USE_LIBS += [ + "mozgtk", + ] + OS_LIBS += CONFIG["MOZ_GTK3_LIBS"] + +if CONFIG["MOZ_WAYLAND"]: + USE_LIBS += [ + "mozwayland", + ] + +if CONFIG["MOZ_JPROF"]: + USE_LIBS += [ + "jprof", + ] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk" or CONFIG["MOZ_TREE_FREETYPE"]: + USE_LIBS += [ + "freetype", + ] + +if CONFIG["MOZ_WEBRTC"]: + if CONFIG["OS_TARGET"] == "WINNT": + OS_LIBS += [ + "secur32", + "iphlpapi", + "strmiids", + "dmoguids", + "wmcodecdspuuid", + "amstrmid", + "msdmo", + "wininet", + ] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa": + OS_LIBS += [ + "-framework Foundation", + "-framework CoreFoundation", + "-framework CoreLocation", + "-framework QuartzCore", + "-framework Carbon", + "-framework CoreAudio", + "-framework CoreVideo", + "-framework AudioToolbox", + "-framework AudioUnit", + "-framework AddressBook", + "-framework OpenGL", + "-framework Security", + "-framework ServiceManagement", + "-framework CoreServices", + "-framework ApplicationServices", + "-framework AppKit", + "-framework CoreMIDI", + "-framework SystemConfiguration", + "-framework AVFoundation", + "-framework CoreMedia", + "-framework IOKit", + "-F%s" % CONFIG["MACOS_PRIVATE_FRAMEWORKS_DIR"], + "-framework CoreUI", + "-framework CoreSymbolication", + "cups", + ] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "uikit": + OS_LIBS += [ + "-framework Foundation", + "-framework CoreFoundation", + "-framework CoreGraphics", + "-framework CoreText", + "-framework AVFoundation", + "-framework AudioToolbox", + "-framework CoreMedia", + "-framework CoreVideo", + "-framework OpenGLES", + "-framework QuartzCore", + ] + +if CONFIG["MOZ_WMF"]: + OS_LIBS += [ + "mfuuid", + "wmcodecdspuuid", + "strmiids", + ] + +if CONFIG["OS_ARCH"] == "FreeBSD": + OS_LIBS += [ + "util", + ] + +if CONFIG["OS_ARCH"] == "WINNT": + OS_LIBS += [ + "crypt32", + "gdi32", + "shell32", + "ntdll", + "ole32", + "version", + "winspool", + "userenv", + "uuid", + ] + +if CONFIG["OS_ARCH"] == "Linux" and CONFIG["OS_TARGET"] != "Android": + OS_LIBS += [ + "rt", + ] + +if CONFIG["MOZ_ANDROID_GOOGLE_VR"]: + OS_LIBS += [ + "-L%s" % CONFIG["MOZ_ANDROID_GOOGLE_VR_LIBS"], + "-lgvr", + ] + +if CONFIG["MOZ_SYSTEM_JPEG"]: + OS_LIBS += CONFIG["MOZ_JPEG_LIBS"] + +if CONFIG["MOZ_SYSTEM_PNG"]: + OS_LIBS += CONFIG["MOZ_PNG_LIBS"] + +if CONFIG["MOZ_SYSTEM_WEBP"]: + OS_LIBS += CONFIG["MOZ_WEBP_LIBS"] + +if CONFIG["MOZ_SYSTEM_LIBEVENT"]: + OS_LIBS += CONFIG["MOZ_LIBEVENT_LIBS"] + +if CONFIG["MOZ_SYSTEM_LIBVPX"]: + OS_LIBS += CONFIG["MOZ_LIBVPX_LIBS"] + +if not CONFIG["MOZ_TREE_PIXMAN"]: + OS_LIBS += CONFIG["MOZ_PIXMAN_LIBS"] + +if CONFIG["HAVE_CLOCK_MONOTONIC"]: + OS_LIBS += CONFIG["REALTIME_LIBS"] + +OS_LIBS += CONFIG["ICONV_LIBS"] + +if CONFIG["OS_ARCH"] == "OpenBSD": + OS_LIBS += [ + "sndio", + ] + +if CONFIG["MOZ_ENABLE_DBUS"]: + OS_LIBS += CONFIG["MOZ_DBUS_GLIB_LIBS"] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk" and CONFIG["COMPILE_ENVIRONMENT"]: + OS_LIBS += [l for l in CONFIG["MOZ_GTK3_LIBS"] if l not in ("-lgtk-3", "-lgdk-3")] + OS_LIBS += CONFIG["MOZ_X11_LIBS"] + OS_LIBS += CONFIG["MOZ_PANGO_LIBS"] + +if CONFIG["MOZ_ENABLE_LIBPROXY"]: + OS_LIBS += CONFIG["MOZ_LIBPROXY_LIBS"] + +if CONFIG["OS_ARCH"] == "FreeBSD": + OS_LIBS += [ + "util", + ] + +if CONFIG["OS_ARCH"] == "Darwin": + OS_LIBS += [ + # Link to Metal as required by the Metal gfx-hal backend + "-weak_framework Metal", + "-weak_framework MediaPlayer", + ] + + +if CONFIG["OS_ARCH"] == "WINNT": + OS_LIBS += [ + "shell32", + "ole32", + "version", + "winspool", + "comdlg32", + "imm32", + "msimg32", + "netapi32", + "shlwapi", + "ws2_32", + "dnsapi", + "dwmapi", + "iphlpapi", + "uxtheme", + "setupapi", + "secur32", + "sensorsapi", + "portabledeviceguids", + "wininet", + "wintrust", + "wtsapi32", + "locationapi", + "sapi", + "dxguid", + "dhcpcsvc", + # gfx-rs supports D3D11 and D3D12, but we are not linking to them implicitly + # "d3d11", # should be explicitly linked by gfx-backend-d3d11 + #'d3d12', # should be explicitly linked by d3d12-rs + "d3dcompiler", + ] + + if CONFIG["CC_TYPE"] == "clang-cl": + OS_LIBS += [ + "runtimeobject", + ] + + if CONFIG["ACCESSIBILITY"]: + OS_LIBS += [ + "oleacc", + ] + + # Prevent winapi-rs from statically linking + LIBRARY_DEFINES["WINAPI_NO_BUNDLED_LIBRARIES"] = True + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": + OS_LIBS += [ + "usp10", + "oleaut32", + ] + +# The buildid is refreshed on every (incremental) build. But we want to avoid +# rebuilding libxul every time, so instead of having a source file that +# #include's buildid.h, which would have a dependency on it, and that would +# thus trigger make to rebuild everything, we generate a source with the +# buildid hard coded in it. Then we make that source file depend on all the +# objects files that constitute libxul, so that if any of the files linked into +# libxul is rebuilt, we refresh the buildid and link it into libxul. + +if CONFIG["COMPILE_ENVIRONMENT"]: + SOURCES += ["!buildid.cpp"] + if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"): + libxul_list = "XUL" + else: + libxul_list = "%sxul_%s" % ( + CONFIG["DLL_PREFIX"], + CONFIG["DLL_SUFFIX"].lstrip(".").replace(".", "_"), + ) + GeneratedFile( + "buildid.cpp", script="gen_buildid.py", inputs=["!build/%s.list" % libxul_list] + ) diff --git a/toolkit/library/nsDllMain.cpp b/toolkit/library/nsDllMain.cpp new file mode 100644 index 0000000000..396005b184 --- /dev/null +++ b/toolkit/library/nsDllMain.cpp @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <windows.h> +#include "nsToolkit.h" +#include "mozilla/Assertions.h" +#include "mozilla/WindowsVersion.h" + +#if defined(__GNUC__) +// If DllMain gets name mangled, it won't be seen. +extern "C" { +#endif + +BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved) { + switch (reason) { + case DLL_PROCESS_ATTACH: + nsToolkit::Startup((HINSTANCE)hModule); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + nsToolkit::Shutdown(); + break; + } + + return TRUE; +} + +#if defined(__GNUC__) +} // extern "C" +#endif diff --git a/toolkit/library/rust/Cargo.toml b/toolkit/library/rust/Cargo.toml new file mode 100644 index 0000000000..a7eee7999d --- /dev/null +++ b/toolkit/library/rust/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "gkrust" +version = "0.1.0" +authors = ["The Mozilla Project Developers"] +license = "MPL-2.0" +description = "Rust code for libxul" + +[dependencies] +gkrust-shared = { path = "shared" } +mozilla-central-workspace-hack = { path = "../../../build/workspace-hack" } + +# Workarounds for https://github.com/rust-lang/rust/issues/58393 +mozglue-static = { path = "../../../mozglue/static/rust" } +swgl = { path = "../../../gfx/wr/swgl" } +lmdb-rkv-sys = "0.11" + +[dev-dependencies] +stylo_tests = { path = "../../../servo/ports/geckolib/tests/" } + +[lib] +path = "lib.rs" +crate-type = ["staticlib"] +test = false +doctest = false +bench = false +doc = false +plugin = false +harness = false + +[package.metadata.cargo-udeps.ignore] +normal = ["mozilla-central-workspace-hack"] diff --git a/toolkit/library/rust/gkrust-features.mozbuild b/toolkit/library/rust/gkrust-features.mozbuild new file mode 100644 index 0000000000..2c1c4bbd6a --- /dev/null +++ b/toolkit/library/rust/gkrust-features.mozbuild @@ -0,0 +1,81 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +gkrust_features = [] + +if CONFIG['MOZ_DEBUG']: + gkrust_features += [ + 'gecko_debug', + 'gecko_refcount_logging', + ] + +if CONFIG['MOZ_TSAN']: + gkrust_features += ['thread_sanitizer'] + +if CONFIG['MOZ_WEBRENDER_DEBUGGER']: + gkrust_features += ['webrender_debugger'] + +if CONFIG['MOZ_PULSEAUDIO']: + gkrust_features += ['cubeb_pulse_rust'] + +if CONFIG['MOZ_AUDIOUNIT_RUST']: + gkrust_features += ['cubeb_coreaudio_rust'] + +if CONFIG['MOZ_RUST_SIMD']: + gkrust_features += ['simd-accel'] + +# This feature is not yet supported on all platforms, and this check needs to +# match MOZ_CUBEB_REMOTING in CubebUtils.cpp. +if (CONFIG['OS_ARCH'] == 'Linux' and CONFIG['OS_TARGET'] != 'Android') or CONFIG['OS_ARCH'] == 'Darwin' or CONFIG['OS_ARCH'] == 'WINNT': + gkrust_features += ['cubeb-remoting'] + +if CONFIG['MOZ_MEMORY']: + gkrust_features += ['moz_memory'] + +if CONFIG['MOZ_PLACES']: + gkrust_features += ['moz_places'] + +if CONFIG['JS_ENABLE_SMOOSH']: + gkrust_features += ['smoosh'] + +if CONFIG['MOZ_GECKO_PROFILER']: + gkrust_features += ['gecko_profiler'] + +if CONFIG['MOZ_GECKO_PROFILER_PARSE_ELF']: + gkrust_features += ['gecko_profiler_parse_elf'] + +if CONFIG['MOZ_BITS_DOWNLOAD']: + gkrust_features += ['bitsdownload'] + +if CONFIG['LIBFUZZER']: + gkrust_features += ['libfuzzer'] + +if CONFIG['MOZ_WEBRTC']: + gkrust_features += ['webrtc'] + +# We need to tell Glean it is being built with Gecko. +gkrust_features += ['glean_with_gecko'] + +if not CONFIG['MOZILLA_OFFICIAL']: + gkrust_features += ['glean_disable_upload'] + +if CONFIG['OS_TARGET'] != 'Android': + gkrust_features += ['glean_million_queue'] + +if CONFIG['MOZ_ENABLE_DBUS']: + gkrust_features += ['with_dbus'] + +if CONFIG["MOZ_CRASHREPORTER"] and CONFIG['MOZ_OXIDIZED_BREAKPAD']: + gkrust_features += ['oxidized_breakpad'] + +if CONFIG["MOZ_WEBMIDI_MIDIR_IMPL"]: + gkrust_features += ['webmidi_midir_impl'] + +if CONFIG["MOZ_UNIFFI_FIXTURES"]: + gkrust_features += ['uniffi_fixtures'] + +# This must remain last. +gkrust_features = ["gkrust-shared/%s" % f for f in gkrust_features] diff --git a/toolkit/library/rust/lib.rs b/toolkit/library/rust/lib.rs new file mode 100644 index 0000000000..815413a5da --- /dev/null +++ b/toolkit/library/rust/lib.rs @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// You should not be adding code to this crate; you will almost certainly +// get link errors when linking libxul-gtest. Add any |extern crate| +// declarations or similar to the gkrust-shared crate in +// toolkit/library/rust/shared/lib.rs. +extern crate gkrust_shared; diff --git a/toolkit/library/rust/moz.build b/toolkit/library/rust/moz.build new file mode 100644 index 0000000000..0ce6e469c6 --- /dev/null +++ b/toolkit/library/rust/moz.build @@ -0,0 +1,58 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include("gkrust-features.mozbuild") + +RustLibrary("gkrust", gkrust_features, is_gkrust=True) + +for feature in gkrust_features: + # We don't want to enable refcount logging during rusttests, since the + # relevant FFI symbols wouldn't be found. + # Nor do we want Glean to assume there are Gecko symbols. + if feature not in ( + "gkrust-shared/gecko_refcount_logging", + "gkrust-shared/glean_with_gecko", + ): + RUST_TEST_FEATURES.append(feature) + +# Target directory doesn't matter a lot here, since we can't share panic=abort +# compilation artifacts with gkrust. +RUST_TESTS = [ + "firefox-on-glean", + "l10nregistry", + "selectors", + "servo_arc", + "qcms", + # this does nothing, but is needed so that `gkrust_features` are recognized + # also see: https://github.com/rust-lang/cargo/issues/9856 + "gkrust", +] + +# Code coverage builds link a bunch of Gecko bindings code from the style +# crate, which is not used by our tests but would cause link errors. +# +# Bug 1768874 tracks improving the setup to potentially remove these +# altogether. +if not CONFIG["MOZ_CODE_COVERAGE"]: + RUST_TESTS += ["stylo_tests"] + # Same happens for the style tests, except the windows linker is not great + # at eliminating dead code, so we end up with some missing symbols too. + if CONFIG["OS_TARGET"] != "WINNT": + RUST_TESTS += ["style"] + +if CONFIG["CPU_ARCH"] != "x86": + # malloc_size_of_derive is a build dependency, so if we are doing + # cross-compile for x86, this may not run correctly. + RUST_TESTS += ["malloc_size_of_derive"] + +if CONFIG["MOZ_BITS_DOWNLOAD"]: + RUST_TESTS += ["bits_client"] + +# Export the `rure` crate's included .h file. The symbols defined in that file +# will be exported from the `gkrust-shared` crate. +EXPORTS += [ + "/third_party/rust/rure/include/rure.h", +] diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml new file mode 100644 index 0000000000..2a63b594f4 --- /dev/null +++ b/toolkit/library/rust/shared/Cargo.toml @@ -0,0 +1,156 @@ + +[package] +name = "gkrust-shared" +version = "0.1.0" +authors = ["The Mozilla Project Developers"] +license = "MPL-2.0" +description = "Shared Rust code for libxul" + +[dependencies] +moz_asserts = "0.1" +mozglue-static = { path = "../../../../mozglue/static/rust" } +geckoservo = { path = "../../../../servo/ports/geckolib" } +kvstore = { path = "../../../components/kvstore" } +lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] } +mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "cf8b0e04de9c60f38f7f057f9f29c74d19336d0c", features = ["missing-pixi-permitted"] } +nserror = { path = "../../../../xpcom/rust/nserror" } +nsstring = { path = "../../../../xpcom/rust/nsstring" } +netwerk_helper = { path = "../../../../netwerk/base/rust-helper" } +xpcom = { path = "../../../../xpcom/rust/xpcom" } +prefs_parser = { path = "../../../../modules/libpref/parser" } +static_prefs = { path = "../../../../modules/libpref/init/static_prefs" } +profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true } +mozurl = { path = "../../../../netwerk/base/mozurl" } +webrender_bindings = { path = "../../../../gfx/webrender_bindings" } +cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "93b5c01a131f65c83c11aeb317f4583405c5eb79", optional = true } +cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="cf48897be5cbe147d051ebbbe1eaf5fd8fb6bbc9", optional = true, features=["pulse-dlopen"] } +cubeb-sys = { version = "0.10.3", optional = true, features=["gecko-in-tree"] } +audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "0b51291d2483a17dce3e300c7784b369e02bee73", optional = true } +audioipc2-server = { git = "https://github.com/mozilla/audioipc", rev = "0b51291d2483a17dce3e300c7784b369e02bee73", optional = true } +encoding_glue = { path = "../../../../intl/encoding_glue" } +authrs_bridge = { path = "../../../../dom/webauthn/authrs_bridge" } +gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" } +gecko_logger = { path = "../../../../xpcom/rust/gecko_logger" } +rsdparsa_capi = { path = "../../../../dom/media/webrtc/sdp/rsdparsa_capi" } +# We have these to enforce common feature sets for said crates. +log = {version = "0.4", features = ["release_max_level_info"]} +cose-c = { version = "0.1.5" } +jsrust_shared = { path = "../../../../js/src/rust/shared" } +cascade_bloom_filter = { path = "../../../components/cascade_bloom_filter" } +cert_storage = { path = "../../../../security/manager/ssl/cert_storage" } +crypto_hash = { path = "../../../../security/manager/ssl/crypto_hash" } +bitsdownload = { path = "../../../components/bitsdownload", optional = true } +storage = { path = "../../../../storage/rust" } +bookmark_sync = { path = "../../../components/places/bookmark_sync", optional = true } +chardetng_c = "0.1.1" +audio_thread_priority = { version = "0.26.1", default_features = false, features = ["winapi"] } +mdns_service = { path="../../../../dom/media/webrtc/transport/mdns_service", optional = true } +neqo_glue = { path = "../../../../netwerk/socket/neqo_glue" } +wgpu_bindings = { path = "../../../../gfx/wgpu_bindings" } +mapped_hyph = { git = "https://github.com/jfkthame/mapped_hyph.git", rev = "c7651a0cffff41996ad13c44f689bd9cd2192c01" } +fog_control = { path = "../../../components/glean" } +app_services_logger = { path = "../../../../services/common/app_services_logger" } +http_sfv = { path = "../../../../netwerk/base/http-sfv" } +unic-langid = { version = "0.9", features = ["likelysubtags"] } +unic-langid-ffi = { path = "../../../../intl/locale/rust/unic-langid-ffi" } +fluent-langneg = { version = "0.13", features = ["cldr"] } +fluent-langneg-ffi = { path = "../../../../intl/locale/rust/fluent-langneg-ffi" } +oxilangtag = "0.1.3" +oxilangtag-ffi = { path = "../../../../intl/locale/rust/oxilangtag-ffi" } +rure = "0.2.2" +rust_minidump_writer_linux = { path = "../../../crashreporter/rust_minidump_writer_linux", optional = true } +gecko-profiler = { path = "../../../../tools/profiler/rust-api"} +midir_impl = { path = "../../../../dom/midi/midir_impl", optional = true } +dom = { path = "../../../../dom/base/rust" } +origin-trials-ffi = { path = "../../../../dom/origin-trials/ffi" } +jog = { path = "../../../components/glean/bindings/jog" } +dap_ffi = { path = "../../../components/telemetry/dap/ffi" } +data-encoding-ffi = { path = "../../../../dom/fs/parent/rust/data-encoding-ffi" } +uniffi-example-arithmetic = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de", optional = true } +uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de", optional = true } +uniffi-example-rondpoint = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de", optional = true } +uniffi-example-sprites = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de", optional = true } +uniffi-example-todolist = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de", optional = true } +uniffi-example-custom-types = { path = "../../../components/uniffi-example-custom-types/", optional = true } +uniffi-fixture-callbacks = { path = "../../../components/uniffi-fixture-callbacks/", optional = true } +uniffi-fixture-external-types = { path = "../../../components/uniffi-fixture-external-types/", optional = true } +binary_http = { path = "../../../../netwerk/protocol/http/binary_http" } +oblivious_http = { path = "../../../../netwerk/protocol/http/oblivious_http" } +mime-guess-ffi = { path = "../../../../dom/fs/parent/rust/mime-guess-ffi" } + +# Note: `modern_sqlite` means rusqlite's bindings file be for a sqlite with +# version less than or equal to what we link to. This isn't a problem because we +# tend to keep this up to date, but it needs to be taken into consideration when +# changing this version. +rusqlite = { version = "0.28.0", features = ["modern_sqlite", "in_gecko"] } + +fluent = { version = "0.16.0", features = ["fluent-pseudo"] } +fluent-ffi = { path = "../../../../intl/l10n/rust/fluent-ffi" } +l10nregistry-ffi = { path = "../../../../intl/l10n/rust/l10nregistry-ffi" } +l10nregistry = { path = "../../../../intl/l10n/rust/l10nregistry-rs" } +fluent-fallback = "0.7.0" +localization-ffi = { path = "../../../../intl/l10n/rust/localization-ffi" } + +processtools = { path = "../../../components/processtools" } +qcms = { path = "../../../../gfx/qcms", features = ["c_bindings", "neon"], default-features = false } + +wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "5ab6fe33d00021325ee920b3c10526dc8301cf46" } +aa-stroke = { git = "https://github.com/FirefoxGraphics/aa-stroke", rev = "07d3c25322518f294300e96246e09b95e118555d" } + +# Force url to stay at 2.1.0. See bug 1734538. +url = "=2.1.0" + +# Force mio to stay at 0.8.0 to avoid windows-sys dependencies. +mio = "=0.8.0" + +# Since we're building with at least rustc 1.63, enable rust 1.57 features (use of try_reserve methods). +fallible_collections = { version = "0.4", features = ["rust_1_57"] } + +[target.'cfg(not(target_os = "android"))'.dependencies] +viaduct = "0.1" +webext_storage_bridge = { path = "../../../components/extensions/storage/webext_storage_bridge" } +tabs = { version = "0.1" } + +[target.'cfg(target_os = "windows")'.dependencies] +detect_win32k_conflicts = { path = "../../../xre/detect_win32k_conflicts" } + +[features] +default = [] +moz_memory = ["mozglue-static/moz_memory"] +cubeb-remoting = ["cubeb-sys", "audioipc2-client", "audioipc2-server"] +cubeb_coreaudio_rust = ["cubeb-sys", "cubeb-coreaudio"] +cubeb_pulse_rust = ["cubeb-sys", "cubeb-pulse"] +gecko_debug = ["geckoservo/gecko_debug", "nsstring/gecko_debug"] +gecko_refcount_logging = ["geckoservo/gecko_refcount_logging", "xpcom/gecko_refcount_logging"] +simd-accel = ["encoding_glue/simd-accel", "jsrust_shared/simd-accel"] +moz_places = ["bookmark_sync"] +spidermonkey_rust = [] +smoosh = ["jsrust_shared/smoosh"] +gecko_profiler = ["gecko-profiler/enabled", "profiler_helper"] +gecko_profiler_parse_elf = ["profiler_helper/parse_elf"] +libfuzzer = [] +webrtc = ["mdns_service"] +glean_disable_upload = ["fog_control/disable_upload"] +glean_million_queue = ["fog_control/million_queue"] +glean_with_gecko = ["fog_control/with_gecko", "jog/with_gecko"] +oxidized_breakpad = ["rust_minidump_writer_linux"] +with_dbus = ["audio_thread_priority/with_dbus"] +thread_sanitizer = ["xpcom/thread_sanitizer"] +uniffi_fixtures = [ + "uniffi-example-arithmetic", "uniffi-example-geometry", "uniffi-example-rondpoint", "uniffi-example-sprites", + "uniffi-example-todolist", "uniffi-example-custom-types", "uniffi-fixture-callbacks", + "uniffi-fixture-external-types", +] +webmidi_midir_impl = ["midir_impl"] + +[lib] +path = "lib.rs" +test = false +doctest = false +bench = false +doc = false +plugin = false +harness = false + +[package.metadata.cargo-udeps.ignore] +normal = ["moz_asserts"] diff --git a/toolkit/library/rust/shared/lib.rs b/toolkit/library/rust/shared/lib.rs new file mode 100644 index 0000000000..6ab7e5a0bb --- /dev/null +++ b/toolkit/library/rust/shared/lib.rs @@ -0,0 +1,159 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extern crate geckoservo; + +extern crate app_services_logger; +#[cfg(feature = "cubeb-remoting")] +extern crate audioipc2_client; +#[cfg(feature = "cubeb-remoting")] +extern crate audioipc2_server; +extern crate authrs_bridge; +#[cfg(feature = "bitsdownload")] +extern crate bitsdownload; +#[cfg(feature = "moz_places")] +extern crate bookmark_sync; +extern crate cascade_bloom_filter; +extern crate cert_storage; +extern crate crypto_hash; +extern crate chardetng_c; +extern crate cosec; +#[cfg(feature = "cubeb_coreaudio_rust")] +extern crate cubeb_coreaudio; +#[cfg(feature = "cubeb_pulse_rust")] +extern crate cubeb_pulse; +extern crate encoding_glue; +extern crate fog_control; +extern crate gecko_profiler; +extern crate gkrust_utils; +extern crate http_sfv; +extern crate jog; +extern crate jsrust_shared; +extern crate kvstore; +extern crate mapped_hyph; +extern crate mozurl; +extern crate mp4parse_capi; +extern crate netwerk_helper; +extern crate nserror; +extern crate nsstring; +extern crate prefs_parser; +extern crate processtools; +#[cfg(feature = "gecko_profiler")] +extern crate profiler_helper; +extern crate rsdparsa_capi; +extern crate static_prefs; +extern crate storage; +extern crate webrender_bindings; +extern crate xpcom; + +extern crate audio_thread_priority; + +#[cfg(not(target_os = "android"))] +extern crate webext_storage_bridge; + +#[cfg(not(target_os = "android"))] +extern crate tabs; + +#[cfg(not(target_os = "android"))] +mod reexport_tabs { + tabs::uniffi_reexport_scaffolding!(); +} + +#[cfg(feature = "webrtc")] +extern crate mdns_service; +extern crate neqo_glue; +extern crate wgpu_bindings; + +extern crate aa_stroke; +extern crate qcms; +extern crate wpf_gpu_raster; + +extern crate unic_langid; +extern crate unic_langid_ffi; + +extern crate fluent_langneg; +extern crate fluent_langneg_ffi; + +extern crate fluent; +extern crate fluent_ffi; + +extern crate oxilangtag_ffi; + +extern crate rure; + +extern crate fluent_fallback; +extern crate l10nregistry_ffi; +extern crate localization_ffi; + +#[cfg(not(target_os = "android"))] +extern crate viaduct; + +extern crate gecko_logger; + +#[cfg(feature = "oxidized_breakpad")] +extern crate rust_minidump_writer_linux; + +#[cfg(feature = "webmidi_midir_impl")] +extern crate midir_impl; + +#[cfg(target_os = "windows")] +extern crate detect_win32k_conflicts; + +extern crate origin_trials_ffi; + +extern crate dap_ffi; + +extern crate data_encoding_ffi; + +extern crate binary_http; +extern crate oblivious_http; + +extern crate mime_guess_ffi; + +#[cfg(feature = "uniffi_fixtures")] +mod uniffi_fixtures { + extern crate arithmetical; + extern crate uniffi_geometry; + extern crate uniffi_rondpoint; + extern crate uniffi_sprites; + extern crate uniffi_todolist; + + arithmetical::uniffi_reexport_scaffolding!(); + uniffi_fixture_callbacks::uniffi_reexport_scaffolding!(); + uniffi_custom_types::uniffi_reexport_scaffolding!(); + uniffi_fixture_external_types::uniffi_reexport_scaffolding!(); + uniffi_geometry::uniffi_reexport_scaffolding!(); + uniffi_rondpoint::uniffi_reexport_scaffolding!(); + uniffi_sprites::uniffi_reexport_scaffolding!(); + uniffi_todolist::uniffi_reexport_scaffolding!(); +} + +extern crate log; +use log::info; + +use std::{ffi::CStr, os::raw::c_char}; + +use gecko_logger::GeckoLogger; + +#[no_mangle] +pub extern "C" fn GkRust_Init() { + // Initialize logging. + let _ = GeckoLogger::init(); +} + +#[no_mangle] +pub extern "C" fn GkRust_Shutdown() {} + +/// Used to implement `nsIDebug2::RustPanic` for testing purposes. +#[no_mangle] +pub unsafe extern "C" fn intentional_panic(message: *const c_char) { + panic!("{}", CStr::from_ptr(message).to_string_lossy()); +} + +/// Used to implement `nsIDebug2::rustLog` for testing purposes. +#[no_mangle] +pub unsafe extern "C" fn debug_log(target: *const c_char, message: *const c_char) { + // NOTE: The `info!` log macro is used here because we have the `release_max_level_info` feature set. + info!(target: CStr::from_ptr(target).to_str().unwrap(), "{}", CStr::from_ptr(message).to_str().unwrap()); +} diff --git a/toolkit/library/symverscript.in b/toolkit/library/symverscript.in new file mode 100644 index 0000000000..ef70826ad4 --- /dev/null +++ b/toolkit/library/symverscript.in @@ -0,0 +1,4 @@ +#filter substitution +@VERSION@ { + global: *; +}; diff --git a/toolkit/library/xulrunner.rc b/toolkit/library/xulrunner.rc new file mode 100644 index 0000000000..0158f6cbfc --- /dev/null +++ b/toolkit/library/xulrunner.rc @@ -0,0 +1,6 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla-config.h" +#include "widget.rc" |